diff options
| -rw-r--r-- | meta-moblin/packages/linux/linux-moblin-2.6.28+2.6.29-rc2/psb-driver.patch | 2711 |
1 files changed, 714 insertions, 1997 deletions
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.28+2.6.29-rc2/psb-driver.patch b/meta-moblin/packages/linux/linux-moblin-2.6.28+2.6.29-rc2/psb-driver.patch index c515bc60ce..ca449c6cf5 100644 --- a/meta-moblin/packages/linux/linux-moblin-2.6.28+2.6.29-rc2/psb-driver.patch +++ b/meta-moblin/packages/linux/linux-moblin-2.6.28+2.6.29-rc2/psb-driver.patch | |||
| @@ -337,7 +337,7 @@ Index: linux-2.6.28/include/drm/drm.h | |||
| 337 | Index: linux-2.6.28/include/drm/drmP.h | 337 | Index: linux-2.6.28/include/drm/drmP.h |
| 338 | =================================================================== | 338 | =================================================================== |
| 339 | --- linux-2.6.28.orig/include/drm/drmP.h 2009-02-12 09:14:40.000000000 +0000 | 339 | --- linux-2.6.28.orig/include/drm/drmP.h 2009-02-12 09:14:40.000000000 +0000 |
| 340 | +++ linux-2.6.28/include/drm/drmP.h 2009-02-12 09:14:41.000000000 +0000 | 340 | +++ linux-2.6.28/include/drm/drmP.h 2009-02-12 15:59:51.000000000 +0000 |
| 341 | @@ -57,6 +57,7 @@ | 341 | @@ -57,6 +57,7 @@ |
| 342 | #include <linux/dma-mapping.h> | 342 | #include <linux/dma-mapping.h> |
| 343 | #include <linux/mm.h> | 343 | #include <linux/mm.h> |
| @@ -638,16 +638,6 @@ Index: linux-2.6.28/include/drm/drmP.h | |||
| 638 | 638 | ||
| 639 | /* AGP/GART support (drm_agpsupport.h) */ | 639 | /* AGP/GART support (drm_agpsupport.h) */ |
| 640 | extern struct drm_agp_head *drm_agp_init(struct drm_device *dev); | 640 | extern struct drm_agp_head *drm_agp_init(struct drm_device *dev); |
| 641 | @@ -1303,9 +1340,6 @@ | ||
| 642 | extern int drm_sysfs_device_add(struct drm_minor *minor); | ||
| 643 | extern void drm_sysfs_hotplug_event(struct drm_device *dev); | ||
| 644 | extern void drm_sysfs_device_remove(struct drm_minor *minor); | ||
| 645 | -extern char *drm_get_connector_status_name(enum drm_connector_status status); | ||
| 646 | -extern int drm_sysfs_connector_add(struct drm_connector *connector); | ||
| 647 | -extern void drm_sysfs_connector_remove(struct drm_connector *connector); | ||
| 648 | |||
| 649 | /* | ||
| 650 | * Basic memory manager support (drm_mm.c) | ||
| 651 | Index: linux-2.6.28/include/drm/drm_pciids.h | 641 | Index: linux-2.6.28/include/drm/drm_pciids.h |
| 652 | =================================================================== | 642 | =================================================================== |
| 653 | --- linux-2.6.28.orig/include/drm/drm_pciids.h 2009-02-12 09:14:31.000000000 +0000 | 643 | --- linux-2.6.28.orig/include/drm/drm_pciids.h 2009-02-12 09:14:31.000000000 +0000 |
| @@ -665,8 +655,8 @@ Index: linux-2.6.28/include/drm/drm_pciids.h | |||
| 665 | Index: linux-2.6.28/drivers/gpu/drm/Makefile | 655 | Index: linux-2.6.28/drivers/gpu/drm/Makefile |
| 666 | =================================================================== | 656 | =================================================================== |
| 667 | --- linux-2.6.28.orig/drivers/gpu/drm/Makefile 2009-02-12 09:14:37.000000000 +0000 | 657 | --- linux-2.6.28.orig/drivers/gpu/drm/Makefile 2009-02-12 09:14:37.000000000 +0000 |
| 668 | +++ linux-2.6.28/drivers/gpu/drm/Makefile 2009-02-12 09:14:41.000000000 +0000 | 658 | +++ linux-2.6.28/drivers/gpu/drm/Makefile 2009-02-12 16:00:51.000000000 +0000 |
| 669 | @@ -10,8 +10,11 @@ | 659 | @@ -10,6 +10,8 @@ |
| 670 | drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ | 660 | drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ |
| 671 | drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ | 661 | drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ |
| 672 | drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \ | 662 | drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \ |
| @@ -674,11 +664,8 @@ Index: linux-2.6.28/drivers/gpu/drm/Makefile | |||
| 674 | + drm_bo_lock.o drm_bo_move.o drm_regman.o \ | 664 | + drm_bo_lock.o drm_bo_move.o drm_regman.o \ |
| 675 | drm_crtc.o drm_crtc_helper.o drm_modes.o drm_edid.o | 665 | drm_crtc.o drm_crtc_helper.o drm_modes.o drm_edid.o |
| 676 | 666 | ||
| 677 | + | ||
| 678 | drm-$(CONFIG_COMPAT) += drm_ioc32.o | 667 | drm-$(CONFIG_COMPAT) += drm_ioc32.o |
| 679 | 668 | @@ -22,6 +24,7 @@ | |
| 680 | obj-$(CONFIG_DRM) += drm.o | ||
| 681 | @@ -22,6 +25,7 @@ | ||
| 682 | obj-$(CONFIG_DRM_I810) += i810/ | 669 | obj-$(CONFIG_DRM_I810) += i810/ |
| 683 | obj-$(CONFIG_DRM_I830) += i830/ | 670 | obj-$(CONFIG_DRM_I830) += i830/ |
| 684 | obj-$(CONFIG_DRM_I915) += i915/ | 671 | obj-$(CONFIG_DRM_I915) += i915/ |
| @@ -7239,1908 +7226,6 @@ Index: linux-2.6.28/drivers/gpu/drm/psb/Makefile | |||
| 7239 | + psb_schedule.o psb_xhw.o | 7226 | + psb_schedule.o psb_xhw.o |
| 7240 | + | 7227 | + |
| 7241 | +obj-$(CONFIG_DRM_PSB) += psb.o | 7228 | +obj-$(CONFIG_DRM_PSB) += psb.o |
| 7242 | Index: linux-2.6.28/drivers/gpu/drm/psb/i915_reg.h | ||
| 7243 | =================================================================== | ||
| 7244 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | ||
| 7245 | +++ linux-2.6.28/drivers/gpu/drm/psb/i915_reg.h 2009-02-12 09:14:41.000000000 +0000 | ||
| 7246 | @@ -0,0 +1,67 @@ | ||
| 7247 | +#include "../i915/i915_reg.h" | ||
| 7248 | + | ||
| 7249 | + | ||
| 7250 | +/*#define IS_I830(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82830_CGC) | ||
| 7251 | +#define IS_845G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82845G_IG) | ||
| 7252 | +#define IS_I85X(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82855GM_IG) | ||
| 7253 | +#define IS_I855(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82855GM_IG) | ||
| 7254 | +#define IS_I865G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82865_IG) | ||
| 7255 | + | ||
| 7256 | +#define IS_I915G(dev) (dev->pci_device == PCI_DEVICE_ID_INTEL_82915G_IG) | ||
| 7257 | +#define IS_I915GM(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82915GM_IG) | ||
| 7258 | +#define IS_I945G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82945G_IG) | ||
| 7259 | +#define IS_I945GM(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82945GM_IG) | ||
| 7260 | + | ||
| 7261 | +#define IS_I965G(dev) ((dev)->pci_device == 0x2972 || \ | ||
| 7262 | + (dev)->pci_device == 0x2982 || \ | ||
| 7263 | + (dev)->pci_device == 0x2992 || \ | ||
| 7264 | + (dev)->pci_device == 0x29A2 || \ | ||
| 7265 | + (dev)->pci_device == 0x2A02 || \ | ||
| 7266 | + (dev)->pci_device == 0x2A12) | ||
| 7267 | + | ||
| 7268 | +#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02) | ||
| 7269 | + | ||
| 7270 | +#define IS_G33(dev) ((dev)->pci_device == 0x29C2 || \ | ||
| 7271 | + (dev)->pci_device == 0x29B2 || \ | ||
| 7272 | + (dev)->pci_device == 0x29D2) | ||
| 7273 | + | ||
| 7274 | +#define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \ | ||
| 7275 | + IS_I945GM(dev) || IS_I965G(dev) || IS_POULSBO(dev)) | ||
| 7276 | + | ||
| 7277 | +#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \ | ||
| 7278 | + IS_I945GM(dev) || IS_I965GM(dev) || IS_POULSBO(dev)) | ||
| 7279 | + | ||
| 7280 | +#define IS_POULSBO(dev) (((dev)->pci_device == 0x8108) || \ | ||
| 7281 | + ((dev)->pci_device == 0x8109))*/ | ||
| 7282 | + | ||
| 7283 | +#define FPA0 0x06040 | ||
| 7284 | +#define FPA1 0x06044 | ||
| 7285 | +#define FPB0 0x06048 | ||
| 7286 | +#define FPB1 0x0604c | ||
| 7287 | +#define FP_N_DIV_MASK 0x003f0000 | ||
| 7288 | +#define FP_N_DIV_SHIFT 16 | ||
| 7289 | +#define FP_M1_DIV_MASK 0x00003f00 | ||
| 7290 | +#define FP_M1_DIV_SHIFT 8 | ||
| 7291 | +#define FP_M2_DIV_MASK 0x0000003f | ||
| 7292 | +#define FP_M2_DIV_SHIFT 0 | ||
| 7293 | + | ||
| 7294 | +#define DPLL_B_MD 0x06020 | ||
| 7295 | + | ||
| 7296 | +#define ADPA 0x61100 | ||
| 7297 | +#define ADPA_DAC_ENABLE (1<<31) | ||
| 7298 | +#define ADPA_DAC_DISABLE 0 | ||
| 7299 | +#define ADPA_PIPE_SELECT_MASK (1<<30) | ||
| 7300 | +#define ADPA_PIPE_A_SELECT 0 | ||
| 7301 | +#define ADPA_PIPE_B_SELECT (1<<30) | ||
| 7302 | +#define ADPA_USE_VGA_HVPOLARITY (1<<15) | ||
| 7303 | +#define ADPA_SETS_HVPOLARITY 0 | ||
| 7304 | +#define ADPA_VSYNC_CNTL_DISABLE (1<<11) | ||
| 7305 | +#define ADPA_VSYNC_CNTL_ENABLE 0 | ||
| 7306 | +#define ADPA_HSYNC_CNTL_DISABLE (1<<10) | ||
| 7307 | +#define ADPA_HSYNC_CNTL_ENABLE 0 | ||
| 7308 | +#define ADPA_VSYNC_ACTIVE_HIGH (1<<4) | ||
| 7309 | +#define ADPA_VSYNC_ACTIVE_LOW 0 | ||
| 7310 | +#define ADPA_HSYNC_ACTIVE_HIGH (1<<3) | ||
| 7311 | +#define ADPA_HSYNC_ACTIVE_LOW 0 | ||
| 7312 | + | ||
| 7313 | + | ||
| 7314 | Index: linux-2.6.28/drivers/gpu/drm/psb/intel_display.c | ||
| 7315 | =================================================================== | ||
| 7316 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | ||
| 7317 | +++ linux-2.6.28/drivers/gpu/drm/psb/intel_display.c 2009-02-12 09:14:41.000000000 +0000 | ||
| 7318 | @@ -0,0 +1,1813 @@ | ||
| 7319 | +/* | ||
| 7320 | + * Copyright © 2006-2007 Intel Corporation | ||
| 7321 | + * | ||
| 7322 | + * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7323 | + * copy of this software and associated documentation files (the "Software"), | ||
| 7324 | + * to deal in the Software without restriction, including without limitation | ||
| 7325 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 7326 | + * and/or sell copies of the Software, and to permit persons to whom the | ||
| 7327 | + * Software is furnished to do so, subject to the following conditions: | ||
| 7328 | + * | ||
| 7329 | + * The above copyright notice and this permission notice (including the next | ||
| 7330 | + * paragraph) shall be included in all copies or substantial portions of the | ||
| 7331 | + * Software. | ||
| 7332 | + * | ||
| 7333 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 7334 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 7335 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 7336 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 7337 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| 7338 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 7339 | + * DEALINGS IN THE SOFTWARE. | ||
| 7340 | + * | ||
| 7341 | + * Authors: | ||
| 7342 | + * Eric Anholt <eric@anholt.net> | ||
| 7343 | + */ | ||
| 7344 | + | ||
| 7345 | +#include <linux/i2c.h> | ||
| 7346 | +#include "drmP.h" | ||
| 7347 | +#include "../i915/intel_drv.h" | ||
| 7348 | +#include "i915_drm.h" | ||
| 7349 | +#include "../i915/i915_drv.h" | ||
| 7350 | + | ||
| 7351 | +#include "drm_crtc_helper.h" | ||
| 7352 | + | ||
| 7353 | +bool intel_pipe_has_type (struct drm_crtc *crtc, int type); | ||
| 7354 | + | ||
| 7355 | +typedef struct { | ||
| 7356 | + /* given values */ | ||
| 7357 | + int n; | ||
| 7358 | + int m1, m2; | ||
| 7359 | + int p1, p2; | ||
| 7360 | + /* derived values */ | ||
| 7361 | + int dot; | ||
| 7362 | + int vco; | ||
| 7363 | + int m; | ||
| 7364 | + int p; | ||
| 7365 | +} intel_clock_t; | ||
| 7366 | + | ||
| 7367 | +typedef struct { | ||
| 7368 | + int min, max; | ||
| 7369 | +} intel_range_t; | ||
| 7370 | + | ||
| 7371 | +typedef struct { | ||
| 7372 | + int dot_limit; | ||
| 7373 | + int p2_slow, p2_fast; | ||
| 7374 | +} intel_p2_t; | ||
| 7375 | + | ||
| 7376 | +#define INTEL_P2_NUM 2 | ||
| 7377 | + | ||
| 7378 | +typedef struct { | ||
| 7379 | + intel_range_t dot, vco, n, m, m1, m2, p, p1; | ||
| 7380 | + intel_p2_t p2; | ||
| 7381 | +} intel_limit_t; | ||
| 7382 | + | ||
| 7383 | +#define I8XX_DOT_MIN 25000 | ||
| 7384 | +#define I8XX_DOT_MAX 350000 | ||
| 7385 | +#define I8XX_VCO_MIN 930000 | ||
| 7386 | +#define I8XX_VCO_MAX 1400000 | ||
| 7387 | +#define I8XX_N_MIN 3 | ||
| 7388 | +#define I8XX_N_MAX 16 | ||
| 7389 | +#define I8XX_M_MIN 96 | ||
| 7390 | +#define I8XX_M_MAX 140 | ||
| 7391 | +#define I8XX_M1_MIN 18 | ||
| 7392 | +#define I8XX_M1_MAX 26 | ||
| 7393 | +#define I8XX_M2_MIN 6 | ||
| 7394 | +#define I8XX_M2_MAX 16 | ||
| 7395 | +#define I8XX_P_MIN 4 | ||
| 7396 | +#define I8XX_P_MAX 128 | ||
| 7397 | +#define I8XX_P1_MIN 2 | ||
| 7398 | +#define I8XX_P1_MAX 33 | ||
| 7399 | +#define I8XX_P1_LVDS_MIN 1 | ||
| 7400 | +#define I8XX_P1_LVDS_MAX 6 | ||
| 7401 | +#define I8XX_P2_SLOW 4 | ||
| 7402 | +#define I8XX_P2_FAST 2 | ||
| 7403 | +#define I8XX_P2_LVDS_SLOW 14 | ||
| 7404 | +#define I8XX_P2_LVDS_FAST 14 /* No fast option */ | ||
| 7405 | +#define I8XX_P2_SLOW_LIMIT 165000 | ||
| 7406 | + | ||
| 7407 | +#define I9XX_DOT_MIN 20000 | ||
| 7408 | +#define I9XX_DOT_MAX 400000 | ||
| 7409 | +#define I9XX_VCO_MIN 1400000 | ||
| 7410 | +#define I9XX_VCO_MAX 2800000 | ||
| 7411 | +#define I9XX_N_MIN 3 | ||
| 7412 | +#define I9XX_N_MAX 8 | ||
| 7413 | +#define I9XX_M_MIN 70 | ||
| 7414 | +#define I9XX_M_MAX 120 | ||
| 7415 | +#define I9XX_M1_MIN 10 | ||
| 7416 | +#define I9XX_M1_MAX 20 | ||
| 7417 | +#define I9XX_M2_MIN 5 | ||
| 7418 | +#define I9XX_M2_MAX 9 | ||
| 7419 | +#define I9XX_P_SDVO_DAC_MIN 5 | ||
| 7420 | +#define I9XX_P_SDVO_DAC_MAX 80 | ||
| 7421 | +#define I9XX_P_LVDS_MIN 7 | ||
| 7422 | +#define I9XX_P_LVDS_MAX 98 | ||
| 7423 | +#define I9XX_P1_MIN 1 | ||
| 7424 | +#define I9XX_P1_MAX 8 | ||
| 7425 | +#define I9XX_P2_SDVO_DAC_SLOW 10 | ||
| 7426 | +#define I9XX_P2_SDVO_DAC_FAST 5 | ||
| 7427 | +#define I9XX_P2_SDVO_DAC_SLOW_LIMIT 200000 | ||
| 7428 | +#define I9XX_P2_LVDS_SLOW 14 | ||
| 7429 | +#define I9XX_P2_LVDS_FAST 7 | ||
| 7430 | +#define I9XX_P2_LVDS_SLOW_LIMIT 112000 | ||
| 7431 | + | ||
| 7432 | +#define INTEL_LIMIT_I8XX_DVO_DAC 0 | ||
| 7433 | +#define INTEL_LIMIT_I8XX_LVDS 1 | ||
| 7434 | +#define INTEL_LIMIT_I9XX_SDVO_DAC 2 | ||
| 7435 | +#define INTEL_LIMIT_I9XX_LVDS 3 | ||
| 7436 | + | ||
| 7437 | +static const intel_limit_t intel_limits[] = { | ||
| 7438 | + { /* INTEL_LIMIT_I8XX_DVO_DAC */ | ||
| 7439 | + .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, | ||
| 7440 | + .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, | ||
| 7441 | + .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, | ||
| 7442 | + .m = { .min = I8XX_M_MIN, .max = I8XX_M_MAX }, | ||
| 7443 | + .m1 = { .min = I8XX_M1_MIN, .max = I8XX_M1_MAX }, | ||
| 7444 | + .m2 = { .min = I8XX_M2_MIN, .max = I8XX_M2_MAX }, | ||
| 7445 | + .p = { .min = I8XX_P_MIN, .max = I8XX_P_MAX }, | ||
| 7446 | + .p1 = { .min = I8XX_P1_MIN, .max = I8XX_P1_MAX }, | ||
| 7447 | + .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, | ||
| 7448 | + .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, | ||
| 7449 | + }, | ||
| 7450 | + { /* INTEL_LIMIT_I8XX_LVDS */ | ||
| 7451 | + .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, | ||
| 7452 | + .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, | ||
| 7453 | + .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, | ||
| 7454 | + .m = { .min = I8XX_M_MIN, .max = I8XX_M_MAX }, | ||
| 7455 | + .m1 = { .min = I8XX_M1_MIN, .max = I8XX_M1_MAX }, | ||
| 7456 | + .m2 = { .min = I8XX_M2_MIN, .max = I8XX_M2_MAX }, | ||
| 7457 | + .p = { .min = I8XX_P_MIN, .max = I8XX_P_MAX }, | ||
| 7458 | + .p1 = { .min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX }, | ||
| 7459 | + .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, | ||
| 7460 | + .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, | ||
| 7461 | + }, | ||
| 7462 | + { /* INTEL_LIMIT_I9XX_SDVO_DAC */ | ||
| 7463 | + .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, | ||
| 7464 | + .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, | ||
| 7465 | + .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, | ||
| 7466 | + .m = { .min = I9XX_M_MIN, .max = I9XX_M_MAX }, | ||
| 7467 | + .m1 = { .min = I9XX_M1_MIN, .max = I9XX_M1_MAX }, | ||
| 7468 | + .m2 = { .min = I9XX_M2_MIN, .max = I9XX_M2_MAX }, | ||
| 7469 | + .p = { .min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX }, | ||
| 7470 | + .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX }, | ||
| 7471 | + .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, | ||
| 7472 | + .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, | ||
| 7473 | + }, | ||
| 7474 | + { /* INTEL_LIMIT_I9XX_LVDS */ | ||
| 7475 | + .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, | ||
| 7476 | + .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, | ||
| 7477 | + .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, | ||
| 7478 | + .m = { .min = I9XX_M_MIN, .max = I9XX_M_MAX }, | ||
| 7479 | + .m1 = { .min = I9XX_M1_MIN, .max = I9XX_M1_MAX }, | ||
| 7480 | + .m2 = { .min = I9XX_M2_MIN, .max = I9XX_M2_MAX }, | ||
| 7481 | + .p = { .min = I9XX_P_LVDS_MIN, .max = I9XX_P_LVDS_MAX }, | ||
| 7482 | + .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX }, | ||
| 7483 | + /* The single-channel range is 25-112Mhz, and dual-channel | ||
| 7484 | + * is 80-224Mhz. Prefer single channel as much as possible. | ||
| 7485 | + */ | ||
| 7486 | + .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, | ||
| 7487 | + .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, | ||
| 7488 | + }, | ||
| 7489 | +}; | ||
| 7490 | + | ||
| 7491 | +static const intel_limit_t *intel_limit(struct drm_crtc *crtc) | ||
| 7492 | +{ | ||
| 7493 | + struct drm_device *dev = crtc->dev; | ||
| 7494 | + const intel_limit_t *limit; | ||
| 7495 | + | ||
| 7496 | + if (IS_I9XX(dev)) { | ||
| 7497 | + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | ||
| 7498 | + limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS]; | ||
| 7499 | + else | ||
| 7500 | + limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; | ||
| 7501 | + } else { | ||
| 7502 | + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | ||
| 7503 | + limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS]; | ||
| 7504 | + else | ||
| 7505 | + limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC]; | ||
| 7506 | + } | ||
| 7507 | + return limit; | ||
| 7508 | +} | ||
| 7509 | + | ||
| 7510 | +/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ | ||
| 7511 | + | ||
| 7512 | +static void i8xx_clock(int refclk, intel_clock_t *clock) | ||
| 7513 | +{ | ||
| 7514 | + clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); | ||
| 7515 | + clock->p = clock->p1 * clock->p2; | ||
| 7516 | + clock->vco = refclk * clock->m / (clock->n + 2); | ||
| 7517 | + clock->dot = clock->vco / clock->p; | ||
| 7518 | +} | ||
| 7519 | + | ||
| 7520 | +/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */ | ||
| 7521 | + | ||
| 7522 | +static void i9xx_clock(int refclk, intel_clock_t *clock) | ||
| 7523 | +{ | ||
| 7524 | + clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); | ||
| 7525 | + clock->p = clock->p1 * clock->p2; | ||
| 7526 | + clock->vco = refclk * clock->m / (clock->n + 2); | ||
| 7527 | + clock->dot = clock->vco / clock->p; | ||
| 7528 | +} | ||
| 7529 | + | ||
| 7530 | +static void intel_clock(struct drm_device *dev, int refclk, | ||
| 7531 | + intel_clock_t *clock) | ||
| 7532 | +{ | ||
| 7533 | + if (IS_I9XX(dev)) | ||
| 7534 | + i9xx_clock (refclk, clock); | ||
| 7535 | + else | ||
| 7536 | + i8xx_clock (refclk, clock); | ||
| 7537 | +} | ||
| 7538 | + | ||
| 7539 | +/** | ||
| 7540 | + * Returns whether any output on the specified pipe is of the specified type | ||
| 7541 | + */ | ||
| 7542 | +bool intel_pipe_has_type (struct drm_crtc *crtc, int type) | ||
| 7543 | +{ | ||
| 7544 | + struct drm_device *dev = crtc->dev; | ||
| 7545 | + struct drm_mode_config *mode_config = &dev->mode_config; | ||
| 7546 | + struct drm_connector *l_entry; | ||
| 7547 | + | ||
| 7548 | + list_for_each_entry(l_entry, &mode_config->connector_list, head) { | ||
| 7549 | + if (l_entry->encoder && | ||
| 7550 | + l_entry->encoder->crtc == crtc) { | ||
| 7551 | + struct intel_output *intel_output = to_intel_output(l_entry); | ||
| 7552 | + if (intel_output->type == type) | ||
| 7553 | + return true; | ||
| 7554 | + } | ||
| 7555 | + } | ||
| 7556 | + return false; | ||
| 7557 | +} | ||
| 7558 | + | ||
| 7559 | +#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; } | ||
| 7560 | +/** | ||
| 7561 | + * Returns whether the given set of divisors are valid for a given refclk with | ||
| 7562 | + * the given connectors. | ||
| 7563 | + */ | ||
| 7564 | + | ||
| 7565 | +static bool intel_PLL_is_valid(struct drm_crtc *crtc, intel_clock_t *clock) | ||
| 7566 | +{ | ||
| 7567 | + const intel_limit_t *limit = intel_limit (crtc); | ||
| 7568 | + | ||
| 7569 | + if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) | ||
| 7570 | + INTELPllInvalid ("p1 out of range\n"); | ||
| 7571 | + if (clock->p < limit->p.min || limit->p.max < clock->p) | ||
| 7572 | + INTELPllInvalid ("p out of range\n"); | ||
| 7573 | + if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2) | ||
| 7574 | + INTELPllInvalid ("m2 out of range\n"); | ||
| 7575 | + if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) | ||
| 7576 | + INTELPllInvalid ("m1 out of range\n"); | ||
| 7577 | + if (clock->m1 <= clock->m2) | ||
| 7578 | + INTELPllInvalid ("m1 <= m2\n"); | ||
| 7579 | + if (clock->m < limit->m.min || limit->m.max < clock->m) | ||
| 7580 | + INTELPllInvalid ("m out of range\n"); | ||
| 7581 | + if (clock->n < limit->n.min || limit->n.max < clock->n) | ||
| 7582 | + INTELPllInvalid ("n out of range\n"); | ||
| 7583 | + if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) | ||
| 7584 | + INTELPllInvalid ("vco out of range\n"); | ||
| 7585 | + /* XXX: We may need to be checking "Dot clock" depending on the multiplier, | ||
| 7586 | + * connector, etc., rather than just a single range. | ||
| 7587 | + */ | ||
| 7588 | + if (clock->dot < limit->dot.min || limit->dot.max < clock->dot) | ||
| 7589 | + INTELPllInvalid ("dot out of range\n"); | ||
| 7590 | + | ||
| 7591 | + return true; | ||
| 7592 | +} | ||
| 7593 | + | ||
| 7594 | +/** | ||
| 7595 | + * Returns a set of divisors for the desired target clock with the given | ||
| 7596 | + * refclk, or FALSE. The returned values represent the clock equation: | ||
| 7597 | + * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. | ||
| 7598 | + */ | ||
| 7599 | +static bool intel_find_best_PLL(struct drm_crtc *crtc, int target, | ||
| 7600 | + int refclk, intel_clock_t *best_clock) | ||
| 7601 | +{ | ||
| 7602 | + struct drm_device *dev = crtc->dev; | ||
| 7603 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 7604 | + intel_clock_t clock; | ||
| 7605 | + const intel_limit_t *limit = intel_limit(crtc); | ||
| 7606 | + int err = target; | ||
| 7607 | + | ||
| 7608 | + if (IS_I9XX(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && | ||
| 7609 | + (I915_READ(LVDS) & LVDS_PORT_EN) != 0) { | ||
| 7610 | + /* | ||
| 7611 | + * For LVDS, if the panel is on, just rely on its current | ||
| 7612 | + * settings for dual-channel. We haven't figured out how to | ||
| 7613 | + * reliably set up different single/dual channel state, if we | ||
| 7614 | + * even can. | ||
| 7615 | + */ | ||
| 7616 | + if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == | ||
| 7617 | + LVDS_CLKB_POWER_UP) | ||
| 7618 | + clock.p2 = limit->p2.p2_fast; | ||
| 7619 | + else | ||
| 7620 | + clock.p2 = limit->p2.p2_slow; | ||
| 7621 | + } else { | ||
| 7622 | + if (target < limit->p2.dot_limit) | ||
| 7623 | + clock.p2 = limit->p2.p2_slow; | ||
| 7624 | + else | ||
| 7625 | + clock.p2 = limit->p2.p2_fast; | ||
| 7626 | + } | ||
| 7627 | + | ||
| 7628 | + memset (best_clock, 0, sizeof (*best_clock)); | ||
| 7629 | + | ||
| 7630 | + for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) { | ||
| 7631 | + for (clock.m2 = limit->m2.min; clock.m2 < clock.m1 && | ||
| 7632 | + clock.m2 <= limit->m2.max; clock.m2++) { | ||
| 7633 | + for (clock.n = limit->n.min; clock.n <= limit->n.max; | ||
| 7634 | + clock.n++) { | ||
| 7635 | + for (clock.p1 = limit->p1.min; | ||
| 7636 | + clock.p1 <= limit->p1.max; clock.p1++) { | ||
| 7637 | + int this_err; | ||
| 7638 | + | ||
| 7639 | + intel_clock(dev, refclk, &clock); | ||
| 7640 | + | ||
| 7641 | + if (!intel_PLL_is_valid(crtc, &clock)) | ||
| 7642 | + continue; | ||
| 7643 | + | ||
| 7644 | + this_err = abs(clock.dot - target); | ||
| 7645 | + if (this_err < err) { | ||
| 7646 | + *best_clock = clock; | ||
| 7647 | + err = this_err; | ||
| 7648 | + } | ||
| 7649 | + } | ||
| 7650 | + } | ||
| 7651 | + } | ||
| 7652 | + } | ||
| 7653 | + | ||
| 7654 | + return (err != target); | ||
| 7655 | +} | ||
| 7656 | + | ||
| 7657 | +void | ||
| 7658 | +intel_wait_for_vblank(struct drm_device *dev) | ||
| 7659 | +{ | ||
| 7660 | + /* Wait for 20ms, i.e. one cycle at 50hz. */ | ||
| 7661 | + udelay(20000); | ||
| 7662 | +} | ||
| 7663 | + | ||
| 7664 | +static void | ||
| 7665 | +intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | ||
| 7666 | + struct drm_framebuffer *old_fb) | ||
| 7667 | +{ | ||
| 7668 | + struct drm_device *dev = crtc->dev; | ||
| 7669 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 7670 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 7671 | + int pipe = intel_crtc->pipe; | ||
| 7672 | + unsigned long Start, Offset; | ||
| 7673 | + int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR); | ||
| 7674 | + int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); | ||
| 7675 | + int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; | ||
| 7676 | + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | ||
| 7677 | + u32 dspcntr, alignment; | ||
| 7678 | + | ||
| 7679 | + Start = crtc->fb->offset; | ||
| 7680 | + Offset = y * crtc->fb->pitch + x; | ||
| 7681 | + | ||
| 7682 | + DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); | ||
| 7683 | + if (IS_I965G(dev)) { | ||
| 7684 | + I915_WRITE(dspbase, Offset); | ||
| 7685 | + I915_READ(dspbase); | ||
| 7686 | + I915_WRITE(dspsurf, Start); | ||
| 7687 | + I915_READ(dspsurf); | ||
| 7688 | + } else { | ||
| 7689 | + I915_WRITE(dspbase, Start + Offset); | ||
| 7690 | + I915_READ(dspbase); | ||
| 7691 | + } | ||
| 7692 | + | ||
| 7693 | + | ||
| 7694 | + if (!dev_priv->sarea_priv) | ||
| 7695 | + return; | ||
| 7696 | + | ||
| 7697 | + switch (pipe) { | ||
| 7698 | + case 0: | ||
| 7699 | + dev_priv->sarea_priv->pipeA_x = x; | ||
| 7700 | + dev_priv->sarea_priv->pipeA_y = y; | ||
| 7701 | + break; | ||
| 7702 | + case 1: | ||
| 7703 | + dev_priv->sarea_priv->pipeB_x = x; | ||
| 7704 | + dev_priv->sarea_priv->pipeB_y = y; | ||
| 7705 | + break; | ||
| 7706 | + default: | ||
| 7707 | + DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); | ||
| 7708 | + break; | ||
| 7709 | + } | ||
| 7710 | +} | ||
| 7711 | + | ||
| 7712 | + | ||
| 7713 | + | ||
| 7714 | +/** | ||
| 7715 | + * Sets the power management mode of the pipe and plane. | ||
| 7716 | + * | ||
| 7717 | + * This code should probably grow support for turning the cursor off and back | ||
| 7718 | + * on appropriately at the same time as we're turning the pipe off/on. | ||
| 7719 | + */ | ||
| 7720 | +static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) | ||
| 7721 | +{ | ||
| 7722 | + struct drm_device *dev = crtc->dev; | ||
| 7723 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 7724 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 7725 | + int pipe = intel_crtc->pipe; | ||
| 7726 | + int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; | ||
| 7727 | + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | ||
| 7728 | + int dspbase_reg = (pipe == 0) ? DSPAADDR : DSPBADDR; | ||
| 7729 | + int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | ||
| 7730 | + u32 temp; | ||
| 7731 | + bool enabled; | ||
| 7732 | + | ||
| 7733 | + /* XXX: When our outputs are all unaware of DPMS modes other than off | ||
| 7734 | + * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. | ||
| 7735 | + */ | ||
| 7736 | + switch (mode) { | ||
| 7737 | + case DRM_MODE_DPMS_ON: | ||
| 7738 | + case DRM_MODE_DPMS_STANDBY: | ||
| 7739 | + case DRM_MODE_DPMS_SUSPEND: | ||
| 7740 | + /* Enable the DPLL */ | ||
| 7741 | + temp = I915_READ(dpll_reg); | ||
| 7742 | + if ((temp & DPLL_VCO_ENABLE) == 0) { | ||
| 7743 | + I915_WRITE(dpll_reg, temp); | ||
| 7744 | + I915_READ(dpll_reg); | ||
| 7745 | + /* Wait for the clocks to stabilize. */ | ||
| 7746 | + udelay(150); | ||
| 7747 | + I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); | ||
| 7748 | + I915_READ(dpll_reg); | ||
| 7749 | + /* Wait for the clocks to stabilize. */ | ||
| 7750 | + udelay(150); | ||
| 7751 | + I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); | ||
| 7752 | + I915_READ(dpll_reg); | ||
| 7753 | + /* Wait for the clocks to stabilize. */ | ||
| 7754 | + udelay(150); | ||
| 7755 | + } | ||
| 7756 | + | ||
| 7757 | + /* Enable the pipe */ | ||
| 7758 | + temp = I915_READ(pipeconf_reg); | ||
| 7759 | + if ((temp & PIPEACONF_ENABLE) == 0) | ||
| 7760 | + I915_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); | ||
| 7761 | + | ||
| 7762 | + /* Enable the plane */ | ||
| 7763 | + temp = I915_READ(dspcntr_reg); | ||
| 7764 | + if ((temp & DISPLAY_PLANE_ENABLE) == 0) { | ||
| 7765 | + I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); | ||
| 7766 | + /* Flush the plane changes */ | ||
| 7767 | + I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); | ||
| 7768 | + } | ||
| 7769 | + | ||
| 7770 | + intel_crtc_load_lut(crtc); | ||
| 7771 | + | ||
| 7772 | + /* Give the overlay scaler a chance to enable if it's on this pipe */ | ||
| 7773 | + //intel_crtc_dpms_video(crtc, true); TODO | ||
| 7774 | + break; | ||
| 7775 | + case DRM_MODE_DPMS_OFF: | ||
| 7776 | + /* Give the overlay scaler a chance to disable if it's on this pipe */ | ||
| 7777 | + //intel_crtc_dpms_video(crtc, FALSE); TODO | ||
| 7778 | + | ||
| 7779 | + /* Disable the VGA plane that we never use */ | ||
| 7780 | + I915_WRITE(VGACNTRL, VGA_DISP_DISABLE); | ||
| 7781 | + | ||
| 7782 | + /* Disable display plane */ | ||
| 7783 | + temp = I915_READ(dspcntr_reg); | ||
| 7784 | + if ((temp & DISPLAY_PLANE_ENABLE) != 0) { | ||
| 7785 | + I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); | ||
| 7786 | + /* Flush the plane changes */ | ||
| 7787 | + I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); | ||
| 7788 | + I915_READ(dspbase_reg); | ||
| 7789 | + } | ||
| 7790 | + | ||
| 7791 | + if (!IS_I9XX(dev)) { | ||
| 7792 | + /* Wait for vblank for the disable to take effect */ | ||
| 7793 | + intel_wait_for_vblank(dev); | ||
| 7794 | + } | ||
| 7795 | + | ||
| 7796 | + /* Next, disable display pipes */ | ||
| 7797 | + temp = I915_READ(pipeconf_reg); | ||
| 7798 | + if ((temp & PIPEACONF_ENABLE) != 0) { | ||
| 7799 | + I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); | ||
| 7800 | + I915_READ(pipeconf_reg); | ||
| 7801 | + } | ||
| 7802 | + | ||
| 7803 | + /* Wait for vblank for the disable to take effect. */ | ||
| 7804 | + intel_wait_for_vblank(dev); | ||
| 7805 | + | ||
| 7806 | + temp = I915_READ(dpll_reg); | ||
| 7807 | + if ((temp & DPLL_VCO_ENABLE) != 0) { | ||
| 7808 | + I915_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); | ||
| 7809 | + I915_READ(dpll_reg); | ||
| 7810 | + } | ||
| 7811 | + | ||
| 7812 | + /* Wait for the clocks to turn off. */ | ||
| 7813 | + udelay(150); | ||
| 7814 | + break; | ||
| 7815 | + } | ||
| 7816 | + | ||
| 7817 | + | ||
| 7818 | + if (!dev_priv->sarea_priv) | ||
| 7819 | + return; | ||
| 7820 | + | ||
| 7821 | + enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF; | ||
| 7822 | + | ||
| 7823 | + switch (pipe) { | ||
| 7824 | + case 0: | ||
| 7825 | + dev_priv->sarea_priv->pipeA_w = enabled ? crtc->mode.hdisplay : 0; | ||
| 7826 | + dev_priv->sarea_priv->pipeA_h = enabled ? crtc->mode.vdisplay : 0; | ||
| 7827 | + break; | ||
| 7828 | + case 1: | ||
| 7829 | + dev_priv->sarea_priv->pipeB_w = enabled ? crtc->mode.hdisplay : 0; | ||
| 7830 | + dev_priv->sarea_priv->pipeB_h = enabled ? crtc->mode.vdisplay : 0; | ||
| 7831 | + break; | ||
| 7832 | + default: | ||
| 7833 | + DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); | ||
| 7834 | + break; | ||
| 7835 | + } | ||
| 7836 | + | ||
| 7837 | + intel_crtc->dpms_mode = mode; | ||
| 7838 | +} | ||
| 7839 | + | ||
| 7840 | +static void intel_crtc_prepare (struct drm_crtc *crtc) | ||
| 7841 | +{ | ||
| 7842 | + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | ||
| 7843 | + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); | ||
| 7844 | +} | ||
| 7845 | + | ||
| 7846 | +static void intel_crtc_commit (struct drm_crtc *crtc) | ||
| 7847 | +{ | ||
| 7848 | + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | ||
| 7849 | + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); | ||
| 7850 | +} | ||
| 7851 | + | ||
| 7852 | +void intel_encoder_prepare (struct drm_encoder *encoder) | ||
| 7853 | +{ | ||
| 7854 | + struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; | ||
| 7855 | + /* lvds has its own version of prepare see intel_lvds_prepare */ | ||
| 7856 | + encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); | ||
| 7857 | +} | ||
| 7858 | + | ||
| 7859 | +void intel_encoder_commit (struct drm_encoder *encoder) | ||
| 7860 | +{ | ||
| 7861 | + struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; | ||
| 7862 | + /* lvds has its own version of commit see intel_lvds_commit */ | ||
| 7863 | + encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); | ||
| 7864 | +} | ||
| 7865 | + | ||
| 7866 | +static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, | ||
| 7867 | + struct drm_display_mode *mode, | ||
| 7868 | + struct drm_display_mode *adjusted_mode) | ||
| 7869 | +{ | ||
| 7870 | + return true; | ||
| 7871 | +} | ||
| 7872 | + | ||
| 7873 | + | ||
| 7874 | +/** Returns the core display clock speed for i830 - i945 */ | ||
| 7875 | +static int intel_get_core_clock_speed(struct drm_device *dev) | ||
| 7876 | +{ | ||
| 7877 | + | ||
| 7878 | + /* Core clock values taken from the published datasheets. | ||
| 7879 | + * The 830 may go up to 166 Mhz, which we should check. | ||
| 7880 | + */ | ||
| 7881 | + if (IS_I945G(dev)) | ||
| 7882 | + return 400000; | ||
| 7883 | + else if (IS_I915G(dev)) | ||
| 7884 | + return 333000; | ||
| 7885 | + else if (IS_I945GM(dev) || IS_POULSBO(dev) || IS_845G(dev)) | ||
| 7886 | + return 200000; | ||
| 7887 | + else if (IS_I915GM(dev)) { | ||
| 7888 | + u16 gcfgc = 0; | ||
| 7889 | + | ||
| 7890 | + pci_read_config_word(dev->pdev, GCFGC, &gcfgc); | ||
| 7891 | + | ||
| 7892 | + if (gcfgc & GC_LOW_FREQUENCY_ENABLE) | ||
| 7893 | + return 133000; | ||
| 7894 | + else { | ||
| 7895 | + switch (gcfgc & GC_DISPLAY_CLOCK_MASK) { | ||
| 7896 | + case GC_DISPLAY_CLOCK_333_MHZ: | ||
| 7897 | + return 333000; | ||
| 7898 | + default: | ||
| 7899 | + case GC_DISPLAY_CLOCK_190_200_MHZ: | ||
| 7900 | + return 190000; | ||
| 7901 | + } | ||
| 7902 | + } | ||
| 7903 | + } else if (IS_I865G(dev)) | ||
| 7904 | + return 266000; | ||
| 7905 | + else if (IS_I855(dev)) { | ||
| 7906 | + u16 hpllcc = 0; | ||
| 7907 | + /* Assume that the hardware is in the high speed state. This | ||
| 7908 | + * should be the default. | ||
| 7909 | + */ | ||
| 7910 | + switch (hpllcc & GC_CLOCK_CONTROL_MASK) { | ||
| 7911 | + case GC_CLOCK_133_200: | ||
| 7912 | + case GC_CLOCK_100_200: | ||
| 7913 | + return 200000; | ||
| 7914 | + case GC_CLOCK_166_250: | ||
| 7915 | + return 250000; | ||
| 7916 | + case GC_CLOCK_100_133: | ||
| 7917 | + return 133000; | ||
| 7918 | + } | ||
| 7919 | + } else /* 852, 830 */ | ||
| 7920 | + return 133000; | ||
| 7921 | + | ||
| 7922 | + return 0; /* Silence gcc warning */ | ||
| 7923 | +} | ||
| 7924 | + | ||
| 7925 | + | ||
| 7926 | +/** | ||
| 7927 | + * Return the pipe currently connected to the panel fitter, | ||
| 7928 | + * or -1 if the panel fitter is not present or not in use | ||
| 7929 | + */ | ||
| 7930 | +static int intel_panel_fitter_pipe (struct drm_device *dev) | ||
| 7931 | +{ | ||
| 7932 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 7933 | + u32 pfit_control; | ||
| 7934 | + | ||
| 7935 | + /* i830 doesn't have a panel fitter */ | ||
| 7936 | + if (IS_I830(dev)) | ||
| 7937 | + return -1; | ||
| 7938 | + | ||
| 7939 | + pfit_control = I915_READ(PFIT_CONTROL); | ||
| 7940 | + | ||
| 7941 | + /* See if the panel fitter is in use */ | ||
| 7942 | + if ((pfit_control & PFIT_ENABLE) == 0) | ||
| 7943 | + return -1; | ||
| 7944 | + | ||
| 7945 | + /* 965 can place panel fitter on either pipe */ | ||
| 7946 | + if (IS_I965G(dev)) | ||
| 7947 | + return (pfit_control >> 29) & 0x3; | ||
| 7948 | + | ||
| 7949 | + /* older chips can only use pipe 1 */ | ||
| 7950 | + return 1; | ||
| 7951 | +} | ||
| 7952 | + | ||
| 7953 | +#define WA_NO_FB_GARBAGE_DISPLAY | ||
| 7954 | +#ifdef WA_NO_FB_GARBAGE_DISPLAY | ||
| 7955 | +static u32 fp_reg_value[2]; | ||
| 7956 | +static u32 dpll_reg_value[2]; | ||
| 7957 | +static u32 dpll_md_reg_value[2]; | ||
| 7958 | +static u32 dspcntr_reg_value[2]; | ||
| 7959 | +static u32 pipeconf_reg_value[2]; | ||
| 7960 | +static u32 htot_reg_value[2]; | ||
| 7961 | +static u32 hblank_reg_value[2]; | ||
| 7962 | +static u32 hsync_reg_value[2]; | ||
| 7963 | +static u32 vtot_reg_value[2]; | ||
| 7964 | +static u32 vblank_reg_value[2]; | ||
| 7965 | +static u32 vsync_reg_value[2]; | ||
| 7966 | +static u32 dspsize_reg_value[2]; | ||
| 7967 | +static u32 dspstride_reg_value[2]; | ||
| 7968 | +static u32 dsppos_reg_value[2]; | ||
| 7969 | +static u32 pipesrc_reg_value[2]; | ||
| 7970 | + | ||
| 7971 | +static u32 dspbase_value[2]; | ||
| 7972 | + | ||
| 7973 | +static u32 lvds_reg_value[2]; | ||
| 7974 | +static u32 vgacntrl_reg_value[2]; | ||
| 7975 | +static u32 pfit_control_reg_value[2]; | ||
| 7976 | + | ||
| 7977 | +#if 0 | ||
| 7978 | +void intel_crtc_mode_restore(struct drm_crtc *crtc) | ||
| 7979 | +{ | ||
| 7980 | + struct drm_device *dev = crtc->dev; | ||
| 7981 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 7982 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 7983 | + int pipe = intel_crtc->pipe; | ||
| 7984 | + int fp_reg = (pipe == 0) ? FPA0 : FPB0; | ||
| 7985 | + int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; | ||
| 7986 | + int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; | ||
| 7987 | + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | ||
| 7988 | + int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | ||
| 7989 | + int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; | ||
| 7990 | + int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; | ||
| 7991 | + int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; | ||
| 7992 | + int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; | ||
| 7993 | + int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; | ||
| 7994 | + int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; | ||
| 7995 | + int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; | ||
| 7996 | + int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; | ||
| 7997 | + int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; | ||
| 7998 | + int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; | ||
| 7999 | + int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR); | ||
| 8000 | + | ||
| 8001 | + bool ok, is_sdvo = false, is_dvo = false; | ||
| 8002 | + bool is_crt = false, is_lvds = false, is_tv = false; | ||
| 8003 | + struct drm_mode_config *mode_config = &dev->mode_config; | ||
| 8004 | + struct drm_connector *output; | ||
| 8005 | + | ||
| 8006 | + list_for_each_entry(output, &mode_config->connector_list, head) { | ||
| 8007 | + struct intel_output *intel_output = to_intel_output(crtc); | ||
| 8008 | + | ||
| 8009 | + if (output->crtc != crtc) | ||
| 8010 | + continue; | ||
| 8011 | + | ||
| 8012 | + switch (intel_output->type) { | ||
| 8013 | + case INTEL_OUTPUT_LVDS: | ||
| 8014 | + is_lvds = TRUE; | ||
| 8015 | + break; | ||
| 8016 | + case INTEL_OUTPUT_SDVO: | ||
| 8017 | + is_sdvo = TRUE; | ||
| 8018 | + break; | ||
| 8019 | + case INTEL_OUTPUT_DVO: | ||
| 8020 | + is_dvo = TRUE; | ||
| 8021 | + break; | ||
| 8022 | + case INTEL_OUTPUT_TVOUT: | ||
| 8023 | + is_tv = TRUE; | ||
| 8024 | + break; | ||
| 8025 | + case INTEL_OUTPUT_ANALOG: | ||
| 8026 | + is_crt = TRUE; | ||
| 8027 | + break; | ||
| 8028 | + } | ||
| 8029 | + if(is_lvds && ((lvds_reg_value[pipe] & LVDS_PORT_EN) == 0)) | ||
| 8030 | + { | ||
| 8031 | + printk("%s: is_lvds but not the boot display, so return\n", | ||
| 8032 | + __FUNCTION__); | ||
| 8033 | + return; | ||
| 8034 | + } | ||
| 8035 | + output->funcs->prepare(output); | ||
| 8036 | + } | ||
| 8037 | + | ||
| 8038 | + intel_crtc_prepare(crtc); | ||
| 8039 | + /* Disable the panel fitter if it was on our pipe */ | ||
| 8040 | + if (intel_panel_fitter_pipe(dev) == pipe) | ||
| 8041 | + I915_WRITE(PFIT_CONTROL, 0); | ||
| 8042 | + | ||
| 8043 | + if (dpll_reg_value[pipe] & DPLL_VCO_ENABLE) { | ||
| 8044 | + I915_WRITE(fp_reg, fp_reg_value[pipe]); | ||
| 8045 | + I915_WRITE(dpll_reg, dpll_reg_value[pipe]& ~DPLL_VCO_ENABLE); | ||
| 8046 | + I915_READ(dpll_reg); | ||
| 8047 | + udelay(150); | ||
| 8048 | + } | ||
| 8049 | + | ||
| 8050 | + /* | ||
| 8051 | + if(is_lvds) | ||
| 8052 | + I915_WRITE(LVDS, lvds_reg_value[pipe]); | ||
| 8053 | + */ | ||
| 8054 | + if (is_lvds) { | ||
| 8055 | + I915_WRITE(LVDS, lvds_reg_value[pipe]); | ||
| 8056 | + I915_READ(LVDS); | ||
| 8057 | + } | ||
| 8058 | + | ||
| 8059 | + I915_WRITE(fp_reg, fp_reg_value[pipe]); | ||
| 8060 | + I915_WRITE(dpll_reg, dpll_reg_value[pipe]); | ||
| 8061 | + I915_READ(dpll_reg); | ||
| 8062 | + udelay(150); | ||
| 8063 | + //I915_WRITE(dpll_md_reg, dpll_md_reg_value[pipe]); | ||
| 8064 | + I915_WRITE(dpll_reg, dpll_reg_value[pipe]); | ||
| 8065 | + I915_READ(dpll_reg); | ||
| 8066 | + udelay(150); | ||
| 8067 | + I915_WRITE(htot_reg, htot_reg_value[pipe]); | ||
| 8068 | + I915_WRITE(hblank_reg, hblank_reg_value[pipe]); | ||
| 8069 | + I915_WRITE(hsync_reg, hsync_reg_value[pipe]); | ||
| 8070 | + I915_WRITE(vtot_reg, vtot_reg_value[pipe]); | ||
| 8071 | + I915_WRITE(vblank_reg, vblank_reg_value[pipe]); | ||
| 8072 | + I915_WRITE(vsync_reg, vsync_reg_value[pipe]); | ||
| 8073 | + I915_WRITE(dspstride_reg, dspstride_reg_value[pipe]); | ||
| 8074 | + I915_WRITE(dspsize_reg, dspsize_reg_value[pipe]); | ||
| 8075 | + I915_WRITE(dsppos_reg, dsppos_reg_value[pipe]); | ||
| 8076 | + I915_WRITE(pipesrc_reg, pipesrc_reg_value[pipe]); | ||
| 8077 | + I915_WRITE(pipeconf_reg, pipeconf_reg_value[pipe]); | ||
| 8078 | + I915_READ(pipeconf_reg); | ||
| 8079 | + intel_wait_for_vblank(dev); | ||
| 8080 | + I915_WRITE(dspcntr_reg, dspcntr_reg_value[pipe]); | ||
| 8081 | + I915_WRITE(dspbase, dspbase_value[pipe]); | ||
| 8082 | + I915_READ(dspbase); | ||
| 8083 | + I915_WRITE(VGACNTRL, vgacntrl_reg_value[pipe]); | ||
| 8084 | + intel_wait_for_vblank(dev); | ||
| 8085 | + I915_WRITE(PFIT_CONTROL, pfit_control_reg_value[pipe]); | ||
| 8086 | + | ||
| 8087 | + intel_crtc_commit(crtc); | ||
| 8088 | + list_for_each_entry(output, &mode_config->connector_list, head) { | ||
| 8089 | + if (output->crtc != crtc) | ||
| 8090 | + continue; | ||
| 8091 | + | ||
| 8092 | + output->funcs->commit(output); | ||
| 8093 | + //output->funcs->dpms(output, DRM_MODE_DPMS_OFF); | ||
| 8094 | + //printk("turn off the display first\n"); | ||
| 8095 | + } | ||
| 8096 | + return; | ||
| 8097 | +} | ||
| 8098 | + | ||
| 8099 | +void intel_crtc_mode_save(struct drm_crtc *crtc) | ||
| 8100 | +{ | ||
| 8101 | + struct drm_device *dev = crtc->dev; | ||
| 8102 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 8103 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 8104 | + int pipe = intel_crtc->pipe; | ||
| 8105 | + int fp_reg = (pipe == 0) ? FPA0 : FPB0; | ||
| 8106 | + int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; | ||
| 8107 | + int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; | ||
| 8108 | + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | ||
| 8109 | + int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | ||
| 8110 | + int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; | ||
| 8111 | + int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; | ||
| 8112 | + int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; | ||
| 8113 | + int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; | ||
| 8114 | + int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; | ||
| 8115 | + int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; | ||
| 8116 | + int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; | ||
| 8117 | + int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; | ||
| 8118 | + int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; | ||
| 8119 | + int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; | ||
| 8120 | + int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR); | ||
| 8121 | + bool ok, is_sdvo = false, is_dvo = false; | ||
| 8122 | + bool is_crt = false, is_lvds = false, is_tv = false; | ||
| 8123 | + struct drm_mode_config *mode_config = &dev->mode_config; | ||
| 8124 | + struct drm_connector *output; | ||
| 8125 | + | ||
| 8126 | + list_for_each_entry(output, &mode_config->connector_list, head) { | ||
| 8127 | + struct intel_output *intel_output = to_intel_output(crtc); | ||
| 8128 | + | ||
| 8129 | + if (output->crtc != crtc) | ||
| 8130 | + continue; | ||
| 8131 | + | ||
| 8132 | + switch (intel_output->type) { | ||
| 8133 | + case INTEL_OUTPUT_LVDS: | ||
| 8134 | + is_lvds = TRUE; | ||
| 8135 | + break; | ||
| 8136 | + case INTEL_OUTPUT_SDVO: | ||
| 8137 | + is_sdvo = TRUE; | ||
| 8138 | + break; | ||
| 8139 | + case INTEL_OUTPUT_DVO: | ||
| 8140 | + is_dvo = TRUE; | ||
| 8141 | + break; | ||
| 8142 | + case INTEL_OUTPUT_TVOUT: | ||
| 8143 | + is_tv = TRUE; | ||
| 8144 | + break; | ||
| 8145 | + case INTEL_OUTPUT_ANALOG: | ||
| 8146 | + is_crt = TRUE; | ||
| 8147 | + break; | ||
| 8148 | + } | ||
| 8149 | + } | ||
| 8150 | + | ||
| 8151 | + fp_reg_value[pipe] = I915_READ(fp_reg); | ||
| 8152 | + dpll_reg_value[pipe] = I915_READ(dpll_reg); | ||
| 8153 | + dpll_md_reg_value[pipe] = I915_READ(dpll_md_reg); | ||
| 8154 | + dspcntr_reg_value[pipe] = I915_READ(dspcntr_reg); | ||
| 8155 | + pipeconf_reg_value[pipe] = I915_READ(pipeconf_reg); | ||
| 8156 | + htot_reg_value[pipe] = I915_READ(htot_reg); | ||
| 8157 | + hblank_reg_value[pipe] = I915_READ(hblank_reg); | ||
| 8158 | + hsync_reg_value[pipe] = I915_READ(hsync_reg); | ||
| 8159 | + vtot_reg_value[pipe] = I915_READ(vtot_reg); | ||
| 8160 | + vblank_reg_value[pipe] = I915_READ(vblank_reg); | ||
| 8161 | + vsync_reg_value[pipe] = I915_READ(vsync_reg); | ||
| 8162 | + dspsize_reg_value[pipe] = I915_READ(dspsize_reg); | ||
| 8163 | + dspstride_reg_value[pipe] = I915_READ(dspstride_reg); | ||
| 8164 | + dsppos_reg_value[pipe] = I915_READ(dsppos_reg); | ||
| 8165 | + pipesrc_reg_value[pipe] = I915_READ(pipesrc_reg); | ||
| 8166 | + dspbase_value[pipe] = I915_READ(dspbase); | ||
| 8167 | + if(is_lvds) | ||
| 8168 | + lvds_reg_value[pipe] = I915_READ(LVDS); | ||
| 8169 | + vgacntrl_reg_value[pipe] = I915_READ(VGACNTRL); | ||
| 8170 | + pfit_control_reg_value[pipe] = I915_READ(PFIT_CONTROL); | ||
| 8171 | +} | ||
| 8172 | +#endif | ||
| 8173 | +#endif | ||
| 8174 | +static void intel_crtc_mode_set(struct drm_crtc *crtc, | ||
| 8175 | + struct drm_display_mode *mode, | ||
| 8176 | + struct drm_display_mode *adjusted_mode, | ||
| 8177 | + int x, int y, | ||
| 8178 | + struct drm_framebuffer *old_fb) | ||
| 8179 | +{ | ||
| 8180 | + struct drm_device *dev = crtc->dev; | ||
| 8181 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 8182 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 8183 | + int pipe = intel_crtc->pipe; | ||
| 8184 | + int fp_reg = (pipe == 0) ? FPA0 : FPB0; | ||
| 8185 | + int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; | ||
| 8186 | + int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; | ||
| 8187 | + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | ||
| 8188 | + int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | ||
| 8189 | + int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; | ||
| 8190 | + int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; | ||
| 8191 | + int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; | ||
| 8192 | + int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; | ||
| 8193 | + int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; | ||
| 8194 | + int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; | ||
| 8195 | + int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; | ||
| 8196 | + int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; | ||
| 8197 | + int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; | ||
| 8198 | + int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; | ||
| 8199 | + int refclk; | ||
| 8200 | + intel_clock_t clock; | ||
| 8201 | + u32 dpll = 0, fp = 0, dspcntr, pipeconf; | ||
| 8202 | + bool ok, is_sdvo = false, is_dvo = false; | ||
| 8203 | + bool is_crt = false, is_lvds = false, is_tv = false; | ||
| 8204 | + struct drm_mode_config *mode_config = &dev->mode_config; | ||
| 8205 | + struct drm_connector *connector; | ||
| 8206 | + | ||
| 8207 | + if (!crtc->fb) { | ||
| 8208 | + DRM_ERROR("Can't set mode without attached fb\n"); | ||
| 8209 | + return; | ||
| 8210 | + } | ||
| 8211 | + | ||
| 8212 | + list_for_each_entry(connector, &mode_config->connector_list, head) { | ||
| 8213 | + struct intel_output *intel_output = to_intel_output(connector); | ||
| 8214 | + | ||
| 8215 | + if (!connector->encoder || connector->encoder->crtc != crtc) | ||
| 8216 | + continue; | ||
| 8217 | + | ||
| 8218 | + switch (intel_output->type) { | ||
| 8219 | + case INTEL_OUTPUT_LVDS: | ||
| 8220 | + is_lvds = true; | ||
| 8221 | + break; | ||
| 8222 | + case INTEL_OUTPUT_SDVO: | ||
| 8223 | + case INTEL_OUTPUT_HDMI: | ||
| 8224 | + is_sdvo = true; | ||
| 8225 | + break; | ||
| 8226 | + case INTEL_OUTPUT_DVO: | ||
| 8227 | + is_dvo = true; | ||
| 8228 | + break; | ||
| 8229 | + case INTEL_OUTPUT_TVOUT: | ||
| 8230 | + is_tv = true; | ||
| 8231 | + break; | ||
| 8232 | + case INTEL_OUTPUT_ANALOG: | ||
| 8233 | + is_crt = true; | ||
| 8234 | + break; | ||
| 8235 | + } | ||
| 8236 | + } | ||
| 8237 | + | ||
| 8238 | + if (IS_I9XX(dev)) { | ||
| 8239 | + refclk = 96000; | ||
| 8240 | + } else { | ||
| 8241 | + refclk = 48000; | ||
| 8242 | + } | ||
| 8243 | + | ||
| 8244 | + ok = intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, &clock); | ||
| 8245 | + if (!ok) { | ||
| 8246 | + DRM_ERROR("Couldn't find PLL settings for mode!\n"); | ||
| 8247 | + return; | ||
| 8248 | + } | ||
| 8249 | + | ||
| 8250 | + fp = clock.n << 16 | clock.m1 << 8 | clock.m2; | ||
| 8251 | + | ||
| 8252 | + dpll = DPLL_VGA_MODE_DIS; | ||
| 8253 | + if (IS_I9XX(dev)) { | ||
| 8254 | + if (is_lvds) { | ||
| 8255 | + dpll |= DPLLB_MODE_LVDS; | ||
| 8256 | + if (IS_POULSBO(dev)) | ||
| 8257 | + dpll |= DPLL_DVO_HIGH_SPEED; | ||
| 8258 | + } else | ||
| 8259 | + dpll |= DPLLB_MODE_DAC_SERIAL; | ||
| 8260 | + if (is_sdvo) { | ||
| 8261 | + dpll |= DPLL_DVO_HIGH_SPEED; | ||
| 8262 | + if (IS_I945G(dev) || IS_I945GM(dev) || IS_POULSBO(dev)) { | ||
| 8263 | + int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; | ||
| 8264 | + dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; | ||
| 8265 | + } | ||
| 8266 | + } | ||
| 8267 | + | ||
| 8268 | + /* compute bitmask from p1 value */ | ||
| 8269 | + dpll |= (1 << (clock.p1 - 1)) << 16; | ||
| 8270 | + switch (clock.p2) { | ||
| 8271 | + case 5: | ||
| 8272 | + dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; | ||
| 8273 | + break; | ||
| 8274 | + case 7: | ||
| 8275 | + dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; | ||
| 8276 | + break; | ||
| 8277 | + case 10: | ||
| 8278 | + dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; | ||
| 8279 | + break; | ||
| 8280 | + case 14: | ||
| 8281 | + dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; | ||
| 8282 | + break; | ||
| 8283 | + } | ||
| 8284 | + if (IS_I965G(dev)) | ||
| 8285 | + dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); | ||
| 8286 | + } else { | ||
| 8287 | + if (is_lvds) { | ||
| 8288 | + dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; | ||
| 8289 | + } else { | ||
| 8290 | + if (clock.p1 == 2) | ||
| 8291 | + dpll |= PLL_P1_DIVIDE_BY_TWO; | ||
| 8292 | + else | ||
| 8293 | + dpll |= (clock.p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT; | ||
| 8294 | + if (clock.p2 == 4) | ||
| 8295 | + dpll |= PLL_P2_DIVIDE_BY_4; | ||
| 8296 | + } | ||
| 8297 | + } | ||
| 8298 | + | ||
| 8299 | + if (is_tv) { | ||
| 8300 | + /* XXX: just matching BIOS for now */ | ||
| 8301 | +/* dpll |= PLL_REF_INPUT_TVCLKINBC; */ | ||
| 8302 | + dpll |= 3; | ||
| 8303 | + } | ||
| 8304 | + else | ||
| 8305 | + dpll |= PLL_REF_INPUT_DREFCLK; | ||
| 8306 | + | ||
| 8307 | + /* setup pipeconf */ | ||
| 8308 | + pipeconf = I915_READ(pipeconf_reg); | ||
| 8309 | + | ||
| 8310 | + /* Set up the display plane register */ | ||
| 8311 | + dspcntr = DISPPLANE_GAMMA_ENABLE; | ||
| 8312 | + | ||
| 8313 | + switch (crtc->fb->bits_per_pixel) { | ||
| 8314 | + case 8: | ||
| 8315 | + dspcntr |= DISPPLANE_8BPP; | ||
| 8316 | + break; | ||
| 8317 | + case 16: | ||
| 8318 | + if (crtc->fb->depth == 15) | ||
| 8319 | + dspcntr |= DISPPLANE_15_16BPP; | ||
| 8320 | + else | ||
| 8321 | + dspcntr |= DISPPLANE_16BPP; | ||
| 8322 | + break; | ||
| 8323 | + case 32: | ||
| 8324 | + dspcntr |= DISPPLANE_32BPP_NO_ALPHA; | ||
| 8325 | + break; | ||
| 8326 | + default: | ||
| 8327 | + DRM_ERROR("Unknown color depth\n"); | ||
| 8328 | + return; | ||
| 8329 | + } | ||
| 8330 | + | ||
| 8331 | + | ||
| 8332 | + if (pipe == 0) | ||
| 8333 | + dspcntr |= DISPPLANE_SEL_PIPE_A; | ||
| 8334 | + else | ||
| 8335 | + dspcntr |= DISPPLANE_SEL_PIPE_B; | ||
| 8336 | + | ||
| 8337 | + if (pipe == 0 && !IS_I965G(dev)) { | ||
| 8338 | + /* Enable pixel doubling when the dot clock is > 90% of the (display) | ||
| 8339 | + * core speed. | ||
| 8340 | + * | ||
| 8341 | + * XXX: No double-wide on 915GM pipe B. Is that the only reason for the | ||
| 8342 | + * pipe == 0 check? | ||
| 8343 | + */ | ||
| 8344 | + if (mode->clock > intel_get_core_clock_speed(dev) * 9 / 10) | ||
| 8345 | + pipeconf |= PIPEACONF_DOUBLE_WIDE; | ||
| 8346 | + else | ||
| 8347 | + pipeconf &= ~PIPEACONF_DOUBLE_WIDE; | ||
| 8348 | + } | ||
| 8349 | + | ||
| 8350 | + dspcntr |= DISPLAY_PLANE_ENABLE; | ||
| 8351 | + pipeconf |= PIPEACONF_ENABLE; | ||
| 8352 | + dpll |= DPLL_VCO_ENABLE; | ||
| 8353 | + | ||
| 8354 | + | ||
| 8355 | + /* Disable the panel fitter if it was on our pipe */ | ||
| 8356 | + if (intel_panel_fitter_pipe(dev) == pipe) | ||
| 8357 | + I915_WRITE(PFIT_CONTROL, 0); | ||
| 8358 | + | ||
| 8359 | + DRM_DEBUG("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); | ||
| 8360 | + drm_mode_debug_printmodeline(mode); | ||
| 8361 | + | ||
| 8362 | + | ||
| 8363 | + if (dpll & DPLL_VCO_ENABLE) { | ||
| 8364 | + I915_WRITE(fp_reg, fp); | ||
| 8365 | + I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); | ||
| 8366 | + I915_READ(dpll_reg); | ||
| 8367 | + udelay(150); | ||
| 8368 | + } | ||
| 8369 | + | ||
| 8370 | + /* The LVDS pin pair needs to be on before the DPLLs are enabled. | ||
| 8371 | + * This is an exception to the general rule that mode_set doesn't turn | ||
| 8372 | + * things on. | ||
| 8373 | + */ | ||
| 8374 | + if (is_lvds) { | ||
| 8375 | + u32 lvds = I915_READ(LVDS); | ||
| 8376 | + | ||
| 8377 | + lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT; | ||
| 8378 | + /* Set the B0-B3 data pairs corresponding to whether we're going to | ||
| 8379 | + * set the DPLLs for dual-channel mode or not. | ||
| 8380 | + */ | ||
| 8381 | + if (clock.p2 == 7) | ||
| 8382 | + lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; | ||
| 8383 | + else | ||
| 8384 | + lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); | ||
| 8385 | + | ||
| 8386 | + /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) | ||
| 8387 | + * appropriately here, but we need to look more thoroughly into how | ||
| 8388 | + * panels behave in the two modes. | ||
| 8389 | + */ | ||
| 8390 | + | ||
| 8391 | + I915_WRITE(LVDS, lvds); | ||
| 8392 | + I915_READ(LVDS); | ||
| 8393 | + } | ||
| 8394 | + | ||
| 8395 | + I915_WRITE(fp_reg, fp); | ||
| 8396 | + I915_WRITE(dpll_reg, dpll); | ||
| 8397 | + I915_READ(dpll_reg); | ||
| 8398 | + /* Wait for the clocks to stabilize. */ | ||
| 8399 | + udelay(150); | ||
| 8400 | + | ||
| 8401 | + if (IS_I965G(dev)) { | ||
| 8402 | + int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; | ||
| 8403 | + I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | | ||
| 8404 | + ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); | ||
| 8405 | + } else { | ||
| 8406 | + /* write it again -- the BIOS does, after all */ | ||
| 8407 | + I915_WRITE(dpll_reg, dpll); | ||
| 8408 | + } | ||
| 8409 | + I915_READ(dpll_reg); | ||
| 8410 | + /* Wait for the clocks to stabilize. */ | ||
| 8411 | + udelay(150); | ||
| 8412 | + | ||
| 8413 | + I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | | ||
| 8414 | + ((adjusted_mode->crtc_htotal - 1) << 16)); | ||
| 8415 | + I915_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | | ||
| 8416 | + ((adjusted_mode->crtc_hblank_end - 1) << 16)); | ||
| 8417 | + I915_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | | ||
| 8418 | + ((adjusted_mode->crtc_hsync_end - 1) << 16)); | ||
| 8419 | + I915_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | | ||
| 8420 | + ((adjusted_mode->crtc_vtotal - 1) << 16)); | ||
| 8421 | + I915_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | | ||
| 8422 | + ((adjusted_mode->crtc_vblank_end - 1) << 16)); | ||
| 8423 | + I915_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | | ||
| 8424 | + ((adjusted_mode->crtc_vsync_end - 1) << 16)); | ||
| 8425 | + I915_WRITE(dspstride_reg, crtc->fb->pitch); | ||
| 8426 | + /* pipesrc and dspsize control the size that is scaled from, which should | ||
| 8427 | + * always be the user's requested size. | ||
| 8428 | + */ | ||
| 8429 | + I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); | ||
| 8430 | + I915_WRITE(dsppos_reg, 0); | ||
| 8431 | + I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); | ||
| 8432 | + I915_WRITE(pipeconf_reg, pipeconf); | ||
| 8433 | + I915_READ(pipeconf_reg); | ||
| 8434 | + | ||
| 8435 | + intel_wait_for_vblank(dev); | ||
| 8436 | + | ||
| 8437 | + I915_WRITE(dspcntr_reg, dspcntr); | ||
| 8438 | + | ||
| 8439 | + /* Flush the plane changes */ | ||
| 8440 | + intel_pipe_set_base(crtc, x, y, old_fb); | ||
| 8441 | + | ||
| 8442 | + intel_wait_for_vblank(dev); | ||
| 8443 | +} | ||
| 8444 | + | ||
| 8445 | +/** Loads the palette/gamma unit for the CRTC with the prepared values */ | ||
| 8446 | +void intel_crtc_load_lut(struct drm_crtc *crtc) | ||
| 8447 | +{ | ||
| 8448 | + struct drm_device *dev = crtc->dev; | ||
| 8449 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 8450 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 8451 | + int palreg = (intel_crtc->pipe == 0) ? PALETTE_A : PALETTE_B; | ||
| 8452 | + int i; | ||
| 8453 | + | ||
| 8454 | + /* The clocks have to be on to load the palette. */ | ||
| 8455 | + if (!crtc->enabled) | ||
| 8456 | + return; | ||
| 8457 | + | ||
| 8458 | + for (i = 0; i < 256; i++) { | ||
| 8459 | + I915_WRITE(palreg + 4 * i, | ||
| 8460 | + (intel_crtc->lut_r[i] << 16) | | ||
| 8461 | + (intel_crtc->lut_g[i] << 8) | | ||
| 8462 | + intel_crtc->lut_b[i]); | ||
| 8463 | + } | ||
| 8464 | +} | ||
| 8465 | + | ||
| 8466 | +static int intel_crtc_cursor_set(struct drm_crtc *crtc, | ||
| 8467 | + struct drm_file *file_priv, | ||
| 8468 | + uint32_t handle, | ||
| 8469 | + uint32_t width, uint32_t height) | ||
| 8470 | +{ | ||
| 8471 | + struct drm_device *dev = crtc->dev; | ||
| 8472 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 8473 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 8474 | + struct drm_gem_object *bo; | ||
| 8475 | + struct drm_i915_gem_object *obj_priv; | ||
| 8476 | + int pipe = intel_crtc->pipe; | ||
| 8477 | + uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; | ||
| 8478 | + uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; | ||
| 8479 | + uint32_t temp; | ||
| 8480 | + size_t addr; | ||
| 8481 | + int ret; | ||
| 8482 | + | ||
| 8483 | + DRM_DEBUG("\n"); | ||
| 8484 | + | ||
| 8485 | + /* if we want to turn off the cursor ignore width and height */ | ||
| 8486 | + if (!handle) { | ||
| 8487 | + DRM_DEBUG("cursor off\n"); | ||
| 8488 | + temp = CURSOR_MODE_DISABLE; | ||
| 8489 | + addr = 0; | ||
| 8490 | + bo = NULL; | ||
| 8491 | + goto finish; | ||
| 8492 | + } | ||
| 8493 | + | ||
| 8494 | + /* Currently we only support 64x64 cursors */ | ||
| 8495 | + if (width != 64 || height != 64) { | ||
| 8496 | + DRM_ERROR("we currently only support 64x64 cursors\n"); | ||
| 8497 | + return -EINVAL; | ||
| 8498 | + } | ||
| 8499 | + | ||
| 8500 | + bo = drm_gem_object_lookup(dev, file_priv, handle); | ||
| 8501 | + if (!bo) | ||
| 8502 | + return -ENOENT; | ||
| 8503 | + | ||
| 8504 | + obj_priv = bo->driver_private; | ||
| 8505 | + | ||
| 8506 | + if (bo->size < width * height * 4) { | ||
| 8507 | + DRM_ERROR("buffer is to small\n"); | ||
| 8508 | + ret = -ENOMEM; | ||
| 8509 | + goto fail; | ||
| 8510 | + } | ||
| 8511 | +#if 0 | ||
| 8512 | + /* we only need to pin inside GTT if cursor is non-phy */ | ||
| 8513 | + if (!dev_priv->cursor_needs_physical) { | ||
| 8514 | + ret = i915_gem_object_pin(bo, PAGE_SIZE); | ||
| 8515 | + if (ret) { | ||
| 8516 | + DRM_ERROR("failed to pin cursor bo\n"); | ||
| 8517 | + goto fail; | ||
| 8518 | + } | ||
| 8519 | + addr = obj_priv->gtt_offset; | ||
| 8520 | + } else { | ||
| 8521 | + ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1); | ||
| 8522 | + if (ret) { | ||
| 8523 | + DRM_ERROR("failed to attach phys object\n"); | ||
| 8524 | + goto fail; | ||
| 8525 | + } | ||
| 8526 | + addr = obj_priv->phys_obj->handle->busaddr; | ||
| 8527 | + } | ||
| 8528 | +#endif | ||
| 8529 | + temp = 0; | ||
| 8530 | + /* set the pipe for the cursor */ | ||
| 8531 | + temp |= (pipe << 28); | ||
| 8532 | + temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; | ||
| 8533 | + | ||
| 8534 | + finish: | ||
| 8535 | + I915_WRITE(control, temp); | ||
| 8536 | + I915_WRITE(base, addr); | ||
| 8537 | + | ||
| 8538 | + if (intel_crtc->cursor_bo) { | ||
| 8539 | +#if 0 | ||
| 8540 | + if (dev_priv->cursor_needs_physical) { | ||
| 8541 | + if (intel_crtc->cursor_bo != bo) | ||
| 8542 | + i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo); | ||
| 8543 | + } else | ||
| 8544 | + i915_gem_object_unpin(intel_crtc->cursor_bo); | ||
| 8545 | + mutex_lock(&dev->struct_mutex); | ||
| 8546 | + drm_gem_object_unreference(intel_crtc->cursor_bo); | ||
| 8547 | + mutex_unlock(&dev->struct_mutex); | ||
| 8548 | +#endif | ||
| 8549 | + } | ||
| 8550 | + | ||
| 8551 | + intel_crtc->cursor_addr = addr; | ||
| 8552 | + intel_crtc->cursor_bo = bo; | ||
| 8553 | + | ||
| 8554 | + return 0; | ||
| 8555 | +fail: | ||
| 8556 | + mutex_lock(&dev->struct_mutex); | ||
| 8557 | + drm_gem_object_unreference(bo); | ||
| 8558 | + mutex_unlock(&dev->struct_mutex); | ||
| 8559 | + return ret; | ||
| 8560 | +} | ||
| 8561 | + | ||
| 8562 | +static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) | ||
| 8563 | +{ | ||
| 8564 | + struct drm_device *dev = crtc->dev; | ||
| 8565 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 8566 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 8567 | + int pipe = intel_crtc->pipe; | ||
| 8568 | + uint32_t temp = 0; | ||
| 8569 | + uint32_t adder; | ||
| 8570 | + | ||
| 8571 | + if (x < 0) { | ||
| 8572 | + temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); | ||
| 8573 | + x = -x; | ||
| 8574 | + } | ||
| 8575 | + if (y < 0) { | ||
| 8576 | + temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); | ||
| 8577 | + y = -y; | ||
| 8578 | + } | ||
| 8579 | + | ||
| 8580 | + temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); | ||
| 8581 | + temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); | ||
| 8582 | + | ||
| 8583 | + adder = intel_crtc->cursor_addr; | ||
| 8584 | + I915_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp); | ||
| 8585 | + I915_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder); | ||
| 8586 | + | ||
| 8587 | + return 0; | ||
| 8588 | +} | ||
| 8589 | + | ||
| 8590 | +/** Sets the color ramps on behalf of RandR */ | ||
| 8591 | +void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, | ||
| 8592 | + u16 blue, int regno) | ||
| 8593 | +{ | ||
| 8594 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 8595 | + | ||
| 8596 | + intel_crtc->lut_r[regno] = red >> 8; | ||
| 8597 | + intel_crtc->lut_g[regno] = green >> 8; | ||
| 8598 | + intel_crtc->lut_b[regno] = blue >> 8; | ||
| 8599 | +} | ||
| 8600 | + | ||
| 8601 | +static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, | ||
| 8602 | + u16 *blue, uint32_t size) | ||
| 8603 | +{ | ||
| 8604 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 8605 | + int i; | ||
| 8606 | + | ||
| 8607 | + if (size != 256) | ||
| 8608 | + return; | ||
| 8609 | + | ||
| 8610 | + for (i = 0; i < 256; i++) { | ||
| 8611 | + intel_crtc->lut_r[i] = red[i] >> 8; | ||
| 8612 | + intel_crtc->lut_g[i] = green[i] >> 8; | ||
| 8613 | + intel_crtc->lut_b[i] = blue[i] >> 8; | ||
| 8614 | + } | ||
| 8615 | + | ||
| 8616 | + intel_crtc_load_lut(crtc); | ||
| 8617 | +} | ||
| 8618 | + | ||
| 8619 | +/** | ||
| 8620 | + * Get a pipe with a simple mode set on it for doing load-based monitor | ||
| 8621 | + * detection. | ||
| 8622 | + * | ||
| 8623 | + * It will be up to the load-detect code to adjust the pipe as appropriate for | ||
| 8624 | + * its requirements. The pipe will be connected to no other outputs. | ||
| 8625 | + * | ||
| 8626 | + * Currently this code will only succeed if there is a pipe with no outputs | ||
| 8627 | + * configured for it. In the future, it could choose to temporarily disable | ||
| 8628 | + * some outputs to free up a pipe for its use. | ||
| 8629 | + * | ||
| 8630 | + * \return crtc, or NULL if no pipes are available. | ||
| 8631 | + */ | ||
| 8632 | + | ||
| 8633 | +/* VESA 640x480x72Hz mode to set on the pipe */ | ||
| 8634 | +static struct drm_display_mode load_detect_mode = { | ||
| 8635 | + DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664, | ||
| 8636 | + 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), | ||
| 8637 | +}; | ||
| 8638 | + | ||
| 8639 | +struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output, | ||
| 8640 | + struct drm_display_mode *mode, | ||
| 8641 | + int *dpms_mode) | ||
| 8642 | +{ | ||
| 8643 | + struct intel_crtc *intel_crtc; | ||
| 8644 | + struct drm_crtc *possible_crtc; | ||
| 8645 | + struct drm_crtc *supported_crtc =NULL; | ||
| 8646 | + struct drm_encoder *encoder = &intel_output->enc; | ||
| 8647 | + struct drm_crtc *crtc = NULL; | ||
| 8648 | + struct drm_device *dev = encoder->dev; | ||
| 8649 | + struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; | ||
| 8650 | + struct drm_crtc_helper_funcs *crtc_funcs; | ||
| 8651 | + int i = -1; | ||
| 8652 | + | ||
| 8653 | + /* | ||
| 8654 | + * Algorithm gets a little messy: | ||
| 8655 | + * - if the connector already has an assigned crtc, use it (but make | ||
| 8656 | + * sure it's on first) | ||
| 8657 | + * - try to find the first unused crtc that can drive this connector, | ||
| 8658 | + * and use that if we find one | ||
| 8659 | + * - if there are no unused crtcs available, try to use the first | ||
| 8660 | + * one we found that supports the connector | ||
| 8661 | + */ | ||
| 8662 | + | ||
| 8663 | + /* See if we already have a CRTC for this connector */ | ||
| 8664 | + if (encoder->crtc) { | ||
| 8665 | + crtc = encoder->crtc; | ||
| 8666 | + /* Make sure the crtc and connector are running */ | ||
| 8667 | + intel_crtc = to_intel_crtc(crtc); | ||
| 8668 | + *dpms_mode = intel_crtc->dpms_mode; | ||
| 8669 | + if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) { | ||
| 8670 | + crtc_funcs = crtc->helper_private; | ||
| 8671 | + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); | ||
| 8672 | + encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); | ||
| 8673 | + } | ||
| 8674 | + return crtc; | ||
| 8675 | + } | ||
| 8676 | + | ||
| 8677 | + /* Find an unused one (if possible) */ | ||
| 8678 | + list_for_each_entry(possible_crtc, &dev->mode_config.crtc_list, head) { | ||
| 8679 | + i++; | ||
| 8680 | + if (!(encoder->possible_crtcs & (1 << i))) | ||
| 8681 | + continue; | ||
| 8682 | + if (!possible_crtc->enabled) { | ||
| 8683 | + crtc = possible_crtc; | ||
| 8684 | + break; | ||
| 8685 | + } | ||
| 8686 | + if (!supported_crtc) | ||
| 8687 | + supported_crtc = possible_crtc; | ||
| 8688 | + } | ||
| 8689 | + | ||
| 8690 | + /* | ||
| 8691 | + * If we didn't find an unused CRTC, don't use any. | ||
| 8692 | + */ | ||
| 8693 | + if (!crtc) { | ||
| 8694 | + return NULL; | ||
| 8695 | + } | ||
| 8696 | + | ||
| 8697 | + encoder->crtc = crtc; | ||
| 8698 | + intel_output->load_detect_temp = true; | ||
| 8699 | + | ||
| 8700 | + intel_crtc = to_intel_crtc(crtc); | ||
| 8701 | + *dpms_mode = intel_crtc->dpms_mode; | ||
| 8702 | + | ||
| 8703 | + if (!crtc->enabled) { | ||
| 8704 | + if (!mode) | ||
| 8705 | + mode = &load_detect_mode; | ||
| 8706 | + drm_crtc_helper_set_mode(crtc, mode, 0, 0, crtc->fb); | ||
| 8707 | + } else { | ||
| 8708 | + if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) { | ||
| 8709 | + crtc_funcs = crtc->helper_private; | ||
| 8710 | + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); | ||
| 8711 | + } | ||
| 8712 | + | ||
| 8713 | + /* Add this connector to the crtc */ | ||
| 8714 | + encoder_funcs->mode_set(encoder, &crtc->mode, &crtc->mode); | ||
| 8715 | + encoder_funcs->commit(encoder); | ||
| 8716 | + } | ||
| 8717 | + /* let the connector get through one full cycle before testing */ | ||
| 8718 | + intel_wait_for_vblank(dev); | ||
| 8719 | + | ||
| 8720 | + return crtc; | ||
| 8721 | +} | ||
| 8722 | + | ||
| 8723 | +void intel_release_load_detect_pipe(struct intel_output *intel_output, int dpms_mode) | ||
| 8724 | +{ | ||
| 8725 | + struct drm_encoder *encoder = &intel_output->enc; | ||
| 8726 | + struct drm_device *dev = encoder->dev; | ||
| 8727 | + struct drm_crtc *crtc = encoder->crtc; | ||
| 8728 | + struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; | ||
| 8729 | + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | ||
| 8730 | + | ||
| 8731 | + if (intel_output->load_detect_temp) { | ||
| 8732 | + encoder->crtc = NULL; | ||
| 8733 | + intel_output->load_detect_temp = false; | ||
| 8734 | + crtc->enabled = drm_helper_crtc_in_use(crtc); | ||
| 8735 | + drm_helper_disable_unused_functions(dev); | ||
| 8736 | + } | ||
| 8737 | + | ||
| 8738 | + /* Switch crtc and output back off if necessary */ | ||
| 8739 | + if (crtc->enabled && dpms_mode != DRM_MODE_DPMS_ON) { | ||
| 8740 | + if (encoder->crtc == crtc) | ||
| 8741 | + encoder_funcs->dpms(encoder, dpms_mode); | ||
| 8742 | + crtc_funcs->dpms(crtc, dpms_mode); | ||
| 8743 | + } | ||
| 8744 | +} | ||
| 8745 | + | ||
| 8746 | +/* Returns the clock of the currently programmed mode of the given pipe. */ | ||
| 8747 | +static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) | ||
| 8748 | +{ | ||
| 8749 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 8750 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 8751 | + int pipe = intel_crtc->pipe; | ||
| 8752 | + u32 dpll = I915_READ((pipe == 0) ? DPLL_A : DPLL_B); | ||
| 8753 | + u32 fp; | ||
| 8754 | + intel_clock_t clock; | ||
| 8755 | + | ||
| 8756 | + if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) | ||
| 8757 | + fp = I915_READ((pipe == 0) ? FPA0 : FPB0); | ||
| 8758 | + else | ||
| 8759 | + fp = I915_READ((pipe == 0) ? FPA1 : FPB1); | ||
| 8760 | + | ||
| 8761 | + clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; | ||
| 8762 | + clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; | ||
| 8763 | + clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT; | ||
| 8764 | + if (IS_I9XX(dev)) { | ||
| 8765 | + clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >> | ||
| 8766 | + DPLL_FPA01_P1_POST_DIV_SHIFT); | ||
| 8767 | + | ||
| 8768 | + switch (dpll & DPLL_MODE_MASK) { | ||
| 8769 | + case DPLLB_MODE_DAC_SERIAL: | ||
| 8770 | + clock.p2 = dpll & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? | ||
| 8771 | + 5 : 10; | ||
| 8772 | + break; | ||
| 8773 | + case DPLLB_MODE_LVDS: | ||
| 8774 | + clock.p2 = dpll & DPLLB_LVDS_P2_CLOCK_DIV_7 ? | ||
| 8775 | + 7 : 14; | ||
| 8776 | + break; | ||
| 8777 | + default: | ||
| 8778 | + DRM_DEBUG("Unknown DPLL mode %08x in programmed " | ||
| 8779 | + "mode\n", (int)(dpll & DPLL_MODE_MASK)); | ||
| 8780 | + return 0; | ||
| 8781 | + } | ||
| 8782 | + | ||
| 8783 | + /* XXX: Handle the 100Mhz refclk */ | ||
| 8784 | + i9xx_clock(96000, &clock); | ||
| 8785 | + } else { | ||
| 8786 | + bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN); | ||
| 8787 | + | ||
| 8788 | + if (is_lvds) { | ||
| 8789 | + clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >> | ||
| 8790 | + DPLL_FPA01_P1_POST_DIV_SHIFT); | ||
| 8791 | + clock.p2 = 14; | ||
| 8792 | + | ||
| 8793 | + if ((dpll & PLL_REF_INPUT_MASK) == | ||
| 8794 | + PLLB_REF_INPUT_SPREADSPECTRUMIN) { | ||
| 8795 | + /* XXX: might not be 66MHz */ | ||
| 8796 | + i8xx_clock(66000, &clock); | ||
| 8797 | + } else | ||
| 8798 | + i8xx_clock(48000, &clock); | ||
| 8799 | + } else { | ||
| 8800 | + if (dpll & PLL_P1_DIVIDE_BY_TWO) | ||
| 8801 | + clock.p1 = 2; | ||
| 8802 | + else { | ||
| 8803 | + clock.p1 = ((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830) >> | ||
| 8804 | + DPLL_FPA01_P1_POST_DIV_SHIFT) + 2; | ||
| 8805 | + } | ||
| 8806 | + if (dpll & PLL_P2_DIVIDE_BY_4) | ||
| 8807 | + clock.p2 = 4; | ||
| 8808 | + else | ||
| 8809 | + clock.p2 = 2; | ||
| 8810 | + | ||
| 8811 | + i8xx_clock(48000, &clock); | ||
| 8812 | + } | ||
| 8813 | + } | ||
| 8814 | + | ||
| 8815 | + /* XXX: It would be nice to validate the clocks, but we can't reuse | ||
| 8816 | + * i830PllIsValid() because it relies on the xf86_config connector | ||
| 8817 | + * configuration being accurate, which it isn't necessarily. | ||
| 8818 | + */ | ||
| 8819 | + | ||
| 8820 | + return clock.dot; | ||
| 8821 | +} | ||
| 8822 | + | ||
| 8823 | +/** Returns the currently programmed mode of the given pipe. */ | ||
| 8824 | +struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, | ||
| 8825 | + struct drm_crtc *crtc) | ||
| 8826 | +{ | ||
| 8827 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 8828 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 8829 | + int pipe = intel_crtc->pipe; | ||
| 8830 | + struct drm_display_mode *mode; | ||
| 8831 | + int htot = I915_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B); | ||
| 8832 | + int hsync = I915_READ((pipe == 0) ? HSYNC_A : HSYNC_B); | ||
| 8833 | + int vtot = I915_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B); | ||
| 8834 | + int vsync = I915_READ((pipe == 0) ? VSYNC_A : VSYNC_B); | ||
| 8835 | + | ||
| 8836 | + mode = kzalloc(sizeof(*mode), GFP_KERNEL); | ||
| 8837 | + if (!mode) | ||
| 8838 | + return NULL; | ||
| 8839 | + | ||
| 8840 | + mode->clock = intel_crtc_clock_get(dev, crtc); | ||
| 8841 | + mode->hdisplay = (htot & 0xffff) + 1; | ||
| 8842 | + mode->htotal = ((htot & 0xffff0000) >> 16) + 1; | ||
| 8843 | + mode->hsync_start = (hsync & 0xffff) + 1; | ||
| 8844 | + mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1; | ||
| 8845 | + mode->vdisplay = (vtot & 0xffff) + 1; | ||
| 8846 | + mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1; | ||
| 8847 | + mode->vsync_start = (vsync & 0xffff) + 1; | ||
| 8848 | + mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1; | ||
| 8849 | + | ||
| 8850 | + drm_mode_set_name(mode); | ||
| 8851 | + drm_mode_set_crtcinfo(mode, 0); | ||
| 8852 | + | ||
| 8853 | + return mode; | ||
| 8854 | +} | ||
| 8855 | + | ||
| 8856 | +static void intel_crtc_destroy(struct drm_crtc *crtc) | ||
| 8857 | +{ | ||
| 8858 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 8859 | + | ||
| 8860 | + drm_crtc_cleanup(crtc); | ||
| 8861 | + kfree(intel_crtc); | ||
| 8862 | +} | ||
| 8863 | + | ||
| 8864 | +static const struct drm_crtc_helper_funcs intel_helper_funcs = { | ||
| 8865 | + .dpms = intel_crtc_dpms, | ||
| 8866 | + .mode_fixup = intel_crtc_mode_fixup, | ||
| 8867 | + .mode_set = intel_crtc_mode_set, | ||
| 8868 | + .mode_set_base = intel_pipe_set_base, | ||
| 8869 | + .prepare = intel_crtc_prepare, | ||
| 8870 | + .commit = intel_crtc_commit, | ||
| 8871 | +}; | ||
| 8872 | + | ||
| 8873 | +static const struct drm_crtc_funcs intel_crtc_funcs = { | ||
| 8874 | + .cursor_set = intel_crtc_cursor_set, | ||
| 8875 | + .cursor_move = intel_crtc_cursor_move, | ||
| 8876 | + .gamma_set = intel_crtc_gamma_set, | ||
| 8877 | + .set_config = drm_crtc_helper_set_config, | ||
| 8878 | + .destroy = intel_crtc_destroy, | ||
| 8879 | +}; | ||
| 8880 | + | ||
| 8881 | + | ||
| 8882 | +static void intel_crtc_init(struct drm_device *dev, int pipe) | ||
| 8883 | +{ | ||
| 8884 | + struct intel_crtc *intel_crtc; | ||
| 8885 | + int i; | ||
| 8886 | + | ||
| 8887 | + intel_crtc = kzalloc(sizeof(struct intel_crtc) + (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL); | ||
| 8888 | + if (intel_crtc == NULL) | ||
| 8889 | + return; | ||
| 8890 | + | ||
| 8891 | + drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs); | ||
| 8892 | + | ||
| 8893 | + intel_crtc->pipe = pipe; | ||
| 8894 | + for (i = 0; i < 256; i++) { | ||
| 8895 | + intel_crtc->lut_r[i] = i; | ||
| 8896 | + intel_crtc->lut_g[i] = i; | ||
| 8897 | + intel_crtc->lut_b[i] = i; | ||
| 8898 | + } | ||
| 8899 | + | ||
| 8900 | + intel_crtc->cursor_addr = 0; | ||
| 8901 | + intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF; | ||
| 8902 | + drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); | ||
| 8903 | + | ||
| 8904 | + intel_crtc->mode_set.crtc = &intel_crtc->base; | ||
| 8905 | + intel_crtc->mode_set.connectors = (struct drm_connector **)(intel_crtc + 1); | ||
| 8906 | + intel_crtc->mode_set.num_connectors = 0; | ||
| 8907 | + | ||
| 8908 | +} | ||
| 8909 | + | ||
| 8910 | +struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe) | ||
| 8911 | +{ | ||
| 8912 | + struct drm_crtc *crtc = NULL; | ||
| 8913 | + | ||
| 8914 | + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
| 8915 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 8916 | + if (intel_crtc->pipe == pipe) | ||
| 8917 | + break; | ||
| 8918 | + } | ||
| 8919 | + return crtc; | ||
| 8920 | +} | ||
| 8921 | + | ||
| 8922 | +static int intel_connector_clones(struct drm_device *dev, int type_mask) | ||
| 8923 | +{ | ||
| 8924 | + int index_mask = 0; | ||
| 8925 | + struct drm_connector *connector; | ||
| 8926 | + int entry = 0; | ||
| 8927 | + | ||
| 8928 | + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 8929 | + struct intel_output *intel_output = to_intel_output(connector); | ||
| 8930 | + if (type_mask & (1 << intel_output->type)) | ||
| 8931 | + index_mask |= (1 << entry); | ||
| 8932 | + entry++; | ||
| 8933 | + } | ||
| 8934 | + return index_mask; | ||
| 8935 | +} | ||
| 8936 | + | ||
| 8937 | + | ||
| 8938 | +static void intel_setup_outputs(struct drm_device *dev) | ||
| 8939 | +{ | ||
| 8940 | + struct drm_connector *connector; | ||
| 8941 | + | ||
| 8942 | + if (!IS_POULSBO(dev)) | ||
| 8943 | + intel_crt_init(dev); | ||
| 8944 | + | ||
| 8945 | + /* Set up integrated LVDS */ | ||
| 8946 | + if (IS_MOBILE(dev) && !IS_I830(dev)) | ||
| 8947 | + intel_lvds_init(dev); | ||
| 8948 | + | ||
| 8949 | + if (IS_I9XX(dev)) { | ||
| 8950 | + intel_sdvo_init(dev, SDVOB); | ||
| 8951 | + intel_sdvo_init(dev, SDVOC); | ||
| 8952 | + } | ||
| 8953 | + | ||
| 8954 | + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 8955 | + struct intel_output *intel_output = to_intel_output(connector); | ||
| 8956 | + struct drm_encoder *encoder = &intel_output->enc; | ||
| 8957 | + int crtc_mask = 0, clone_mask = 0; | ||
| 8958 | + | ||
| 8959 | + /* valid crtcs */ | ||
| 8960 | + switch(intel_output->type) { | ||
| 8961 | + case INTEL_OUTPUT_HDMI: | ||
| 8962 | + crtc_mask = ((1 << 0)| | ||
| 8963 | + (1 << 1)); | ||
| 8964 | + clone_mask = ((1 << INTEL_OUTPUT_HDMI)); | ||
| 8965 | + break; | ||
| 8966 | + case INTEL_OUTPUT_DVO: | ||
| 8967 | + case INTEL_OUTPUT_SDVO: | ||
| 8968 | + crtc_mask = ((1 << 0)| | ||
| 8969 | + (1 << 1)); | ||
| 8970 | + clone_mask = ((1 << INTEL_OUTPUT_ANALOG) | | ||
| 8971 | + (1 << INTEL_OUTPUT_DVO) | | ||
| 8972 | + (1 << INTEL_OUTPUT_SDVO)); | ||
| 8973 | + break; | ||
| 8974 | + case INTEL_OUTPUT_ANALOG: | ||
| 8975 | + crtc_mask = ((1 << 0)| | ||
| 8976 | + (1 << 1)); | ||
| 8977 | + clone_mask = ((1 << INTEL_OUTPUT_ANALOG) | | ||
| 8978 | + (1 << INTEL_OUTPUT_DVO) | | ||
| 8979 | + (1 << INTEL_OUTPUT_SDVO)); | ||
| 8980 | + break; | ||
| 8981 | + case INTEL_OUTPUT_LVDS: | ||
| 8982 | + crtc_mask = (1 << 1); | ||
| 8983 | + clone_mask = (1 << INTEL_OUTPUT_LVDS); | ||
| 8984 | + break; | ||
| 8985 | + case INTEL_OUTPUT_TVOUT: | ||
| 8986 | + crtc_mask = ((1 << 0) | | ||
| 8987 | + (1 << 1)); | ||
| 8988 | + clone_mask = (1 << INTEL_OUTPUT_TVOUT); | ||
| 8989 | + break; | ||
| 8990 | + } | ||
| 8991 | + encoder->possible_crtcs = crtc_mask; | ||
| 8992 | + encoder->possible_clones = intel_connector_clones(dev, clone_mask); | ||
| 8993 | + } | ||
| 8994 | +} | ||
| 8995 | + | ||
| 8996 | +static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb) | ||
| 8997 | +{ | ||
| 8998 | + struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); | ||
| 8999 | + struct drm_device *dev = fb->dev; | ||
| 9000 | + | ||
| 9001 | + //if (fb->fbdev) | ||
| 9002 | + // intelfb_remove(dev, fb); | ||
| 9003 | + | ||
| 9004 | + drm_framebuffer_cleanup(fb); | ||
| 9005 | + mutex_lock(&dev->struct_mutex); | ||
| 9006 | + drm_gem_object_unreference(intel_fb->obj); | ||
| 9007 | + mutex_unlock(&dev->struct_mutex); | ||
| 9008 | + | ||
| 9009 | + kfree(intel_fb); | ||
| 9010 | +} | ||
| 9011 | + | ||
| 9012 | +static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb, | ||
| 9013 | + struct drm_file *file_priv, | ||
| 9014 | + unsigned int *handle) | ||
| 9015 | +{ | ||
| 9016 | + struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); | ||
| 9017 | + struct drm_gem_object *object = intel_fb->obj; | ||
| 9018 | + | ||
| 9019 | + return drm_gem_handle_create(file_priv, object, handle); | ||
| 9020 | +} | ||
| 9021 | + | ||
| 9022 | +static const struct drm_framebuffer_funcs intel_fb_funcs = { | ||
| 9023 | + .destroy = intel_user_framebuffer_destroy, | ||
| 9024 | + .create_handle = intel_user_framebuffer_create_handle, | ||
| 9025 | +}; | ||
| 9026 | + | ||
| 9027 | +int intel_framebuffer_create(struct drm_device *dev, | ||
| 9028 | + struct drm_mode_fb_cmd *mode_cmd, | ||
| 9029 | + struct drm_framebuffer **fb, | ||
| 9030 | + struct drm_gem_object *obj) | ||
| 9031 | +{ | ||
| 9032 | + struct intel_framebuffer *intel_fb; | ||
| 9033 | + int ret; | ||
| 9034 | + | ||
| 9035 | + intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); | ||
| 9036 | + if (!intel_fb) | ||
| 9037 | + return -ENOMEM; | ||
| 9038 | + | ||
| 9039 | + ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs); | ||
| 9040 | + if (ret) { | ||
| 9041 | + DRM_ERROR("framebuffer init failed %d\n", ret); | ||
| 9042 | + return ret; | ||
| 9043 | + } | ||
| 9044 | + | ||
| 9045 | + drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd); | ||
| 9046 | + | ||
| 9047 | + intel_fb->obj = obj; | ||
| 9048 | + | ||
| 9049 | + *fb = &intel_fb->base; | ||
| 9050 | + | ||
| 9051 | + return 0; | ||
| 9052 | +} | ||
| 9053 | + | ||
| 9054 | + | ||
| 9055 | +static struct drm_framebuffer * | ||
| 9056 | +intel_user_framebuffer_create(struct drm_device *dev, | ||
| 9057 | + struct drm_file *filp, | ||
| 9058 | + struct drm_mode_fb_cmd *mode_cmd) | ||
| 9059 | +{ | ||
| 9060 | + struct drm_gem_object *obj; | ||
| 9061 | + struct drm_framebuffer *fb; | ||
| 9062 | + int ret; | ||
| 9063 | + | ||
| 9064 | + obj = drm_gem_object_lookup(dev, filp, mode_cmd->handle); | ||
| 9065 | + if (!obj) | ||
| 9066 | + return NULL; | ||
| 9067 | + | ||
| 9068 | + ret = intel_framebuffer_create(dev, mode_cmd, &fb, obj); | ||
| 9069 | + if (ret) { | ||
| 9070 | + drm_gem_object_unreference(obj); | ||
| 9071 | + return NULL; | ||
| 9072 | + } | ||
| 9073 | + | ||
| 9074 | + return fb; | ||
| 9075 | +} | ||
| 9076 | + | ||
| 9077 | +static const struct drm_mode_config_funcs intel_mode_funcs = { | ||
| 9078 | + .fb_create = intel_user_framebuffer_create, | ||
| 9079 | +// .fb_changed = intelfb_probe, | ||
| 9080 | +}; | ||
| 9081 | + | ||
| 9082 | +void intel_modeset_init(struct drm_device *dev) | ||
| 9083 | +{ | ||
| 9084 | + int num_pipe; | ||
| 9085 | + int i; | ||
| 9086 | + | ||
| 9087 | + drm_mode_config_init(dev); | ||
| 9088 | + | ||
| 9089 | + dev->mode_config.min_width = 0; | ||
| 9090 | + dev->mode_config.min_height = 0; | ||
| 9091 | + | ||
| 9092 | + dev->mode_config.funcs = (void *)&intel_mode_funcs; | ||
| 9093 | + | ||
| 9094 | + dev->mode_config.max_width = 2048; | ||
| 9095 | + dev->mode_config.max_height = 2048; | ||
| 9096 | + | ||
| 9097 | + /* set memory base */ | ||
| 9098 | + if (IS_I9XX(dev)) | ||
| 9099 | + dev->mode_config.fb_base = pci_resource_start(dev->pdev, 2); | ||
| 9100 | + else | ||
| 9101 | + dev->mode_config.fb_base = pci_resource_start(dev->pdev, 0); | ||
| 9102 | + | ||
| 9103 | + if (IS_MOBILE(dev) || IS_I9XX(dev)) | ||
| 9104 | + num_pipe = 2; | ||
| 9105 | + else | ||
| 9106 | + num_pipe = 1; | ||
| 9107 | + DRM_DEBUG("%d display pipe%s available.\n", | ||
| 9108 | + num_pipe, num_pipe > 1 ? "s" : ""); | ||
| 9109 | + | ||
| 9110 | + for (i = 0; i < num_pipe; i++) { | ||
| 9111 | + intel_crtc_init(dev, i); | ||
| 9112 | + } | ||
| 9113 | + | ||
| 9114 | + intel_setup_outputs(dev); | ||
| 9115 | +} | ||
| 9116 | + | ||
| 9117 | +void intel_modeset_cleanup(struct drm_device *dev) | ||
| 9118 | +{ | ||
| 9119 | + drm_mode_config_cleanup(dev); | ||
| 9120 | +} | ||
| 9121 | + | ||
| 9122 | + | ||
| 9123 | +/* current intel driver doesn't take advantage of encoders | ||
| 9124 | + always give back the encoder for the connector | ||
| 9125 | +*/ | ||
| 9126 | +struct drm_encoder *intel_best_encoder(struct drm_connector *connector) | ||
| 9127 | +{ | ||
| 9128 | + struct intel_output *intel_output = to_intel_output(connector); | ||
| 9129 | + | ||
| 9130 | + return &intel_output->enc; | ||
| 9131 | +} | ||
| 9132 | Index: linux-2.6.28/drivers/gpu/drm/psb/intel_drv.h | ||
| 9133 | =================================================================== | ||
| 9134 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | ||
| 9135 | +++ linux-2.6.28/drivers/gpu/drm/psb/intel_drv.h 2009-02-12 09:14:41.000000000 +0000 | ||
| 9136 | @@ -0,0 +1,7 @@ | ||
| 9137 | +#include "../i915/intel_drv.h" | ||
| 9138 | +extern void intel_modeset_init(struct drm_device *dev); | ||
| 9139 | +extern void intel_modeset_cleanup(struct drm_device *dev); | ||
| 9140 | + | ||
| 9141 | +extern void intel_crtc_mode_restore(struct drm_crtc *crtc); | ||
| 9142 | +extern void intel_crtc_mode_save(struct drm_crtc *crtc); | ||
| 9143 | + | ||
| 9144 | Index: linux-2.6.28/drivers/gpu/drm/psb/psb_buffer.c | 7229 | Index: linux-2.6.28/drivers/gpu/drm/psb/psb_buffer.c |
| 9145 | =================================================================== | 7230 | =================================================================== |
| 9146 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | 7231 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 |
| @@ -9961,7 +8046,7 @@ Index: linux-2.6.28/drivers/gpu/drm/psb/psb_drm.h | |||
| 9961 | Index: linux-2.6.28/drivers/gpu/drm/psb/psb_drv.c | 8046 | Index: linux-2.6.28/drivers/gpu/drm/psb/psb_drv.c |
| 9962 | =================================================================== | 8047 | =================================================================== |
| 9963 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | 8048 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 |
| 9964 | +++ linux-2.6.28/drivers/gpu/drm/psb/psb_drv.c 2009-02-12 09:14:41.000000000 +0000 | 8049 | +++ linux-2.6.28/drivers/gpu/drm/psb/psb_drv.c 2009-02-12 10:11:59.000000000 +0000 |
| 9965 | @@ -0,0 +1,1096 @@ | 8050 | @@ -0,0 +1,1096 @@ |
| 9966 | +/************************************************************************** | 8051 | +/************************************************************************** |
| 9967 | + * Copyright (c) 2007, Intel Corporation. | 8052 | + * Copyright (c) 2007, Intel Corporation. |
| @@ -9992,7 +8077,7 @@ Index: linux-2.6.28/drivers/gpu/drm/psb/psb_drv.c | |||
| 9992 | +#include "psb_drm.h" | 8077 | +#include "psb_drm.h" |
| 9993 | +#include "psb_drv.h" | 8078 | +#include "psb_drv.h" |
| 9994 | +#include "psb_reg.h" | 8079 | +#include "psb_reg.h" |
| 9995 | +#include "i915_reg.h" | 8080 | +#include "../i915/i915_reg.h" |
| 9996 | +#include "psb_msvdx.h" | 8081 | +#include "psb_msvdx.h" |
| 9997 | +#include "drm_pciids.h" | 8082 | +#include "drm_pciids.h" |
| 9998 | +#include "psb_scene.h" | 8083 | +#include "psb_scene.h" |
| @@ -11062,8 +9147,8 @@ Index: linux-2.6.28/drivers/gpu/drm/psb/psb_drv.c | |||
| 11062 | Index: linux-2.6.28/drivers/gpu/drm/psb/psb_drv.h | 9147 | Index: linux-2.6.28/drivers/gpu/drm/psb/psb_drv.h |
| 11063 | =================================================================== | 9148 | =================================================================== |
| 11064 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | 9149 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 |
| 11065 | +++ linux-2.6.28/drivers/gpu/drm/psb/psb_drv.h 2009-02-12 09:14:41.000000000 +0000 | 9150 | +++ linux-2.6.28/drivers/gpu/drm/psb/psb_drv.h 2009-02-12 10:10:55.000000000 +0000 |
| 11066 | @@ -0,0 +1,548 @@ | 9151 | @@ -0,0 +1,549 @@ |
| 11067 | +/************************************************************************** | 9152 | +/************************************************************************** |
| 11068 | + * Copyright (c) 2007, Intel Corporation. | 9153 | + * Copyright (c) 2007, Intel Corporation. |
| 11069 | + * All Rights Reserved. | 9154 | + * All Rights Reserved. |
| @@ -11094,8 +9179,9 @@ Index: linux-2.6.28/drivers/gpu/drm/psb/psb_drv.h | |||
| 11094 | +#include "psb_drm.h" | 9179 | +#include "psb_drm.h" |
| 11095 | +#include "psb_reg.h" | 9180 | +#include "psb_reg.h" |
| 11096 | +#include "psb_schedule.h" | 9181 | +#include "psb_schedule.h" |
| 11097 | +#include "intel_drv.h" | ||
| 11098 | +#include "psb_priv.h" | 9182 | +#include "psb_priv.h" |
| 9183 | +#include "../i915/intel_drv.h" | ||
| 9184 | + | ||
| 11099 | + | 9185 | + |
| 11100 | +enum { | 9186 | +enum { |
| 11101 | + CHIP_PSB_8108 = 0, | 9187 | + CHIP_PSB_8108 = 0, |
| @@ -13497,7 +11583,7 @@ Index: linux-2.6.28/drivers/gpu/drm/psb/psb_gtt.c | |||
| 13497 | Index: linux-2.6.28/drivers/gpu/drm/psb/psb_i2c.c | 11583 | Index: linux-2.6.28/drivers/gpu/drm/psb/psb_i2c.c |
| 13498 | =================================================================== | 11584 | =================================================================== |
| 13499 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | 11585 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 |
| 13500 | +++ linux-2.6.28/drivers/gpu/drm/psb/psb_i2c.c 2009-02-12 09:14:41.000000000 +0000 | 11586 | +++ linux-2.6.28/drivers/gpu/drm/psb/psb_i2c.c 2009-02-12 10:12:29.000000000 +0000 |
| 13501 | @@ -0,0 +1,179 @@ | 11587 | @@ -0,0 +1,179 @@ |
| 13502 | +/* | 11588 | +/* |
| 13503 | + * Copyright © 2006-2007 Intel Corporation | 11589 | + * Copyright © 2006-2007 Intel Corporation |
| @@ -13534,7 +11620,7 @@ Index: linux-2.6.28/drivers/gpu/drm/psb/psb_i2c.c | |||
| 13534 | +#include <linux/i2c-algo-bit.h> | 11620 | +#include <linux/i2c-algo-bit.h> |
| 13535 | +#include "drmP.h" | 11621 | +#include "drmP.h" |
| 13536 | +#include "drm.h" | 11622 | +#include "drm.h" |
| 13537 | +#include "intel_drv.h" | 11623 | +#include "../i915/intel_drv.h" |
| 13538 | +#include "psb_drv.h" | 11624 | +#include "psb_drv.h" |
| 13539 | + | 11625 | + |
| 13540 | +/* | 11626 | +/* |
| @@ -20396,7 +18482,7 @@ Index: linux-2.6.28/drivers/gpu/drm/psb/psb_schedule.h | |||
| 20396 | Index: linux-2.6.28/drivers/gpu/drm/psb/psb_setup.c | 18482 | Index: linux-2.6.28/drivers/gpu/drm/psb/psb_setup.c |
| 20397 | =================================================================== | 18483 | =================================================================== |
| 20398 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | 18484 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 |
| 20399 | +++ linux-2.6.28/drivers/gpu/drm/psb/psb_setup.c 2009-02-12 09:14:42.000000000 +0000 | 18485 | +++ linux-2.6.28/drivers/gpu/drm/psb/psb_setup.c 2009-02-12 09:59:18.000000000 +0000 |
| 20400 | @@ -0,0 +1,18 @@ | 18486 | @@ -0,0 +1,18 @@ |
| 20401 | +#include "drmP.h" | 18487 | +#include "drmP.h" |
| 20402 | +#include "drm.h" | 18488 | +#include "drm.h" |
| @@ -20414,7 +18500,7 @@ Index: linux-2.6.28/drivers/gpu/drm/psb/psb_setup.c | |||
| 20414 | + | 18500 | + |
| 20415 | +#include "../i915/intel_lvds.c" | 18501 | +#include "../i915/intel_lvds.c" |
| 20416 | +#include "../i915/intel_sdvo.c" | 18502 | +#include "../i915/intel_sdvo.c" |
| 20417 | +#include "intel_display.c" | 18503 | +#include "../i915/intel_display.c" |
| 20418 | +#include "../i915/intel_modes.c" | 18504 | +#include "../i915/intel_modes.c" |
| 20419 | Index: linux-2.6.28/drivers/gpu/drm/psb/psb_sgx.c | 18505 | Index: linux-2.6.28/drivers/gpu/drm/psb/psb_sgx.c |
| 20420 | =================================================================== | 18506 | =================================================================== |
| @@ -23369,22 +21455,6 @@ Index: linux-2.6.28/drivers/gpu/drm/drm_crtc.c | |||
| 23369 | } | 21455 | } |
| 23370 | mutex_unlock(&dev->mode_config.mutex); | 21456 | mutex_unlock(&dev->mode_config.mutex); |
| 23371 | } | 21457 | } |
| 23372 | Index: linux-2.6.28/drivers/gpu/drm/drm_sysfs.c | ||
| 23373 | =================================================================== | ||
| 23374 | --- linux-2.6.28.orig/drivers/gpu/drm/drm_sysfs.c 2009-02-12 09:14:37.000000000 +0000 | ||
| 23375 | +++ linux-2.6.28/drivers/gpu/drm/drm_sysfs.c 2009-02-12 09:14:42.000000000 +0000 | ||
| 23376 | @@ -156,8 +156,9 @@ | ||
| 23377 | enum drm_connector_status status; | ||
| 23378 | |||
| 23379 | status = connector->funcs->detect(connector); | ||
| 23380 | - return snprintf(buf, PAGE_SIZE, "%s", | ||
| 23381 | - drm_get_connector_status_name(status)); | ||
| 23382 | + return 0; | ||
| 23383 | + //return snprintf(buf, PAGE_SIZE, "%s", | ||
| 23384 | + // drm_get_connector_status_name(status)); | ||
| 23385 | } | ||
| 23386 | |||
| 23387 | static ssize_t dpms_show(struct device *device, | ||
| 23388 | Index: linux-2.6.28/include/drm/drm_crtc.h | 21458 | Index: linux-2.6.28/include/drm/drm_crtc.h |
| 23389 | =================================================================== | 21459 | =================================================================== |
| 23390 | --- linux-2.6.28.orig/include/drm/drm_crtc.h 2009-02-12 09:14:40.000000000 +0000 | 21460 | --- linux-2.6.28.orig/include/drm/drm_crtc.h 2009-02-12 09:14:40.000000000 +0000 |
| @@ -23411,7 +21481,7 @@ Index: linux-2.6.28/include/drm/drm_crtc.h | |||
| 23411 | Index: linux-2.6.28/drivers/gpu/drm/i915/intel_crt.c | 21481 | Index: linux-2.6.28/drivers/gpu/drm/i915/intel_crt.c |
| 23412 | =================================================================== | 21482 | =================================================================== |
| 23413 | --- linux-2.6.28.orig/drivers/gpu/drm/i915/intel_crt.c 2009-02-12 09:14:37.000000000 +0000 | 21483 | --- linux-2.6.28.orig/drivers/gpu/drm/i915/intel_crt.c 2009-02-12 09:14:37.000000000 +0000 |
| 23414 | +++ linux-2.6.28/drivers/gpu/drm/i915/intel_crt.c 2009-02-12 09:14:42.000000000 +0000 | 21484 | +++ linux-2.6.28/drivers/gpu/drm/i915/intel_crt.c 2009-02-12 16:12:38.000000000 +0000 |
| 23415 | @@ -36,7 +36,7 @@ | 21485 | @@ -36,7 +36,7 @@ |
| 23416 | static void intel_crt_dpms(struct drm_encoder *encoder, int mode) | 21486 | static void intel_crt_dpms(struct drm_encoder *encoder, int mode) |
| 23417 | { | 21487 | { |
| @@ -23448,26 +21518,10 @@ Index: linux-2.6.28/drivers/gpu/drm/i915/intel_crt.c | |||
| 23448 | if (intel_crt_detect_hotplug(connector)) | 21518 | if (intel_crt_detect_hotplug(connector)) |
| 23449 | return connector_status_connected; | 21519 | return connector_status_connected; |
| 23450 | else | 21520 | else |
| 23451 | @@ -189,7 +189,7 @@ | ||
| 23452 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 23453 | |||
| 23454 | intel_i2c_destroy(intel_output->ddc_bus); | ||
| 23455 | - drm_sysfs_connector_remove(connector); | ||
| 23456 | + //drm_sysfs_connector_remove(connector); | ||
| 23457 | drm_connector_cleanup(connector); | ||
| 23458 | kfree(connector); | ||
| 23459 | } | ||
| 23460 | @@ -280,5 +280,5 @@ | ||
| 23461 | drm_encoder_helper_add(&intel_output->enc, &intel_crt_helper_funcs); | ||
| 23462 | drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); | ||
| 23463 | |||
| 23464 | - drm_sysfs_connector_add(connector); | ||
| 23465 | + //drm_sysfs_connector_add(connector); | ||
| 23466 | } | ||
| 23467 | Index: linux-2.6.28/drivers/gpu/drm/i915/intel_lvds.c | 21521 | Index: linux-2.6.28/drivers/gpu/drm/i915/intel_lvds.c |
| 23468 | =================================================================== | 21522 | =================================================================== |
| 23469 | --- linux-2.6.28.orig/drivers/gpu/drm/i915/intel_lvds.c 2009-02-12 09:14:37.000000000 +0000 | 21523 | --- linux-2.6.28.orig/drivers/gpu/drm/i915/intel_lvds.c 2009-02-12 09:14:37.000000000 +0000 |
| 23470 | +++ linux-2.6.28/drivers/gpu/drm/i915/intel_lvds.c 2009-02-12 09:14:42.000000000 +0000 | 21524 | +++ linux-2.6.28/drivers/gpu/drm/i915/intel_lvds.c 2009-02-12 16:13:08.000000000 +0000 |
| 23471 | @@ -36,6 +36,259 @@ | 21525 | @@ -36,6 +36,259 @@ |
| 23472 | #include "i915_drm.h" | 21526 | #include "i915_drm.h" |
| 23473 | #include "i915_drv.h" | 21527 | #include "i915_drv.h" |
| @@ -23938,7 +21992,7 @@ Index: linux-2.6.28/drivers/gpu/drm/i915/intel_lvds.c | |||
| 23938 | 21992 | ||
| 23939 | if (ret) | 21993 | if (ret) |
| 23940 | return ret; | 21994 | return ret; |
| 23941 | @@ -333,9 +637,12 @@ | 21995 | @@ -333,8 +637,11 @@ |
| 23942 | { | 21996 | { |
| 23943 | struct intel_output *intel_output = to_intel_output(connector); | 21997 | struct intel_output *intel_output = to_intel_output(connector); |
| 23944 | 21998 | ||
| @@ -23946,12 +22000,10 @@ Index: linux-2.6.28/drivers/gpu/drm/i915/intel_lvds.c | |||
| 23946 | + iounmap(dev_OpRegion); | 22000 | + iounmap(dev_OpRegion); |
| 23947 | if (intel_output->ddc_bus) | 22001 | if (intel_output->ddc_bus) |
| 23948 | intel_i2c_destroy(intel_output->ddc_bus); | 22002 | intel_i2c_destroy(intel_output->ddc_bus); |
| 23949 | - drm_sysfs_connector_remove(connector); | ||
| 23950 | + intel_i2c_destroy(lvds_i2c_bus); | 22003 | + intel_i2c_destroy(lvds_i2c_bus); |
| 23951 | + //drm_sysfs_connector_remove(connector); | 22004 | drm_sysfs_connector_remove(connector); |
| 23952 | drm_connector_cleanup(connector); | 22005 | drm_connector_cleanup(connector); |
| 23953 | kfree(connector); | 22006 | kfree(connector); |
| 23954 | } | ||
| 23955 | @@ -373,7 +680,45 @@ | 22007 | @@ -373,7 +680,45 @@ |
| 23956 | }; | 22008 | }; |
| 23957 | 22009 | ||
| @@ -24228,19 +22280,10 @@ Index: linux-2.6.28/drivers/gpu/drm/i915/intel_lvds.c | |||
| 24228 | /* | 22280 | /* |
| 24229 | * If we didn't get EDID, try checking if the panel is already turned | 22281 | * If we didn't get EDID, try checking if the panel is already turned |
| 24230 | * on. If so, assume that whatever is currently programmed is the | 22282 | * on. If so, assume that whatever is currently programmed is the |
| 24231 | @@ -520,7 +1001,7 @@ | ||
| 24232 | |||
| 24233 | |||
| 24234 | out: | ||
| 24235 | - drm_sysfs_connector_add(connector); | ||
| 24236 | + //drm_sysfs_connector_add(connector); | ||
| 24237 | return; | ||
| 24238 | |||
| 24239 | failed: | ||
| 24240 | Index: linux-2.6.28/drivers/gpu/drm/i915/intel_sdvo.c | 22283 | Index: linux-2.6.28/drivers/gpu/drm/i915/intel_sdvo.c |
| 24241 | =================================================================== | 22284 | =================================================================== |
| 24242 | --- linux-2.6.28.orig/drivers/gpu/drm/i915/intel_sdvo.c 2009-02-12 09:14:37.000000000 +0000 | 22285 | --- linux-2.6.28.orig/drivers/gpu/drm/i915/intel_sdvo.c 2009-02-12 09:14:37.000000000 +0000 |
| 24243 | +++ linux-2.6.28/drivers/gpu/drm/i915/intel_sdvo.c 2009-02-12 09:14:42.000000000 +0000 | 22286 | +++ linux-2.6.28/drivers/gpu/drm/i915/intel_sdvo.c 2009-02-12 16:12:58.000000000 +0000 |
| 24244 | @@ -37,6 +37,14 @@ | 22287 | @@ -37,6 +37,14 @@ |
| 24245 | 22288 | ||
| 24246 | #undef SDVO_DEBUG | 22289 | #undef SDVO_DEBUG |
| @@ -24310,15 +22353,6 @@ Index: linux-2.6.28/drivers/gpu/drm/i915/intel_sdvo.c | |||
| 24310 | struct intel_output *intel_output = to_intel_output(connector); | 22353 | struct intel_output *intel_output = to_intel_output(connector); |
| 24311 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | 22354 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; |
| 24312 | int o; | 22355 | int o; |
| 24313 | @@ -941,7 +949,7 @@ | ||
| 24314 | |||
| 24315 | if (intel_output->i2c_bus) | ||
| 24316 | intel_i2c_destroy(intel_output->i2c_bus); | ||
| 24317 | - drm_sysfs_connector_remove(connector); | ||
| 24318 | + //drm_sysfs_connector_remove(connector); | ||
| 24319 | drm_connector_cleanup(connector); | ||
| 24320 | kfree(intel_output); | ||
| 24321 | } | ||
| 24322 | @@ -988,6 +996,32 @@ | 22356 | @@ -988,6 +996,32 @@ |
| 24323 | u8 ch[0x40]; | 22357 | u8 ch[0x40]; |
| 24324 | int i; | 22358 | int i; |
| @@ -24352,20 +22386,11 @@ Index: linux-2.6.28/drivers/gpu/drm/i915/intel_sdvo.c | |||
| 24352 | 22386 | ||
| 24353 | intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); | 22387 | intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); |
| 24354 | if (!intel_output) { | 22388 | if (!intel_output) { |
| 24355 | @@ -1087,7 +1121,7 @@ | ||
| 24356 | connector->connector_type = connector_type; | ||
| 24357 | |||
| 24358 | drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc); | ||
| 24359 | - drm_sysfs_connector_add(connector); | ||
| 24360 | + //drm_sysfs_connector_add(connector); | ||
| 24361 | |||
| 24362 | /* Set the input timing to the screen. Assume always input 0. */ | ||
| 24363 | intel_sdvo_set_target_input(intel_output, true, false); | ||
| 24364 | Index: linux-2.6.28/drivers/gpu/drm/psb/psb_priv.h | 22389 | Index: linux-2.6.28/drivers/gpu/drm/psb/psb_priv.h |
| 24365 | =================================================================== | 22390 | =================================================================== |
| 24366 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | 22391 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 |
| 24367 | +++ linux-2.6.28/drivers/gpu/drm/psb/psb_priv.h 2009-02-12 09:14:42.000000000 +0000 | 22392 | +++ linux-2.6.28/drivers/gpu/drm/psb/psb_priv.h 2009-02-12 10:11:32.000000000 +0000 |
| 24368 | @@ -0,0 +1,238 @@ | 22393 | @@ -0,0 +1,244 @@ |
| 24369 | +#include "psb_drm.h" | 22394 | +#include "psb_drm.h" |
| 24370 | +#include "psb_reg.h" | 22395 | +#include "psb_reg.h" |
| 24371 | +#include "psb_schedule.h" | 22396 | +#include "psb_schedule.h" |
| @@ -24604,10 +22629,16 @@ Index: linux-2.6.28/drivers/gpu/drm/psb/psb_priv.h | |||
| 24604 | + | 22629 | + |
| 24605 | +}; | 22630 | +}; |
| 24606 | + | 22631 | + |
| 22632 | + | ||
| 22633 | +extern void intel_modeset_init(struct drm_device *dev); | ||
| 22634 | +extern void intel_modeset_cleanup(struct drm_device *dev); | ||
| 22635 | + | ||
| 22636 | +extern void intel_crtc_mode_restore(struct drm_crtc *crtc); | ||
| 22637 | +extern void intel_crtc_mode_save(struct drm_crtc *crtc); | ||
| 24607 | Index: linux-2.6.28/drivers/gpu/drm/i915/i915_drv.h | 22638 | Index: linux-2.6.28/drivers/gpu/drm/i915/i915_drv.h |
| 24608 | =================================================================== | 22639 | =================================================================== |
| 24609 | --- linux-2.6.28.orig/drivers/gpu/drm/i915/i915_drv.h 2009-02-12 09:47:51.000000000 +0000 | 22640 | --- linux-2.6.28.orig/drivers/gpu/drm/i915/i915_drv.h 2009-02-12 09:47:51.000000000 +0000 |
| 24610 | +++ linux-2.6.28/drivers/gpu/drm/i915/i915_drv.h 2009-02-11 21:23:41.000000000 +0000 | 22641 | +++ linux-2.6.28/drivers/gpu/drm/i915/i915_drv.h 2009-02-12 10:06:18.000000000 +0000 |
| 24611 | @@ -672,6 +672,7 @@ | 22642 | @@ -672,6 +672,7 @@ |
| 24612 | LOCK_TEST_WITH_RETURN(dev, file_priv); \ | 22643 | LOCK_TEST_WITH_RETURN(dev, file_priv); \ |
| 24613 | } while (0) | 22644 | } while (0) |
| @@ -24642,3 +22673,689 @@ Index: linux-2.6.28/drivers/gpu/drm/i915/i915_drv.h | |||
| 24642 | 22673 | ||
| 24643 | #define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev)) | 22674 | #define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev)) |
| 24644 | #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev)) | 22675 | #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev)) |
| 22676 | Index: linux-2.6.28/drivers/gpu/drm/i915/intel_display.c | ||
| 22677 | =================================================================== | ||
| 22678 | --- linux-2.6.28.orig/drivers/gpu/drm/i915/intel_display.c 2009-02-12 09:58:47.000000000 +0000 | ||
| 22679 | +++ linux-2.6.28/drivers/gpu/drm/i915/intel_display.c 2009-02-12 16:32:26.000000000 +0000 | ||
| 22680 | @@ -26,9 +26,9 @@ | ||
| 22681 | |||
| 22682 | #include <linux/i2c.h> | ||
| 22683 | #include "drmP.h" | ||
| 22684 | -#include "intel_drv.h" | ||
| 22685 | +#include "../i915/intel_drv.h" | ||
| 22686 | #include "i915_drm.h" | ||
| 22687 | -#include "i915_drv.h" | ||
| 22688 | +#include "../i915/i915_drv.h" | ||
| 22689 | |||
| 22690 | #include "drm_crtc_helper.h" | ||
| 22691 | |||
| 22692 | @@ -282,7 +282,7 @@ | ||
| 22693 | int refclk, intel_clock_t *best_clock) | ||
| 22694 | { | ||
| 22695 | struct drm_device *dev = crtc->dev; | ||
| 22696 | - struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 22697 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 22698 | intel_clock_t clock; | ||
| 22699 | const intel_limit_t *limit = intel_limit(crtc); | ||
| 22700 | int err = target; | ||
| 22701 | @@ -348,12 +348,8 @@ | ||
| 22702 | struct drm_framebuffer *old_fb) | ||
| 22703 | { | ||
| 22704 | struct drm_device *dev = crtc->dev; | ||
| 22705 | - struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 22706 | - struct drm_i915_master_private *master_priv; | ||
| 22707 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 22708 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 22709 | - struct intel_framebuffer *intel_fb; | ||
| 22710 | - struct drm_i915_gem_object *obj_priv; | ||
| 22711 | - struct drm_gem_object *obj; | ||
| 22712 | int pipe = intel_crtc->pipe; | ||
| 22713 | unsigned long Start, Offset; | ||
| 22714 | int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR); | ||
| 22715 | @@ -362,66 +358,8 @@ | ||
| 22716 | int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | ||
| 22717 | u32 dspcntr, alignment; | ||
| 22718 | |||
| 22719 | - /* no fb bound */ | ||
| 22720 | - if (!crtc->fb) { | ||
| 22721 | - DRM_DEBUG("No FB bound\n"); | ||
| 22722 | - return; | ||
| 22723 | - } | ||
| 22724 | - | ||
| 22725 | - intel_fb = to_intel_framebuffer(crtc->fb); | ||
| 22726 | - obj = intel_fb->obj; | ||
| 22727 | - obj_priv = obj->driver_private; | ||
| 22728 | - | ||
| 22729 | - switch (obj_priv->tiling_mode) { | ||
| 22730 | - case I915_TILING_NONE: | ||
| 22731 | - alignment = 64 * 1024; | ||
| 22732 | - break; | ||
| 22733 | - case I915_TILING_X: | ||
| 22734 | - if (IS_I9XX(dev)) | ||
| 22735 | - alignment = 1024 * 1024; | ||
| 22736 | - else | ||
| 22737 | - alignment = 512 * 1024; | ||
| 22738 | - break; | ||
| 22739 | - case I915_TILING_Y: | ||
| 22740 | - /* FIXME: Is this true? */ | ||
| 22741 | - DRM_ERROR("Y tiled not allowed for scan out buffers\n"); | ||
| 22742 | - return; | ||
| 22743 | - default: | ||
| 22744 | - BUG(); | ||
| 22745 | - } | ||
| 22746 | - | ||
| 22747 | - if (i915_gem_object_pin(intel_fb->obj, alignment)) | ||
| 22748 | - return; | ||
| 22749 | - | ||
| 22750 | - i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1); | ||
| 22751 | - | ||
| 22752 | - Start = obj_priv->gtt_offset; | ||
| 22753 | - Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); | ||
| 22754 | - | ||
| 22755 | - I915_WRITE(dspstride, crtc->fb->pitch); | ||
| 22756 | - | ||
| 22757 | - dspcntr = I915_READ(dspcntr_reg); | ||
| 22758 | - /* Mask out pixel format bits in case we change it */ | ||
| 22759 | - dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; | ||
| 22760 | - switch (crtc->fb->bits_per_pixel) { | ||
| 22761 | - case 8: | ||
| 22762 | - dspcntr |= DISPPLANE_8BPP; | ||
| 22763 | - break; | ||
| 22764 | - case 16: | ||
| 22765 | - if (crtc->fb->depth == 15) | ||
| 22766 | - dspcntr |= DISPPLANE_15_16BPP; | ||
| 22767 | - else | ||
| 22768 | - dspcntr |= DISPPLANE_16BPP; | ||
| 22769 | - break; | ||
| 22770 | - case 24: | ||
| 22771 | - case 32: | ||
| 22772 | - dspcntr |= DISPPLANE_32BPP_NO_ALPHA; | ||
| 22773 | - break; | ||
| 22774 | - default: | ||
| 22775 | - DRM_ERROR("Unknown color depth\n"); | ||
| 22776 | - return; | ||
| 22777 | - } | ||
| 22778 | - I915_WRITE(dspcntr_reg, dspcntr); | ||
| 22779 | + Start = crtc->fb->offset; | ||
| 22780 | + Offset = y * crtc->fb->pitch + x; | ||
| 22781 | |||
| 22782 | DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); | ||
| 22783 | if (IS_I965G(dev)) { | ||
| 22784 | @@ -434,28 +372,18 @@ | ||
| 22785 | I915_READ(dspbase); | ||
| 22786 | } | ||
| 22787 | |||
| 22788 | - intel_wait_for_vblank(dev); | ||
| 22789 | - | ||
| 22790 | - if (old_fb) { | ||
| 22791 | - intel_fb = to_intel_framebuffer(old_fb); | ||
| 22792 | - i915_gem_object_unpin(intel_fb->obj); | ||
| 22793 | - } | ||
| 22794 | - | ||
| 22795 | - if (!dev->primary->master) | ||
| 22796 | - return; | ||
| 22797 | |||
| 22798 | - master_priv = dev->primary->master->driver_priv; | ||
| 22799 | - if (!master_priv->sarea_priv) | ||
| 22800 | + if (!dev_priv->sarea_priv) | ||
| 22801 | return; | ||
| 22802 | |||
| 22803 | switch (pipe) { | ||
| 22804 | case 0: | ||
| 22805 | - master_priv->sarea_priv->pipeA_x = x; | ||
| 22806 | - master_priv->sarea_priv->pipeA_y = y; | ||
| 22807 | + dev_priv->sarea_priv->pipeA_x = x; | ||
| 22808 | + dev_priv->sarea_priv->pipeA_y = y; | ||
| 22809 | break; | ||
| 22810 | case 1: | ||
| 22811 | - master_priv->sarea_priv->pipeB_x = x; | ||
| 22812 | - master_priv->sarea_priv->pipeB_y = y; | ||
| 22813 | + dev_priv->sarea_priv->pipeB_x = x; | ||
| 22814 | + dev_priv->sarea_priv->pipeB_y = y; | ||
| 22815 | break; | ||
| 22816 | default: | ||
| 22817 | DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); | ||
| 22818 | @@ -474,8 +402,7 @@ | ||
| 22819 | static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) | ||
| 22820 | { | ||
| 22821 | struct drm_device *dev = crtc->dev; | ||
| 22822 | - struct drm_i915_master_private *master_priv; | ||
| 22823 | - struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 22824 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 22825 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 22826 | int pipe = intel_crtc->pipe; | ||
| 22827 | int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; | ||
| 22828 | @@ -569,23 +496,20 @@ | ||
| 22829 | break; | ||
| 22830 | } | ||
| 22831 | |||
| 22832 | - if (!dev->primary->master) | ||
| 22833 | - return; | ||
| 22834 | |||
| 22835 | - master_priv = dev->primary->master->driver_priv; | ||
| 22836 | - if (!master_priv->sarea_priv) | ||
| 22837 | + if (!dev_priv->sarea_priv) | ||
| 22838 | return; | ||
| 22839 | |||
| 22840 | enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF; | ||
| 22841 | |||
| 22842 | switch (pipe) { | ||
| 22843 | case 0: | ||
| 22844 | - master_priv->sarea_priv->pipeA_w = enabled ? crtc->mode.hdisplay : 0; | ||
| 22845 | - master_priv->sarea_priv->pipeA_h = enabled ? crtc->mode.vdisplay : 0; | ||
| 22846 | + dev_priv->sarea_priv->pipeA_w = enabled ? crtc->mode.hdisplay : 0; | ||
| 22847 | + dev_priv->sarea_priv->pipeA_h = enabled ? crtc->mode.vdisplay : 0; | ||
| 22848 | break; | ||
| 22849 | case 1: | ||
| 22850 | - master_priv->sarea_priv->pipeB_w = enabled ? crtc->mode.hdisplay : 0; | ||
| 22851 | - master_priv->sarea_priv->pipeB_h = enabled ? crtc->mode.vdisplay : 0; | ||
| 22852 | + dev_priv->sarea_priv->pipeB_w = enabled ? crtc->mode.hdisplay : 0; | ||
| 22853 | + dev_priv->sarea_priv->pipeB_h = enabled ? crtc->mode.vdisplay : 0; | ||
| 22854 | break; | ||
| 22855 | default: | ||
| 22856 | DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); | ||
| 22857 | @@ -640,7 +564,7 @@ | ||
| 22858 | return 400000; | ||
| 22859 | else if (IS_I915G(dev)) | ||
| 22860 | return 333000; | ||
| 22861 | - else if (IS_I945GM(dev) || IS_845G(dev)) | ||
| 22862 | + else if (IS_I945GM(dev) || IS_POULSBO(dev) || IS_845G(dev)) | ||
| 22863 | return 200000; | ||
| 22864 | else if (IS_I915GM(dev)) { | ||
| 22865 | u16 gcfgc = 0; | ||
| 22866 | @@ -687,7 +611,7 @@ | ||
| 22867 | */ | ||
| 22868 | static int intel_panel_fitter_pipe (struct drm_device *dev) | ||
| 22869 | { | ||
| 22870 | - struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 22871 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 22872 | u32 pfit_control; | ||
| 22873 | |||
| 22874 | /* i830 doesn't have a panel fitter */ | ||
| 22875 | @@ -707,7 +631,228 @@ | ||
| 22876 | /* older chips can only use pipe 1 */ | ||
| 22877 | return 1; | ||
| 22878 | } | ||
| 22879 | +#if 0 | ||
| 22880 | +#define WA_NO_FB_GARBAGE_DISPLAY | ||
| 22881 | +#ifdef WA_NO_FB_GARBAGE_DISPLAY | ||
| 22882 | +static u32 fp_reg_value[2]; | ||
| 22883 | +static u32 dpll_reg_value[2]; | ||
| 22884 | +static u32 dpll_md_reg_value[2]; | ||
| 22885 | +static u32 dspcntr_reg_value[2]; | ||
| 22886 | +static u32 pipeconf_reg_value[2]; | ||
| 22887 | +static u32 htot_reg_value[2]; | ||
| 22888 | +static u32 hblank_reg_value[2]; | ||
| 22889 | +static u32 hsync_reg_value[2]; | ||
| 22890 | +static u32 vtot_reg_value[2]; | ||
| 22891 | +static u32 vblank_reg_value[2]; | ||
| 22892 | +static u32 vsync_reg_value[2]; | ||
| 22893 | +static u32 dspsize_reg_value[2]; | ||
| 22894 | +static u32 dspstride_reg_value[2]; | ||
| 22895 | +static u32 dsppos_reg_value[2]; | ||
| 22896 | +static u32 pipesrc_reg_value[2]; | ||
| 22897 | + | ||
| 22898 | +static u32 dspbase_value[2]; | ||
| 22899 | + | ||
| 22900 | +static u32 lvds_reg_value[2]; | ||
| 22901 | +static u32 vgacntrl_reg_value[2]; | ||
| 22902 | +static u32 pfit_control_reg_value[2]; | ||
| 22903 | + | ||
| 22904 | + | ||
| 22905 | +void intel_crtc_mode_restore(struct drm_crtc *crtc) | ||
| 22906 | +{ | ||
| 22907 | + struct drm_device *dev = crtc->dev; | ||
| 22908 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 22909 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 22910 | + int pipe = intel_crtc->pipe; | ||
| 22911 | + int fp_reg = (pipe == 0) ? FPA0 : FPB0; | ||
| 22912 | + int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; | ||
| 22913 | + int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; | ||
| 22914 | + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | ||
| 22915 | + int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | ||
| 22916 | + int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; | ||
| 22917 | + int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; | ||
| 22918 | + int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; | ||
| 22919 | + int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; | ||
| 22920 | + int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; | ||
| 22921 | + int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; | ||
| 22922 | + int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; | ||
| 22923 | + int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; | ||
| 22924 | + int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; | ||
| 22925 | + int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; | ||
| 22926 | + int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR); | ||
| 22927 | + | ||
| 22928 | + bool ok, is_sdvo = false, is_dvo = false; | ||
| 22929 | + bool is_crt = false, is_lvds = false, is_tv = false; | ||
| 22930 | + struct drm_mode_config *mode_config = &dev->mode_config; | ||
| 22931 | + struct drm_connector *output; | ||
| 22932 | + | ||
| 22933 | + list_for_each_entry(output, &mode_config->connector_list, head) { | ||
| 22934 | + struct intel_output *intel_output = to_intel_output(crtc); | ||
| 22935 | + | ||
| 22936 | + if (output->crtc != crtc) | ||
| 22937 | + continue; | ||
| 22938 | + | ||
| 22939 | + switch (intel_output->type) { | ||
| 22940 | + case INTEL_OUTPUT_LVDS: | ||
| 22941 | + is_lvds = TRUE; | ||
| 22942 | + break; | ||
| 22943 | + case INTEL_OUTPUT_SDVO: | ||
| 22944 | + is_sdvo = TRUE; | ||
| 22945 | + break; | ||
| 22946 | + case INTEL_OUTPUT_DVO: | ||
| 22947 | + is_dvo = TRUE; | ||
| 22948 | + break; | ||
| 22949 | + case INTEL_OUTPUT_TVOUT: | ||
| 22950 | + is_tv = TRUE; | ||
| 22951 | + break; | ||
| 22952 | + case INTEL_OUTPUT_ANALOG: | ||
| 22953 | + is_crt = TRUE; | ||
| 22954 | + break; | ||
| 22955 | + } | ||
| 22956 | + if(is_lvds && ((lvds_reg_value[pipe] & LVDS_PORT_EN) == 0)) | ||
| 22957 | + { | ||
| 22958 | + printk("%s: is_lvds but not the boot display, so return\n", | ||
| 22959 | + __FUNCTION__); | ||
| 22960 | + return; | ||
| 22961 | + } | ||
| 22962 | + output->funcs->prepare(output); | ||
| 22963 | + } | ||
| 22964 | + | ||
| 22965 | + intel_crtc_prepare(crtc); | ||
| 22966 | + /* Disable the panel fitter if it was on our pipe */ | ||
| 22967 | + if (intel_panel_fitter_pipe(dev) == pipe) | ||
| 22968 | + I915_WRITE(PFIT_CONTROL, 0); | ||
| 22969 | |||
| 22970 | + if (dpll_reg_value[pipe] & DPLL_VCO_ENABLE) { | ||
| 22971 | + I915_WRITE(fp_reg, fp_reg_value[pipe]); | ||
| 22972 | + I915_WRITE(dpll_reg, dpll_reg_value[pipe]& ~DPLL_VCO_ENABLE); | ||
| 22973 | + I915_READ(dpll_reg); | ||
| 22974 | + udelay(150); | ||
| 22975 | + } | ||
| 22976 | + | ||
| 22977 | + /* | ||
| 22978 | + if(is_lvds) | ||
| 22979 | + I915_WRITE(LVDS, lvds_reg_value[pipe]); | ||
| 22980 | + */ | ||
| 22981 | + if (is_lvds) { | ||
| 22982 | + I915_WRITE(LVDS, lvds_reg_value[pipe]); | ||
| 22983 | + I915_READ(LVDS); | ||
| 22984 | + } | ||
| 22985 | + | ||
| 22986 | + I915_WRITE(fp_reg, fp_reg_value[pipe]); | ||
| 22987 | + I915_WRITE(dpll_reg, dpll_reg_value[pipe]); | ||
| 22988 | + I915_READ(dpll_reg); | ||
| 22989 | + udelay(150); | ||
| 22990 | + //I915_WRITE(dpll_md_reg, dpll_md_reg_value[pipe]); | ||
| 22991 | + I915_WRITE(dpll_reg, dpll_reg_value[pipe]); | ||
| 22992 | + I915_READ(dpll_reg); | ||
| 22993 | + udelay(150); | ||
| 22994 | + I915_WRITE(htot_reg, htot_reg_value[pipe]); | ||
| 22995 | + I915_WRITE(hblank_reg, hblank_reg_value[pipe]); | ||
| 22996 | + I915_WRITE(hsync_reg, hsync_reg_value[pipe]); | ||
| 22997 | + I915_WRITE(vtot_reg, vtot_reg_value[pipe]); | ||
| 22998 | + I915_WRITE(vblank_reg, vblank_reg_value[pipe]); | ||
| 22999 | + I915_WRITE(vsync_reg, vsync_reg_value[pipe]); | ||
| 23000 | + I915_WRITE(dspstride_reg, dspstride_reg_value[pipe]); | ||
| 23001 | + I915_WRITE(dspsize_reg, dspsize_reg_value[pipe]); | ||
| 23002 | + I915_WRITE(dsppos_reg, dsppos_reg_value[pipe]); | ||
| 23003 | + I915_WRITE(pipesrc_reg, pipesrc_reg_value[pipe]); | ||
| 23004 | + I915_WRITE(pipeconf_reg, pipeconf_reg_value[pipe]); | ||
| 23005 | + I915_READ(pipeconf_reg); | ||
| 23006 | + intel_wait_for_vblank(dev); | ||
| 23007 | + I915_WRITE(dspcntr_reg, dspcntr_reg_value[pipe]); | ||
| 23008 | + I915_WRITE(dspbase, dspbase_value[pipe]); | ||
| 23009 | + I915_READ(dspbase); | ||
| 23010 | + I915_WRITE(VGACNTRL, vgacntrl_reg_value[pipe]); | ||
| 23011 | + intel_wait_for_vblank(dev); | ||
| 23012 | + I915_WRITE(PFIT_CONTROL, pfit_control_reg_value[pipe]); | ||
| 23013 | + | ||
| 23014 | + intel_crtc_commit(crtc); | ||
| 23015 | + list_for_each_entry(output, &mode_config->connector_list, head) { | ||
| 23016 | + if (output->crtc != crtc) | ||
| 23017 | + continue; | ||
| 23018 | + | ||
| 23019 | + output->funcs->commit(output); | ||
| 23020 | + //output->funcs->dpms(output, DRM_MODE_DPMS_OFF); | ||
| 23021 | + //printk("turn off the display first\n"); | ||
| 23022 | + } | ||
| 23023 | + return; | ||
| 23024 | +} | ||
| 23025 | + | ||
| 23026 | +void intel_crtc_mode_save(struct drm_crtc *crtc) | ||
| 23027 | +{ | ||
| 23028 | + struct drm_device *dev = crtc->dev; | ||
| 23029 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 23030 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 23031 | + int pipe = intel_crtc->pipe; | ||
| 23032 | + int fp_reg = (pipe == 0) ? FPA0 : FPB0; | ||
| 23033 | + int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; | ||
| 23034 | + int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; | ||
| 23035 | + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | ||
| 23036 | + int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | ||
| 23037 | + int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; | ||
| 23038 | + int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; | ||
| 23039 | + int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; | ||
| 23040 | + int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; | ||
| 23041 | + int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; | ||
| 23042 | + int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; | ||
| 23043 | + int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; | ||
| 23044 | + int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; | ||
| 23045 | + int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; | ||
| 23046 | + int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; | ||
| 23047 | + int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR); | ||
| 23048 | + bool ok, is_sdvo = false, is_dvo = false; | ||
| 23049 | + bool is_crt = false, is_lvds = false, is_tv = false; | ||
| 23050 | + struct drm_mode_config *mode_config = &dev->mode_config; | ||
| 23051 | + struct drm_connector *output; | ||
| 23052 | + | ||
| 23053 | + list_for_each_entry(output, &mode_config->connector_list, head) { | ||
| 23054 | + struct intel_output *intel_output = to_intel_output(crtc); | ||
| 23055 | + | ||
| 23056 | + if (output->crtc != crtc) | ||
| 23057 | + continue; | ||
| 23058 | + | ||
| 23059 | + switch (intel_output->type) { | ||
| 23060 | + case INTEL_OUTPUT_LVDS: | ||
| 23061 | + is_lvds = TRUE; | ||
| 23062 | + break; | ||
| 23063 | + case INTEL_OUTPUT_SDVO: | ||
| 23064 | + is_sdvo = TRUE; | ||
| 23065 | + break; | ||
| 23066 | + case INTEL_OUTPUT_DVO: | ||
| 23067 | + is_dvo = TRUE; | ||
| 23068 | + break; | ||
| 23069 | + case INTEL_OUTPUT_TVOUT: | ||
| 23070 | + is_tv = TRUE; | ||
| 23071 | + break; | ||
| 23072 | + case INTEL_OUTPUT_ANALOG: | ||
| 23073 | + is_crt = TRUE; | ||
| 23074 | + break; | ||
| 23075 | + } | ||
| 23076 | + } | ||
| 23077 | + | ||
| 23078 | + fp_reg_value[pipe] = I915_READ(fp_reg); | ||
| 23079 | + dpll_reg_value[pipe] = I915_READ(dpll_reg); | ||
| 23080 | + dpll_md_reg_value[pipe] = I915_READ(dpll_md_reg); | ||
| 23081 | + dspcntr_reg_value[pipe] = I915_READ(dspcntr_reg); | ||
| 23082 | + pipeconf_reg_value[pipe] = I915_READ(pipeconf_reg); | ||
| 23083 | + htot_reg_value[pipe] = I915_READ(htot_reg); | ||
| 23084 | + hblank_reg_value[pipe] = I915_READ(hblank_reg); | ||
| 23085 | + hsync_reg_value[pipe] = I915_READ(hsync_reg); | ||
| 23086 | + vtot_reg_value[pipe] = I915_READ(vtot_reg); | ||
| 23087 | + vblank_reg_value[pipe] = I915_READ(vblank_reg); | ||
| 23088 | + vsync_reg_value[pipe] = I915_READ(vsync_reg); | ||
| 23089 | + dspsize_reg_value[pipe] = I915_READ(dspsize_reg); | ||
| 23090 | + dspstride_reg_value[pipe] = I915_READ(dspstride_reg); | ||
| 23091 | + dsppos_reg_value[pipe] = I915_READ(dsppos_reg); | ||
| 23092 | + pipesrc_reg_value[pipe] = I915_READ(pipesrc_reg); | ||
| 23093 | + dspbase_value[pipe] = I915_READ(dspbase); | ||
| 23094 | + if(is_lvds) | ||
| 23095 | + lvds_reg_value[pipe] = I915_READ(LVDS); | ||
| 23096 | + vgacntrl_reg_value[pipe] = I915_READ(VGACNTRL); | ||
| 23097 | + pfit_control_reg_value[pipe] = I915_READ(PFIT_CONTROL); | ||
| 23098 | +} | ||
| 23099 | +#endif | ||
| 23100 | +#endif | ||
| 23101 | static void intel_crtc_mode_set(struct drm_crtc *crtc, | ||
| 23102 | struct drm_display_mode *mode, | ||
| 23103 | struct drm_display_mode *adjusted_mode, | ||
| 23104 | @@ -715,7 +860,7 @@ | ||
| 23105 | struct drm_framebuffer *old_fb) | ||
| 23106 | { | ||
| 23107 | struct drm_device *dev = crtc->dev; | ||
| 23108 | - struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 23109 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 23110 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 23111 | int pipe = intel_crtc->pipe; | ||
| 23112 | int fp_reg = (pipe == 0) ? FPA0 : FPB0; | ||
| 23113 | @@ -730,6 +875,7 @@ | ||
| 23114 | int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; | ||
| 23115 | int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; | ||
| 23116 | int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; | ||
| 23117 | + int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; | ||
| 23118 | int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; | ||
| 23119 | int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; | ||
| 23120 | int refclk; | ||
| 23121 | @@ -740,7 +886,10 @@ | ||
| 23122 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
| 23123 | struct drm_connector *connector; | ||
| 23124 | |||
| 23125 | - drm_vblank_pre_modeset(dev, pipe); | ||
| 23126 | + if (!crtc->fb) { | ||
| 23127 | + DRM_ERROR("Can't set mode without attached fb\n"); | ||
| 23128 | + return; | ||
| 23129 | + } | ||
| 23130 | |||
| 23131 | list_for_each_entry(connector, &mode_config->connector_list, head) { | ||
| 23132 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 23133 | @@ -784,13 +933,15 @@ | ||
| 23134 | |||
| 23135 | dpll = DPLL_VGA_MODE_DIS; | ||
| 23136 | if (IS_I9XX(dev)) { | ||
| 23137 | - if (is_lvds) | ||
| 23138 | + if (is_lvds) { | ||
| 23139 | dpll |= DPLLB_MODE_LVDS; | ||
| 23140 | - else | ||
| 23141 | + if (IS_POULSBO(dev)) | ||
| 23142 | + dpll |= DPLL_DVO_HIGH_SPEED; | ||
| 23143 | + } else | ||
| 23144 | dpll |= DPLLB_MODE_DAC_SERIAL; | ||
| 23145 | if (is_sdvo) { | ||
| 23146 | dpll |= DPLL_DVO_HIGH_SPEED; | ||
| 23147 | - if (IS_I945G(dev) || IS_I945GM(dev)) { | ||
| 23148 | + if (IS_I945G(dev) || IS_I945GM(dev) || IS_POULSBO(dev)) { | ||
| 23149 | int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; | ||
| 23150 | dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; | ||
| 23151 | } | ||
| 23152 | @@ -841,6 +992,25 @@ | ||
| 23153 | /* Set up the display plane register */ | ||
| 23154 | dspcntr = DISPPLANE_GAMMA_ENABLE; | ||
| 23155 | |||
| 23156 | + switch (crtc->fb->bits_per_pixel) { | ||
| 23157 | + case 8: | ||
| 23158 | + dspcntr |= DISPPLANE_8BPP; | ||
| 23159 | + break; | ||
| 23160 | + case 16: | ||
| 23161 | + if (crtc->fb->depth == 15) | ||
| 23162 | + dspcntr |= DISPPLANE_15_16BPP; | ||
| 23163 | + else | ||
| 23164 | + dspcntr |= DISPPLANE_16BPP; | ||
| 23165 | + break; | ||
| 23166 | + case 32: | ||
| 23167 | + dspcntr |= DISPPLANE_32BPP_NO_ALPHA; | ||
| 23168 | + break; | ||
| 23169 | + default: | ||
| 23170 | + DRM_ERROR("Unknown color depth\n"); | ||
| 23171 | + return; | ||
| 23172 | + } | ||
| 23173 | + | ||
| 23174 | + | ||
| 23175 | if (pipe == 0) | ||
| 23176 | dspcntr |= DISPPLANE_SEL_PIPE_A; | ||
| 23177 | else | ||
| 23178 | @@ -934,6 +1104,7 @@ | ||
| 23179 | ((adjusted_mode->crtc_vblank_end - 1) << 16)); | ||
| 23180 | I915_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | | ||
| 23181 | ((adjusted_mode->crtc_vsync_end - 1) << 16)); | ||
| 23182 | + I915_WRITE(dspstride_reg, crtc->fb->pitch); | ||
| 23183 | /* pipesrc and dspsize control the size that is scaled from, which should | ||
| 23184 | * always be the user's requested size. | ||
| 23185 | */ | ||
| 23186 | @@ -950,14 +1121,14 @@ | ||
| 23187 | /* Flush the plane changes */ | ||
| 23188 | intel_pipe_set_base(crtc, x, y, old_fb); | ||
| 23189 | |||
| 23190 | - drm_vblank_post_modeset(dev, pipe); | ||
| 23191 | + intel_wait_for_vblank(dev); | ||
| 23192 | } | ||
| 23193 | |||
| 23194 | /** Loads the palette/gamma unit for the CRTC with the prepared values */ | ||
| 23195 | void intel_crtc_load_lut(struct drm_crtc *crtc) | ||
| 23196 | { | ||
| 23197 | struct drm_device *dev = crtc->dev; | ||
| 23198 | - struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 23199 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 23200 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 23201 | int palreg = (intel_crtc->pipe == 0) ? PALETTE_A : PALETTE_B; | ||
| 23202 | int i; | ||
| 23203 | @@ -980,7 +1151,7 @@ | ||
| 23204 | uint32_t width, uint32_t height) | ||
| 23205 | { | ||
| 23206 | struct drm_device *dev = crtc->dev; | ||
| 23207 | - struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 23208 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 23209 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 23210 | struct drm_gem_object *bo; | ||
| 23211 | struct drm_i915_gem_object *obj_priv; | ||
| 23212 | @@ -1019,7 +1190,7 @@ | ||
| 23213 | ret = -ENOMEM; | ||
| 23214 | goto fail; | ||
| 23215 | } | ||
| 23216 | - | ||
| 23217 | +#if 0 | ||
| 23218 | /* we only need to pin inside GTT if cursor is non-phy */ | ||
| 23219 | if (!dev_priv->cursor_needs_physical) { | ||
| 23220 | ret = i915_gem_object_pin(bo, PAGE_SIZE); | ||
| 23221 | @@ -1036,7 +1207,7 @@ | ||
| 23222 | } | ||
| 23223 | addr = obj_priv->phys_obj->handle->busaddr; | ||
| 23224 | } | ||
| 23225 | - | ||
| 23226 | +#endif | ||
| 23227 | temp = 0; | ||
| 23228 | /* set the pipe for the cursor */ | ||
| 23229 | temp |= (pipe << 28); | ||
| 23230 | @@ -1047,6 +1218,7 @@ | ||
| 23231 | I915_WRITE(base, addr); | ||
| 23232 | |||
| 23233 | if (intel_crtc->cursor_bo) { | ||
| 23234 | +#if 0 | ||
| 23235 | if (dev_priv->cursor_needs_physical) { | ||
| 23236 | if (intel_crtc->cursor_bo != bo) | ||
| 23237 | i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo); | ||
| 23238 | @@ -1055,6 +1227,7 @@ | ||
| 23239 | mutex_lock(&dev->struct_mutex); | ||
| 23240 | drm_gem_object_unreference(intel_crtc->cursor_bo); | ||
| 23241 | mutex_unlock(&dev->struct_mutex); | ||
| 23242 | +#endif | ||
| 23243 | } | ||
| 23244 | |||
| 23245 | intel_crtc->cursor_addr = addr; | ||
| 23246 | @@ -1071,7 +1244,7 @@ | ||
| 23247 | static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) | ||
| 23248 | { | ||
| 23249 | struct drm_device *dev = crtc->dev; | ||
| 23250 | - struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 23251 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 23252 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 23253 | int pipe = intel_crtc->pipe; | ||
| 23254 | uint32_t temp = 0; | ||
| 23255 | @@ -1255,7 +1428,7 @@ | ||
| 23256 | /* Returns the clock of the currently programmed mode of the given pipe. */ | ||
| 23257 | static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) | ||
| 23258 | { | ||
| 23259 | - struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 23260 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 23261 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 23262 | int pipe = intel_crtc->pipe; | ||
| 23263 | u32 dpll = I915_READ((pipe == 0) ? DPLL_A : DPLL_B); | ||
| 23264 | @@ -1333,7 +1506,7 @@ | ||
| 23265 | struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, | ||
| 23266 | struct drm_crtc *crtc) | ||
| 23267 | { | ||
| 23268 | - struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 23269 | + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; | ||
| 23270 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 23271 | int pipe = intel_crtc->pipe; | ||
| 23272 | struct drm_display_mode *mode; | ||
| 23273 | @@ -1399,7 +1572,6 @@ | ||
| 23274 | |||
| 23275 | drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs); | ||
| 23276 | |||
| 23277 | - drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); | ||
| 23278 | intel_crtc->pipe = pipe; | ||
| 23279 | for (i = 0; i < 256; i++) { | ||
| 23280 | intel_crtc->lut_r[i] = i; | ||
| 23281 | @@ -1415,11 +1587,6 @@ | ||
| 23282 | intel_crtc->mode_set.connectors = (struct drm_connector **)(intel_crtc + 1); | ||
| 23283 | intel_crtc->mode_set.num_connectors = 0; | ||
| 23284 | |||
| 23285 | - if (i915_fbpercrtc) { | ||
| 23286 | - | ||
| 23287 | - | ||
| 23288 | - | ||
| 23289 | - } | ||
| 23290 | } | ||
| 23291 | |||
| 23292 | struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe) | ||
| 23293 | @@ -1454,27 +1621,17 @@ | ||
| 23294 | { | ||
| 23295 | struct drm_connector *connector; | ||
| 23296 | |||
| 23297 | - intel_crt_init(dev); | ||
| 23298 | + if (!IS_POULSBO(dev)) | ||
| 23299 | + intel_crt_init(dev); | ||
| 23300 | |||
| 23301 | /* Set up integrated LVDS */ | ||
| 23302 | if (IS_MOBILE(dev) && !IS_I830(dev)) | ||
| 23303 | intel_lvds_init(dev); | ||
| 23304 | |||
| 23305 | if (IS_I9XX(dev)) { | ||
| 23306 | - int found; | ||
| 23307 | - | ||
| 23308 | - found = intel_sdvo_init(dev, SDVOB); | ||
| 23309 | - if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) | ||
| 23310 | - intel_hdmi_init(dev, SDVOB); | ||
| 23311 | - | ||
| 23312 | - found = intel_sdvo_init(dev, SDVOC); | ||
| 23313 | - if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) | ||
| 23314 | - intel_hdmi_init(dev, SDVOC); | ||
| 23315 | - } else | ||
| 23316 | - intel_dvo_init(dev); | ||
| 23317 | - | ||
| 23318 | - if (IS_I9XX(dev) && IS_MOBILE(dev)) | ||
| 23319 | - intel_tv_init(dev); | ||
| 23320 | + intel_sdvo_init(dev, SDVOB); | ||
| 23321 | + intel_sdvo_init(dev, SDVOC); | ||
| 23322 | + } | ||
| 23323 | |||
| 23324 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 23325 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 23326 | @@ -1523,8 +1680,8 @@ | ||
| 23327 | struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); | ||
| 23328 | struct drm_device *dev = fb->dev; | ||
| 23329 | |||
| 23330 | - if (fb->fbdev) | ||
| 23331 | - intelfb_remove(dev, fb); | ||
| 23332 | + //if (fb->fbdev) | ||
| 23333 | + // intelfb_remove(dev, fb); | ||
| 23334 | |||
| 23335 | drm_framebuffer_cleanup(fb); | ||
| 23336 | mutex_lock(&dev->struct_mutex); | ||
| 23337 | @@ -1601,7 +1758,7 @@ | ||
| 23338 | |||
| 23339 | static const struct drm_mode_config_funcs intel_mode_funcs = { | ||
| 23340 | .fb_create = intel_user_framebuffer_create, | ||
| 23341 | - .fb_changed = intelfb_probe, | ||
| 23342 | +// .fb_changed = intelfb_probe, | ||
| 23343 | }; | ||
| 23344 | |||
| 23345 | void intel_modeset_init(struct drm_device *dev) | ||
| 23346 | @@ -1616,13 +1773,8 @@ | ||
| 23347 | |||
| 23348 | dev->mode_config.funcs = (void *)&intel_mode_funcs; | ||
| 23349 | |||
| 23350 | - if (IS_I965G(dev)) { | ||
| 23351 | - dev->mode_config.max_width = 8192; | ||
| 23352 | - dev->mode_config.max_height = 8192; | ||
| 23353 | - } else { | ||
| 23354 | - dev->mode_config.max_width = 2048; | ||
| 23355 | - dev->mode_config.max_height = 2048; | ||
| 23356 | - } | ||
| 23357 | + dev->mode_config.max_width = 2048; | ||
| 23358 | + dev->mode_config.max_height = 2048; | ||
| 23359 | |||
| 23360 | /* set memory base */ | ||
| 23361 | if (IS_I9XX(dev)) | ||
