diff options
author | Zhenyu Wang <zhenyuw@linux.intel.com> | 2009-06-05 03:38:42 -0400 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2009-06-05 07:34:51 -0400 |
commit | 2c07245fb8f7f0a282282e5a9747e46defdb2cc7 (patch) | |
tree | 101944c42c459c42c2d362efe9c3762aeece4f19 | |
parent | 2cce0d8740f0d1454d012401257d96c513ce358f (diff) |
drm/i915: enable kernel modesetting on IGDNG
This adds kernel mode setting on IGDNG with VGA output support.
Note that suspend/resume doesn't work yet.
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_crt.c | 76 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 603 |
3 files changed, 643 insertions, 38 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index fa105bd119a6..5d36059d6f4e 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -922,7 +922,7 @@ static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size, | |||
922 | * Some of the preallocated space is taken by the GTT | 922 | * Some of the preallocated space is taken by the GTT |
923 | * and popup. GTT is 1K per MB of aperture size, and popup is 4K. | 923 | * and popup. GTT is 1K per MB of aperture size, and popup is 4K. |
924 | */ | 924 | */ |
925 | if (IS_G4X(dev) || IS_IGD(dev)) | 925 | if (IS_G4X(dev) || IS_IGD(dev) || IS_IGDNG(dev)) |
926 | overhead = 4096; | 926 | overhead = 4096; |
927 | else | 927 | else |
928 | overhead = (*aperture_size / 1024) + 4096; | 928 | overhead = (*aperture_size / 1024) + 4096; |
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 640f5158effc..ff9bccad3871 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
@@ -37,9 +37,14 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode) | |||
37 | { | 37 | { |
38 | struct drm_device *dev = encoder->dev; | 38 | struct drm_device *dev = encoder->dev; |
39 | struct drm_i915_private *dev_priv = dev->dev_private; | 39 | struct drm_i915_private *dev_priv = dev->dev_private; |
40 | u32 temp; | 40 | u32 temp, reg; |
41 | 41 | ||
42 | temp = I915_READ(ADPA); | 42 | if (IS_IGDNG(dev)) |
43 | reg = PCH_ADPA; | ||
44 | else | ||
45 | reg = ADPA; | ||
46 | |||
47 | temp = I915_READ(reg); | ||
43 | temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); | 48 | temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); |
44 | temp |= ADPA_DAC_ENABLE; | 49 | temp |= ADPA_DAC_ENABLE; |
45 | 50 | ||
@@ -58,7 +63,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode) | |||
58 | break; | 63 | break; |
59 | } | 64 | } |
60 | 65 | ||
61 | I915_WRITE(ADPA, temp); | 66 | I915_WRITE(reg, temp); |
62 | } | 67 | } |
63 | 68 | ||
64 | static int intel_crt_mode_valid(struct drm_connector *connector, | 69 | static int intel_crt_mode_valid(struct drm_connector *connector, |
@@ -101,17 +106,23 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, | |||
101 | struct drm_i915_private *dev_priv = dev->dev_private; | 106 | struct drm_i915_private *dev_priv = dev->dev_private; |
102 | int dpll_md_reg; | 107 | int dpll_md_reg; |
103 | u32 adpa, dpll_md; | 108 | u32 adpa, dpll_md; |
109 | u32 adpa_reg; | ||
104 | 110 | ||
105 | if (intel_crtc->pipe == 0) | 111 | if (intel_crtc->pipe == 0) |
106 | dpll_md_reg = DPLL_A_MD; | 112 | dpll_md_reg = DPLL_A_MD; |
107 | else | 113 | else |
108 | dpll_md_reg = DPLL_B_MD; | 114 | dpll_md_reg = DPLL_B_MD; |
109 | 115 | ||
116 | if (IS_IGDNG(dev)) | ||
117 | adpa_reg = PCH_ADPA; | ||
118 | else | ||
119 | adpa_reg = ADPA; | ||
120 | |||
110 | /* | 121 | /* |
111 | * Disable separate mode multiplier used when cloning SDVO to CRT | 122 | * Disable separate mode multiplier used when cloning SDVO to CRT |
112 | * XXX this needs to be adjusted when we really are cloning | 123 | * XXX this needs to be adjusted when we really are cloning |
113 | */ | 124 | */ |
114 | if (IS_I965G(dev)) { | 125 | if (IS_I965G(dev) && !IS_IGDNG(dev)) { |
115 | dpll_md = I915_READ(dpll_md_reg); | 126 | dpll_md = I915_READ(dpll_md_reg); |
116 | I915_WRITE(dpll_md_reg, | 127 | I915_WRITE(dpll_md_reg, |
117 | dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); | 128 | dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); |
@@ -125,13 +136,53 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, | |||
125 | 136 | ||
126 | if (intel_crtc->pipe == 0) { | 137 | if (intel_crtc->pipe == 0) { |
127 | adpa |= ADPA_PIPE_A_SELECT; | 138 | adpa |= ADPA_PIPE_A_SELECT; |
128 | I915_WRITE(BCLRPAT_A, 0); | 139 | if (!IS_IGDNG(dev)) |
140 | I915_WRITE(BCLRPAT_A, 0); | ||
129 | } else { | 141 | } else { |
130 | adpa |= ADPA_PIPE_B_SELECT; | 142 | adpa |= ADPA_PIPE_B_SELECT; |
131 | I915_WRITE(BCLRPAT_B, 0); | 143 | if (!IS_IGDNG(dev)) |
144 | I915_WRITE(BCLRPAT_B, 0); | ||
132 | } | 145 | } |
133 | 146 | ||
134 | I915_WRITE(ADPA, adpa); | 147 | I915_WRITE(adpa_reg, adpa); |
148 | } | ||
149 | |||
150 | static bool intel_igdng_crt_detect_hotplug(struct drm_connector *connector) | ||
151 | { | ||
152 | struct drm_device *dev = connector->dev; | ||
153 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
154 | u32 adpa, temp; | ||
155 | bool ret; | ||
156 | |||
157 | temp = adpa = I915_READ(PCH_ADPA); | ||
158 | |||
159 | adpa &= ~ADPA_CRT_HOTPLUG_MASK; | ||
160 | |||
161 | adpa |= (ADPA_CRT_HOTPLUG_PERIOD_128 | | ||
162 | ADPA_CRT_HOTPLUG_WARMUP_10MS | | ||
163 | ADPA_CRT_HOTPLUG_SAMPLE_4S | | ||
164 | ADPA_CRT_HOTPLUG_VOLTAGE_50 | /* default */ | ||
165 | ADPA_CRT_HOTPLUG_VOLREF_325MV | | ||
166 | ADPA_CRT_HOTPLUG_ENABLE | | ||
167 | ADPA_CRT_HOTPLUG_FORCE_TRIGGER); | ||
168 | |||
169 | DRM_DEBUG("pch crt adpa 0x%x", adpa); | ||
170 | I915_WRITE(PCH_ADPA, adpa); | ||
171 | |||
172 | /* This might not be needed as not specified in spec...*/ | ||
173 | udelay(1000); | ||
174 | |||
175 | /* Check the status to see if both blue and green are on now */ | ||
176 | adpa = I915_READ(PCH_ADPA); | ||
177 | if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) == | ||
178 | ADPA_CRT_HOTPLUG_MONITOR_COLOR) | ||
179 | ret = true; | ||
180 | else | ||
181 | ret = false; | ||
182 | |||
183 | /* restore origin register */ | ||
184 | I915_WRITE(PCH_ADPA, temp); | ||
185 | return ret; | ||
135 | } | 186 | } |
136 | 187 | ||
137 | /** | 188 | /** |
@@ -148,6 +199,10 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) | |||
148 | struct drm_i915_private *dev_priv = dev->dev_private; | 199 | struct drm_i915_private *dev_priv = dev->dev_private; |
149 | u32 hotplug_en; | 200 | u32 hotplug_en; |
150 | int i, tries = 0; | 201 | int i, tries = 0; |
202 | |||
203 | if (IS_IGDNG(dev)) | ||
204 | return intel_igdng_crt_detect_hotplug(connector); | ||
205 | |||
151 | /* | 206 | /* |
152 | * On 4 series desktop, CRT detect sequence need to be done twice | 207 | * On 4 series desktop, CRT detect sequence need to be done twice |
153 | * to get a reliable result. | 208 | * to get a reliable result. |
@@ -427,6 +482,7 @@ void intel_crt_init(struct drm_device *dev) | |||
427 | { | 482 | { |
428 | struct drm_connector *connector; | 483 | struct drm_connector *connector; |
429 | struct intel_output *intel_output; | 484 | struct intel_output *intel_output; |
485 | u32 i2c_reg; | ||
430 | 486 | ||
431 | intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL); | 487 | intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL); |
432 | if (!intel_output) | 488 | if (!intel_output) |
@@ -443,7 +499,11 @@ void intel_crt_init(struct drm_device *dev) | |||
443 | &intel_output->enc); | 499 | &intel_output->enc); |
444 | 500 | ||
445 | /* Set up the DDC bus. */ | 501 | /* Set up the DDC bus. */ |
446 | intel_output->ddc_bus = intel_i2c_create(dev, GPIOA, "CRTDDC_A"); | 502 | if (IS_IGDNG(dev)) |
503 | i2c_reg = PCH_GPIOA; | ||
504 | else | ||
505 | i2c_reg = GPIOA; | ||
506 | intel_output->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A"); | ||
447 | if (!intel_output->ddc_bus) { | 507 | if (!intel_output->ddc_bus) { |
448 | dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " | 508 | dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " |
449 | "failed.\n"); | 509 | "failed.\n"); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c9d6f10ba92e..2cd6ba6523d8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -137,6 +137,8 @@ struct intel_limit { | |||
137 | #define INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS 7 | 137 | #define INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS 7 |
138 | #define INTEL_LIMIT_IGD_SDVO_DAC 8 | 138 | #define INTEL_LIMIT_IGD_SDVO_DAC 8 |
139 | #define INTEL_LIMIT_IGD_LVDS 9 | 139 | #define INTEL_LIMIT_IGD_LVDS 9 |
140 | #define INTEL_LIMIT_IGDNG_SDVO_DAC 10 | ||
141 | #define INTEL_LIMIT_IGDNG_LVDS 11 | ||
140 | 142 | ||
141 | /*The parameter is for SDVO on G4x platform*/ | 143 | /*The parameter is for SDVO on G4x platform*/ |
142 | #define G4X_DOT_SDVO_MIN 25000 | 144 | #define G4X_DOT_SDVO_MIN 25000 |
@@ -216,12 +218,43 @@ struct intel_limit { | |||
216 | #define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7 | 218 | #define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7 |
217 | #define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0 | 219 | #define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0 |
218 | 220 | ||
221 | /* IGDNG */ | ||
222 | /* as we calculate clock using (register_value + 2) for | ||
223 | N/M1/M2, so here the range value for them is (actual_value-2). | ||
224 | */ | ||
225 | #define IGDNG_DOT_MIN 25000 | ||
226 | #define IGDNG_DOT_MAX 350000 | ||
227 | #define IGDNG_VCO_MIN 1760000 | ||
228 | #define IGDNG_VCO_MAX 3510000 | ||
229 | #define IGDNG_N_MIN 1 | ||
230 | #define IGDNG_N_MAX 5 | ||
231 | #define IGDNG_M_MIN 79 | ||
232 | #define IGDNG_M_MAX 118 | ||
233 | #define IGDNG_M1_MIN 12 | ||
234 | #define IGDNG_M1_MAX 23 | ||
235 | #define IGDNG_M2_MIN 5 | ||
236 | #define IGDNG_M2_MAX 9 | ||
237 | #define IGDNG_P_SDVO_DAC_MIN 5 | ||
238 | #define IGDNG_P_SDVO_DAC_MAX 80 | ||
239 | #define IGDNG_P_LVDS_MIN 28 | ||
240 | #define IGDNG_P_LVDS_MAX 112 | ||
241 | #define IGDNG_P1_MIN 1 | ||
242 | #define IGDNG_P1_MAX 8 | ||
243 | #define IGDNG_P2_SDVO_DAC_SLOW 10 | ||
244 | #define IGDNG_P2_SDVO_DAC_FAST 5 | ||
245 | #define IGDNG_P2_LVDS_SLOW 14 /* single channel */ | ||
246 | #define IGDNG_P2_LVDS_FAST 7 /* double channel */ | ||
247 | #define IGDNG_P2_DOT_LIMIT 225000 /* 225Mhz */ | ||
248 | |||
219 | static bool | 249 | static bool |
220 | intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 250 | intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, |
221 | int target, int refclk, intel_clock_t *best_clock); | 251 | int target, int refclk, intel_clock_t *best_clock); |
222 | static bool | 252 | static bool |
223 | intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 253 | intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, |
224 | int target, int refclk, intel_clock_t *best_clock); | 254 | int target, int refclk, intel_clock_t *best_clock); |
255 | static bool | ||
256 | intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | ||
257 | int target, int refclk, intel_clock_t *best_clock); | ||
225 | 258 | ||
226 | static const intel_limit_t intel_limits[] = { | 259 | static const intel_limit_t intel_limits[] = { |
227 | { /* INTEL_LIMIT_I8XX_DVO_DAC */ | 260 | { /* INTEL_LIMIT_I8XX_DVO_DAC */ |
@@ -383,9 +416,47 @@ static const intel_limit_t intel_limits[] = { | |||
383 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, | 416 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, |
384 | .find_pll = intel_find_best_PLL, | 417 | .find_pll = intel_find_best_PLL, |
385 | }, | 418 | }, |
386 | 419 | { /* INTEL_LIMIT_IGDNG_SDVO_DAC */ | |
420 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, | ||
421 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, | ||
422 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, | ||
423 | .m = { .min = IGDNG_M_MIN, .max = IGDNG_M_MAX }, | ||
424 | .m1 = { .min = IGDNG_M1_MIN, .max = IGDNG_M1_MAX }, | ||
425 | .m2 = { .min = IGDNG_M2_MIN, .max = IGDNG_M2_MAX }, | ||
426 | .p = { .min = IGDNG_P_SDVO_DAC_MIN, .max = IGDNG_P_SDVO_DAC_MAX }, | ||
427 | .p1 = { .min = IGDNG_P1_MIN, .max = IGDNG_P1_MAX }, | ||
428 | .p2 = { .dot_limit = IGDNG_P2_DOT_LIMIT, | ||
429 | .p2_slow = IGDNG_P2_SDVO_DAC_SLOW, | ||
430 | .p2_fast = IGDNG_P2_SDVO_DAC_FAST }, | ||
431 | .find_pll = intel_igdng_find_best_PLL, | ||
432 | }, | ||
433 | { /* INTEL_LIMIT_IGDNG_LVDS */ | ||
434 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, | ||
435 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, | ||
436 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, | ||
437 | .m = { .min = IGDNG_M_MIN, .max = IGDNG_M_MAX }, | ||
438 | .m1 = { .min = IGDNG_M1_MIN, .max = IGDNG_M1_MAX }, | ||
439 | .m2 = { .min = IGDNG_M2_MIN, .max = IGDNG_M2_MAX }, | ||
440 | .p = { .min = IGDNG_P_LVDS_MIN, .max = IGDNG_P_LVDS_MAX }, | ||
441 | .p1 = { .min = IGDNG_P1_MIN, .max = IGDNG_P1_MAX }, | ||
442 | .p2 = { .dot_limit = IGDNG_P2_DOT_LIMIT, | ||
443 | .p2_slow = IGDNG_P2_LVDS_SLOW, | ||
444 | .p2_fast = IGDNG_P2_LVDS_FAST }, | ||
445 | .find_pll = intel_igdng_find_best_PLL, | ||
446 | }, | ||
387 | }; | 447 | }; |
388 | 448 | ||
449 | static const intel_limit_t *intel_igdng_limit(struct drm_crtc *crtc) | ||
450 | { | ||
451 | const intel_limit_t *limit; | ||
452 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | ||
453 | limit = &intel_limits[INTEL_LIMIT_IGDNG_LVDS]; | ||
454 | else | ||
455 | limit = &intel_limits[INTEL_LIMIT_IGDNG_SDVO_DAC]; | ||
456 | |||
457 | return limit; | ||
458 | } | ||
459 | |||
389 | static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc) | 460 | static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc) |
390 | { | 461 | { |
391 | struct drm_device *dev = crtc->dev; | 462 | struct drm_device *dev = crtc->dev; |
@@ -418,7 +489,9 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc) | |||
418 | struct drm_device *dev = crtc->dev; | 489 | struct drm_device *dev = crtc->dev; |
419 | const intel_limit_t *limit; | 490 | const intel_limit_t *limit; |
420 | 491 | ||
421 | if (IS_G4X(dev)) { | 492 | if (IS_IGDNG(dev)) |
493 | limit = intel_igdng_limit(crtc); | ||
494 | else if (IS_G4X(dev)) { | ||
422 | limit = intel_g4x_limit(crtc); | 495 | limit = intel_g4x_limit(crtc); |
423 | } else if (IS_I9XX(dev) && !IS_IGD(dev)) { | 496 | } else if (IS_I9XX(dev) && !IS_IGD(dev)) { |
424 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 497 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
@@ -630,7 +703,64 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | |||
630 | } | 703 | } |
631 | } | 704 | } |
632 | } | 705 | } |
706 | return found; | ||
707 | } | ||
708 | |||
709 | static bool | ||
710 | intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | ||
711 | int target, int refclk, intel_clock_t *best_clock) | ||
712 | { | ||
713 | struct drm_device *dev = crtc->dev; | ||
714 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
715 | intel_clock_t clock; | ||
716 | int max_n; | ||
717 | bool found; | ||
718 | int err_most = 47; | ||
719 | found = false; | ||
720 | |||
721 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { | ||
722 | if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == | ||
723 | LVDS_CLKB_POWER_UP) | ||
724 | clock.p2 = limit->p2.p2_fast; | ||
725 | else | ||
726 | clock.p2 = limit->p2.p2_slow; | ||
727 | } else { | ||
728 | if (target < limit->p2.dot_limit) | ||
729 | clock.p2 = limit->p2.p2_slow; | ||
730 | else | ||
731 | clock.p2 = limit->p2.p2_fast; | ||
732 | } | ||
733 | |||
734 | memset(best_clock, 0, sizeof(*best_clock)); | ||
735 | max_n = limit->n.max; | ||
736 | /* based on hardware requriment prefer smaller n to precision */ | ||
737 | for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) { | ||
738 | /* based on hardware requirment prefere larger m1,m2, p1 */ | ||
739 | for (clock.m1 = limit->m1.max; | ||
740 | clock.m1 >= limit->m1.min; clock.m1--) { | ||
741 | for (clock.m2 = limit->m2.max; | ||
742 | clock.m2 >= limit->m2.min; clock.m2--) { | ||
743 | for (clock.p1 = limit->p1.max; | ||
744 | clock.p1 >= limit->p1.min; clock.p1--) { | ||
745 | int this_err; | ||
633 | 746 | ||
747 | intel_clock(dev, refclk, &clock); | ||
748 | if (!intel_PLL_is_valid(crtc, &clock)) | ||
749 | continue; | ||
750 | this_err = abs((10000 - (target*10000/clock.dot))); | ||
751 | if (this_err < err_most) { | ||
752 | *best_clock = clock; | ||
753 | err_most = this_err; | ||
754 | max_n = clock.n; | ||
755 | found = true; | ||
756 | /* found on first matching */ | ||
757 | goto out; | ||
758 | } | ||
759 | } | ||
760 | } | ||
761 | } | ||
762 | } | ||
763 | out: | ||
634 | return found; | 764 | return found; |
635 | } | 765 | } |
636 | 766 | ||
@@ -785,18 +915,292 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
785 | return 0; | 915 | return 0; |
786 | } | 916 | } |
787 | 917 | ||
918 | static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) | ||
919 | { | ||
920 | struct drm_device *dev = crtc->dev; | ||
921 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
922 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
923 | int pipe = intel_crtc->pipe; | ||
924 | int plane = intel_crtc->pipe; | ||
925 | int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B; | ||
926 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | ||
927 | int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; | ||
928 | int dspbase_reg = (plane == 0) ? DSPAADDR : DSPBADDR; | ||
929 | int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL; | ||
930 | int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL; | ||
931 | int fdi_rx_iir_reg = (pipe == 0) ? FDI_RXA_IIR : FDI_RXB_IIR; | ||
932 | int fdi_rx_imr_reg = (pipe == 0) ? FDI_RXA_IMR : FDI_RXB_IMR; | ||
933 | int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF; | ||
934 | int pf_ctl_reg = (pipe == 0) ? PFA_CTL_1 : PFB_CTL_1; | ||
935 | int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; | ||
936 | int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; | ||
937 | int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; | ||
938 | int cpu_vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; | ||
939 | int cpu_vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; | ||
940 | int cpu_vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; | ||
941 | int trans_htot_reg = (pipe == 0) ? TRANS_HTOTAL_A : TRANS_HTOTAL_B; | ||
942 | int trans_hblank_reg = (pipe == 0) ? TRANS_HBLANK_A : TRANS_HBLANK_B; | ||
943 | int trans_hsync_reg = (pipe == 0) ? TRANS_HSYNC_A : TRANS_HSYNC_B; | ||
944 | int trans_vtot_reg = (pipe == 0) ? TRANS_VTOTAL_A : TRANS_VTOTAL_B; | ||
945 | int trans_vblank_reg = (pipe == 0) ? TRANS_VBLANK_A : TRANS_VBLANK_B; | ||
946 | int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B; | ||
947 | u32 temp; | ||
948 | int tries = 5, j; | ||
788 | 949 | ||
950 | /* XXX: When our outputs are all unaware of DPMS modes other than off | ||
951 | * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. | ||
952 | */ | ||
953 | switch (mode) { | ||
954 | case DRM_MODE_DPMS_ON: | ||
955 | case DRM_MODE_DPMS_STANDBY: | ||
956 | case DRM_MODE_DPMS_SUSPEND: | ||
957 | DRM_DEBUG("crtc %d dpms on\n", pipe); | ||
958 | /* enable PCH DPLL */ | ||
959 | temp = I915_READ(pch_dpll_reg); | ||
960 | if ((temp & DPLL_VCO_ENABLE) == 0) { | ||
961 | I915_WRITE(pch_dpll_reg, temp | DPLL_VCO_ENABLE); | ||
962 | I915_READ(pch_dpll_reg); | ||
963 | } | ||
789 | 964 | ||
790 | /** | 965 | /* enable PCH FDI RX PLL, wait warmup plus DMI latency */ |
791 | * Sets the power management mode of the pipe and plane. | 966 | temp = I915_READ(fdi_rx_reg); |
792 | * | 967 | I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE | |
793 | * This code should probably grow support for turning the cursor off and back | 968 | FDI_SEL_PCDCLK | |
794 | * on appropriately at the same time as we're turning the pipe off/on. | 969 | FDI_DP_PORT_WIDTH_X4); /* default 4 lanes */ |
795 | */ | 970 | I915_READ(fdi_rx_reg); |
796 | static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) | 971 | udelay(200); |
972 | |||
973 | /* Enable CPU FDI TX PLL, always on for IGDNG */ | ||
974 | temp = I915_READ(fdi_tx_reg); | ||
975 | if ((temp & FDI_TX_PLL_ENABLE) == 0) { | ||
976 | I915_WRITE(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE); | ||
977 | I915_READ(fdi_tx_reg); | ||
978 | udelay(100); | ||
979 | } | ||
980 | |||
981 | /* Enable CPU pipe */ | ||
982 | temp = I915_READ(pipeconf_reg); | ||
983 | if ((temp & PIPEACONF_ENABLE) == 0) { | ||
984 | I915_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); | ||
985 | I915_READ(pipeconf_reg); | ||
986 | udelay(100); | ||
987 | } | ||
988 | |||
989 | /* configure and enable CPU plane */ | ||
990 | temp = I915_READ(dspcntr_reg); | ||
991 | if ((temp & DISPLAY_PLANE_ENABLE) == 0) { | ||
992 | I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); | ||
993 | /* Flush the plane changes */ | ||
994 | I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); | ||
995 | } | ||
996 | |||
997 | /* enable CPU FDI TX and PCH FDI RX */ | ||
998 | temp = I915_READ(fdi_tx_reg); | ||
999 | temp |= FDI_TX_ENABLE; | ||
1000 | temp |= FDI_DP_PORT_WIDTH_X4; /* default */ | ||
1001 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
1002 | temp |= FDI_LINK_TRAIN_PATTERN_1; | ||
1003 | I915_WRITE(fdi_tx_reg, temp); | ||
1004 | I915_READ(fdi_tx_reg); | ||
1005 | |||
1006 | temp = I915_READ(fdi_rx_reg); | ||
1007 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
1008 | temp |= FDI_LINK_TRAIN_PATTERN_1; | ||
1009 | I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENABLE); | ||
1010 | I915_READ(fdi_rx_reg); | ||
1011 | |||
1012 | udelay(150); | ||
1013 | |||
1014 | /* Train FDI. */ | ||
1015 | /* umask FDI RX Interrupt symbol_lock and bit_lock bit | ||
1016 | for train result */ | ||
1017 | temp = I915_READ(fdi_rx_imr_reg); | ||
1018 | temp &= ~FDI_RX_SYMBOL_LOCK; | ||
1019 | temp &= ~FDI_RX_BIT_LOCK; | ||
1020 | I915_WRITE(fdi_rx_imr_reg, temp); | ||
1021 | I915_READ(fdi_rx_imr_reg); | ||
1022 | udelay(150); | ||
1023 | |||
1024 | temp = I915_READ(fdi_rx_iir_reg); | ||
1025 | DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp); | ||
1026 | |||
1027 | if ((temp & FDI_RX_BIT_LOCK) == 0) { | ||
1028 | for (j = 0; j < tries; j++) { | ||
1029 | temp = I915_READ(fdi_rx_iir_reg); | ||
1030 | DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp); | ||
1031 | if (temp & FDI_RX_BIT_LOCK) | ||
1032 | break; | ||
1033 | udelay(200); | ||
1034 | } | ||
1035 | if (j != tries) | ||
1036 | I915_WRITE(fdi_rx_iir_reg, | ||
1037 | temp | FDI_RX_BIT_LOCK); | ||
1038 | else | ||
1039 | DRM_DEBUG("train 1 fail\n"); | ||
1040 | } else { | ||
1041 | I915_WRITE(fdi_rx_iir_reg, | ||
1042 | temp | FDI_RX_BIT_LOCK); | ||
1043 | DRM_DEBUG("train 1 ok 2!\n"); | ||
1044 | } | ||
1045 | temp = I915_READ(fdi_tx_reg); | ||
1046 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
1047 | temp |= FDI_LINK_TRAIN_PATTERN_2; | ||
1048 | I915_WRITE(fdi_tx_reg, temp); | ||
1049 | |||
1050 | temp = I915_READ(fdi_rx_reg); | ||
1051 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
1052 | temp |= FDI_LINK_TRAIN_PATTERN_2; | ||
1053 | I915_WRITE(fdi_rx_reg, temp); | ||
1054 | |||
1055 | udelay(150); | ||
1056 | |||
1057 | temp = I915_READ(fdi_rx_iir_reg); | ||
1058 | DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp); | ||
1059 | |||
1060 | if ((temp & FDI_RX_SYMBOL_LOCK) == 0) { | ||
1061 | for (j = 0; j < tries; j++) { | ||
1062 | temp = I915_READ(fdi_rx_iir_reg); | ||
1063 | DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp); | ||
1064 | if (temp & FDI_RX_SYMBOL_LOCK) | ||
1065 | break; | ||
1066 | udelay(200); | ||
1067 | } | ||
1068 | if (j != tries) { | ||
1069 | I915_WRITE(fdi_rx_iir_reg, | ||
1070 | temp | FDI_RX_SYMBOL_LOCK); | ||
1071 | DRM_DEBUG("train 2 ok 1!\n"); | ||
1072 | } else | ||
1073 | DRM_DEBUG("train 2 fail\n"); | ||
1074 | } else { | ||
1075 | I915_WRITE(fdi_rx_iir_reg, temp | FDI_RX_SYMBOL_LOCK); | ||
1076 | DRM_DEBUG("train 2 ok 2!\n"); | ||
1077 | } | ||
1078 | DRM_DEBUG("train done\n"); | ||
1079 | |||
1080 | /* set transcoder timing */ | ||
1081 | I915_WRITE(trans_htot_reg, I915_READ(cpu_htot_reg)); | ||
1082 | I915_WRITE(trans_hblank_reg, I915_READ(cpu_hblank_reg)); | ||
1083 | I915_WRITE(trans_hsync_reg, I915_READ(cpu_hsync_reg)); | ||
1084 | |||
1085 | I915_WRITE(trans_vtot_reg, I915_READ(cpu_vtot_reg)); | ||
1086 | I915_WRITE(trans_vblank_reg, I915_READ(cpu_vblank_reg)); | ||
1087 | I915_WRITE(trans_vsync_reg, I915_READ(cpu_vsync_reg)); | ||
1088 | |||
1089 | /* enable PCH transcoder */ | ||
1090 | temp = I915_READ(transconf_reg); | ||
1091 | I915_WRITE(transconf_reg, temp | TRANS_ENABLE); | ||
1092 | I915_READ(transconf_reg); | ||
1093 | |||
1094 | while ((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) == 0) | ||
1095 | ; | ||
1096 | |||
1097 | /* enable normal */ | ||
1098 | |||
1099 | temp = I915_READ(fdi_tx_reg); | ||
1100 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
1101 | I915_WRITE(fdi_tx_reg, temp | FDI_LINK_TRAIN_NONE | | ||
1102 | FDI_TX_ENHANCE_FRAME_ENABLE); | ||
1103 | I915_READ(fdi_tx_reg); | ||
1104 | |||
1105 | temp = I915_READ(fdi_rx_reg); | ||
1106 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
1107 | I915_WRITE(fdi_rx_reg, temp | FDI_LINK_TRAIN_NONE | | ||
1108 | FDI_RX_ENHANCE_FRAME_ENABLE); | ||
1109 | I915_READ(fdi_rx_reg); | ||
1110 | |||
1111 | /* wait one idle pattern time */ | ||
1112 | udelay(100); | ||
1113 | |||
1114 | intel_crtc_load_lut(crtc); | ||
1115 | |||
1116 | break; | ||
1117 | case DRM_MODE_DPMS_OFF: | ||
1118 | DRM_DEBUG("crtc %d dpms off\n", pipe); | ||
1119 | |||
1120 | /* Disable the VGA plane that we never use */ | ||
1121 | I915_WRITE(CPU_VGACNTRL, VGA_DISP_DISABLE); | ||
1122 | |||
1123 | /* Disable display plane */ | ||
1124 | temp = I915_READ(dspcntr_reg); | ||
1125 | if ((temp & DISPLAY_PLANE_ENABLE) != 0) { | ||
1126 | I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); | ||
1127 | /* Flush the plane changes */ | ||
1128 | I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); | ||
1129 | I915_READ(dspbase_reg); | ||
1130 | } | ||
1131 | |||
1132 | /* disable cpu pipe, disable after all planes disabled */ | ||
1133 | temp = I915_READ(pipeconf_reg); | ||
1134 | if ((temp & PIPEACONF_ENABLE) != 0) { | ||
1135 | I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); | ||
1136 | I915_READ(pipeconf_reg); | ||
1137 | /* wait for cpu pipe off, pipe state */ | ||
1138 | while ((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) != 0) | ||
1139 | ; | ||
1140 | } else | ||
1141 | DRM_DEBUG("crtc %d is disabled\n", pipe); | ||
1142 | |||
1143 | /* IGDNG-A : disable cpu panel fitter ? */ | ||
1144 | temp = I915_READ(pf_ctl_reg); | ||
1145 | if ((temp & PF_ENABLE) != 0) { | ||
1146 | I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE); | ||
1147 | I915_READ(pf_ctl_reg); | ||
1148 | } | ||
1149 | |||
1150 | /* disable CPU FDI tx and PCH FDI rx */ | ||
1151 | temp = I915_READ(fdi_tx_reg); | ||
1152 | I915_WRITE(fdi_tx_reg, temp & ~FDI_TX_ENABLE); | ||
1153 | I915_READ(fdi_tx_reg); | ||
1154 | |||
1155 | temp = I915_READ(fdi_rx_reg); | ||
1156 | I915_WRITE(fdi_rx_reg, temp & ~FDI_RX_ENABLE); | ||
1157 | I915_READ(fdi_rx_reg); | ||
1158 | |||
1159 | /* still set train pattern 1 */ | ||
1160 | temp = I915_READ(fdi_tx_reg); | ||
1161 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
1162 | temp |= FDI_LINK_TRAIN_PATTERN_1; | ||
1163 | I915_WRITE(fdi_tx_reg, temp); | ||
1164 | |||
1165 | temp = I915_READ(fdi_rx_reg); | ||
1166 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
1167 | temp |= FDI_LINK_TRAIN_PATTERN_1; | ||
1168 | I915_WRITE(fdi_rx_reg, temp); | ||
1169 | |||
1170 | /* disable PCH transcoder */ | ||
1171 | temp = I915_READ(transconf_reg); | ||
1172 | if ((temp & TRANS_ENABLE) != 0) { | ||
1173 | I915_WRITE(transconf_reg, temp & ~TRANS_ENABLE); | ||
1174 | I915_READ(transconf_reg); | ||
1175 | /* wait for PCH transcoder off, transcoder state */ | ||
1176 | while ((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) != 0) | ||
1177 | ; | ||
1178 | } | ||
1179 | |||
1180 | /* disable PCH DPLL */ | ||
1181 | temp = I915_READ(pch_dpll_reg); | ||
1182 | if ((temp & DPLL_VCO_ENABLE) != 0) { | ||
1183 | I915_WRITE(pch_dpll_reg, temp & ~DPLL_VCO_ENABLE); | ||
1184 | I915_READ(pch_dpll_reg); | ||
1185 | } | ||
1186 | |||
1187 | temp = I915_READ(fdi_rx_reg); | ||
1188 | if ((temp & FDI_RX_PLL_ENABLE) != 0) { | ||
1189 | temp &= ~FDI_SEL_PCDCLK; | ||
1190 | temp &= ~FDI_RX_PLL_ENABLE; | ||
1191 | I915_WRITE(fdi_rx_reg, temp); | ||
1192 | I915_READ(fdi_rx_reg); | ||
1193 | } | ||
1194 | |||
1195 | /* Wait for the clocks to turn off. */ | ||
1196 | udelay(150); | ||
1197 | break; | ||
1198 | } | ||
1199 | } | ||
1200 | |||
1201 | static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) | ||
797 | { | 1202 | { |
798 | struct drm_device *dev = crtc->dev; | 1203 | struct drm_device *dev = crtc->dev; |
799 | struct drm_i915_master_private *master_priv; | ||
800 | struct drm_i915_private *dev_priv = dev->dev_private; | 1204 | struct drm_i915_private *dev_priv = dev->dev_private; |
801 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 1205 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
802 | int pipe = intel_crtc->pipe; | 1206 | int pipe = intel_crtc->pipe; |
@@ -805,7 +1209,6 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
805 | int dspbase_reg = (pipe == 0) ? DSPAADDR : DSPBADDR; | 1209 | int dspbase_reg = (pipe == 0) ? DSPAADDR : DSPBADDR; |
806 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | 1210 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; |
807 | u32 temp; | 1211 | u32 temp; |
808 | bool enabled; | ||
809 | 1212 | ||
810 | /* XXX: When our outputs are all unaware of DPMS modes other than off | 1213 | /* XXX: When our outputs are all unaware of DPMS modes other than off |
811 | * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. | 1214 | * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. |
@@ -890,6 +1293,26 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
890 | udelay(150); | 1293 | udelay(150); |
891 | break; | 1294 | break; |
892 | } | 1295 | } |
1296 | } | ||
1297 | |||
1298 | /** | ||
1299 | * Sets the power management mode of the pipe and plane. | ||
1300 | * | ||
1301 | * This code should probably grow support for turning the cursor off and back | ||
1302 | * on appropriately at the same time as we're turning the pipe off/on. | ||
1303 | */ | ||
1304 | static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) | ||
1305 | { | ||
1306 | struct drm_device *dev = crtc->dev; | ||
1307 | struct drm_i915_master_private *master_priv; | ||
1308 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
1309 | int pipe = intel_crtc->pipe; | ||
1310 | bool enabled; | ||
1311 | |||
1312 | if (IS_IGDNG(dev)) | ||
1313 | igdng_crtc_dpms(crtc, mode); | ||
1314 | else | ||
1315 | i9xx_crtc_dpms(crtc, mode); | ||
893 | 1316 | ||
894 | if (!dev->primary->master) | 1317 | if (!dev->primary->master) |
895 | return; | 1318 | return; |
@@ -947,6 +1370,12 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, | |||
947 | struct drm_display_mode *mode, | 1370 | struct drm_display_mode *mode, |
948 | struct drm_display_mode *adjusted_mode) | 1371 | struct drm_display_mode *adjusted_mode) |
949 | { | 1372 | { |
1373 | struct drm_device *dev = crtc->dev; | ||
1374 | if (IS_IGDNG(dev)) { | ||
1375 | /* FDI link clock is fixed at 2.7G */ | ||
1376 | if (mode->clock * 3 > 27000 * 4) | ||
1377 | return MODE_CLOCK_HIGH; | ||
1378 | } | ||
950 | return true; | 1379 | return true; |
951 | } | 1380 | } |
952 | 1381 | ||
@@ -1030,6 +1459,48 @@ static int intel_panel_fitter_pipe (struct drm_device *dev) | |||
1030 | return 1; | 1459 | return 1; |
1031 | } | 1460 | } |
1032 | 1461 | ||
1462 | struct fdi_m_n { | ||
1463 | u32 tu; | ||
1464 | u32 gmch_m; | ||
1465 | u32 gmch_n; | ||
1466 | u32 link_m; | ||
1467 | u32 link_n; | ||
1468 | }; | ||
1469 | |||
1470 | static void | ||
1471 | fdi_reduce_ratio(u32 *num, u32 *den) | ||
1472 | { | ||
1473 | while (*num > 0xffffff || *den > 0xffffff) { | ||
1474 | *num >>= 1; | ||
1475 | *den >>= 1; | ||
1476 | } | ||
1477 | } | ||
1478 | |||
1479 | #define DATA_N 0x800000 | ||
1480 | #define LINK_N 0x80000 | ||
1481 | |||
1482 | static void | ||
1483 | igdng_compute_m_n(int bytes_per_pixel, int nlanes, | ||
1484 | int pixel_clock, int link_clock, | ||
1485 | struct fdi_m_n *m_n) | ||
1486 | { | ||
1487 | u64 temp; | ||
1488 | |||
1489 | m_n->tu = 64; /* default size */ | ||
1490 | |||
1491 | temp = (u64) DATA_N * pixel_clock; | ||
1492 | temp = div_u64(temp, link_clock); | ||
1493 | m_n->gmch_m = (temp * bytes_per_pixel) / nlanes; | ||
1494 | m_n->gmch_n = DATA_N; | ||
1495 | fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); | ||
1496 | |||
1497 | temp = (u64) LINK_N * pixel_clock; | ||
1498 | m_n->link_m = div_u64(temp, link_clock); | ||
1499 | m_n->link_n = LINK_N; | ||
1500 | fdi_reduce_ratio(&m_n->link_m, &m_n->link_n); | ||
1501 | } | ||
1502 | |||
1503 | |||
1033 | static int intel_crtc_mode_set(struct drm_crtc *crtc, | 1504 | static int intel_crtc_mode_set(struct drm_crtc *crtc, |
1034 | struct drm_display_mode *mode, | 1505 | struct drm_display_mode *mode, |
1035 | struct drm_display_mode *adjusted_mode, | 1506 | struct drm_display_mode *adjusted_mode, |
@@ -1063,6 +1534,16 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1063 | struct drm_connector *connector; | 1534 | struct drm_connector *connector; |
1064 | const intel_limit_t *limit; | 1535 | const intel_limit_t *limit; |
1065 | int ret; | 1536 | int ret; |
1537 | struct fdi_m_n m_n = {0}; | ||
1538 | int data_m1_reg = (pipe == 0) ? PIPEA_DATA_M1 : PIPEB_DATA_M1; | ||
1539 | int data_n1_reg = (pipe == 0) ? PIPEA_DATA_N1 : PIPEB_DATA_N1; | ||
1540 | int link_m1_reg = (pipe == 0) ? PIPEA_LINK_M1 : PIPEB_LINK_M1; | ||
1541 | int link_n1_reg = (pipe == 0) ? PIPEA_LINK_N1 : PIPEB_LINK_N1; | ||
1542 | int pch_fp_reg = (pipe == 0) ? PCH_FPA0 : PCH_FPB0; | ||
1543 | int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B; | ||
1544 | int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL; | ||
1545 | u32 temp; | ||
1546 | int sdvo_pixel_multiply; | ||
1066 | 1547 | ||
1067 | drm_vblank_pre_modeset(dev, pipe); | 1548 | drm_vblank_pre_modeset(dev, pipe); |
1068 | 1549 | ||
@@ -1101,6 +1582,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1101 | DRM_DEBUG("using SSC reference clock of %d MHz\n", refclk / 1000); | 1582 | DRM_DEBUG("using SSC reference clock of %d MHz\n", refclk / 1000); |
1102 | } else if (IS_I9XX(dev)) { | 1583 | } else if (IS_I9XX(dev)) { |
1103 | refclk = 96000; | 1584 | refclk = 96000; |
1585 | if (IS_IGDNG(dev)) | ||
1586 | refclk = 120000; /* 120Mhz refclk */ | ||
1104 | } else { | 1587 | } else { |
1105 | refclk = 48000; | 1588 | refclk = 48000; |
1106 | } | 1589 | } |
@@ -1137,12 +1620,21 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1137 | } | 1620 | } |
1138 | } | 1621 | } |
1139 | 1622 | ||
1623 | /* FDI link */ | ||
1624 | if (IS_IGDNG(dev)) | ||
1625 | igdng_compute_m_n(3, 4, /* lane num 4 */ | ||
1626 | adjusted_mode->clock, | ||
1627 | 270000, /* lane clock */ | ||
1628 | &m_n); | ||
1629 | |||
1140 | if (IS_IGD(dev)) | 1630 | if (IS_IGD(dev)) |
1141 | fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2; | 1631 | fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2; |
1142 | else | 1632 | else |
1143 | fp = clock.n << 16 | clock.m1 << 8 | clock.m2; | 1633 | fp = clock.n << 16 | clock.m1 << 8 | clock.m2; |
1144 | 1634 | ||
1145 | dpll = DPLL_VGA_MODE_DIS; | 1635 | if (!IS_IGDNG(dev)) |
1636 | dpll = DPLL_VGA_MODE_DIS; | ||
1637 | |||
1146 | if (IS_I9XX(dev)) { | 1638 | if (IS_I9XX(dev)) { |
1147 | if (is_lvds) | 1639 | if (is_lvds) |
1148 | dpll |= DPLLB_MODE_LVDS; | 1640 | dpll |= DPLLB_MODE_LVDS; |
@@ -1150,17 +1642,22 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1150 | dpll |= DPLLB_MODE_DAC_SERIAL; | 1642 | dpll |= DPLLB_MODE_DAC_SERIAL; |
1151 | if (is_sdvo) { | 1643 | if (is_sdvo) { |
1152 | dpll |= DPLL_DVO_HIGH_SPEED; | 1644 | dpll |= DPLL_DVO_HIGH_SPEED; |
1153 | if (IS_I945G(dev) || IS_I945GM(dev)) { | 1645 | sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; |
1154 | int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; | 1646 | if (IS_I945G(dev) || IS_I945GM(dev)) |
1155 | dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; | 1647 | dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; |
1156 | } | 1648 | else if (IS_IGDNG(dev)) |
1649 | dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; | ||
1157 | } | 1650 | } |
1158 | 1651 | ||
1159 | /* compute bitmask from p1 value */ | 1652 | /* compute bitmask from p1 value */ |
1160 | if (IS_IGD(dev)) | 1653 | if (IS_IGD(dev)) |
1161 | dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_IGD; | 1654 | dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_IGD; |
1162 | else | 1655 | else { |
1163 | dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; | 1656 | dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; |
1657 | /* also FPA1 */ | ||
1658 | if (IS_IGDNG(dev)) | ||
1659 | dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; | ||
1660 | } | ||
1164 | switch (clock.p2) { | 1661 | switch (clock.p2) { |
1165 | case 5: | 1662 | case 5: |
1166 | dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; | 1663 | dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; |
@@ -1175,7 +1672,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1175 | dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; | 1672 | dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; |
1176 | break; | 1673 | break; |
1177 | } | 1674 | } |
1178 | if (IS_I965G(dev)) | 1675 | if (IS_I965G(dev) && !IS_IGDNG(dev)) |
1179 | dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); | 1676 | dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); |
1180 | } else { | 1677 | } else { |
1181 | if (is_lvds) { | 1678 | if (is_lvds) { |
@@ -1207,10 +1704,14 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1207 | /* Set up the display plane register */ | 1704 | /* Set up the display plane register */ |
1208 | dspcntr = DISPPLANE_GAMMA_ENABLE; | 1705 | dspcntr = DISPPLANE_GAMMA_ENABLE; |
1209 | 1706 | ||
1210 | if (pipe == 0) | 1707 | /* IGDNG's plane is forced to pipe, bit 24 is to |
1211 | dspcntr |= DISPPLANE_SEL_PIPE_A; | 1708 | enable color space conversion */ |
1212 | else | 1709 | if (!IS_IGDNG(dev)) { |
1213 | dspcntr |= DISPPLANE_SEL_PIPE_B; | 1710 | if (pipe == 0) |
1711 | dspcntr |= DISPPLANE_SEL_PIPE_A; | ||
1712 | else | ||
1713 | dspcntr |= DISPPLANE_SEL_PIPE_B; | ||
1714 | } | ||
1214 | 1715 | ||
1215 | if (pipe == 0 && !IS_I965G(dev)) { | 1716 | if (pipe == 0 && !IS_I965G(dev)) { |
1216 | /* Enable pixel doubling when the dot clock is > 90% of the (display) | 1717 | /* Enable pixel doubling when the dot clock is > 90% of the (display) |
@@ -1231,12 +1732,17 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1231 | 1732 | ||
1232 | 1733 | ||
1233 | /* Disable the panel fitter if it was on our pipe */ | 1734 | /* Disable the panel fitter if it was on our pipe */ |
1234 | if (intel_panel_fitter_pipe(dev) == pipe) | 1735 | if (!IS_IGDNG(dev) && intel_panel_fitter_pipe(dev) == pipe) |
1235 | I915_WRITE(PFIT_CONTROL, 0); | 1736 | I915_WRITE(PFIT_CONTROL, 0); |
1236 | 1737 | ||
1237 | DRM_DEBUG("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); | 1738 | DRM_DEBUG("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); |
1238 | drm_mode_debug_printmodeline(mode); | 1739 | drm_mode_debug_printmodeline(mode); |
1239 | 1740 | ||
1741 | /* assign to IGDNG registers */ | ||
1742 | if (IS_IGDNG(dev)) { | ||
1743 | fp_reg = pch_fp_reg; | ||
1744 | dpll_reg = pch_dpll_reg; | ||
1745 | } | ||
1240 | 1746 | ||
1241 | if (dpll & DPLL_VCO_ENABLE) { | 1747 | if (dpll & DPLL_VCO_ENABLE) { |
1242 | I915_WRITE(fp_reg, fp); | 1748 | I915_WRITE(fp_reg, fp); |
@@ -1245,6 +1751,22 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1245 | udelay(150); | 1751 | udelay(150); |
1246 | } | 1752 | } |
1247 | 1753 | ||
1754 | if (IS_IGDNG(dev)) { | ||
1755 | /* enable PCH clock reference source */ | ||
1756 | /* XXX need to change the setting for other outputs */ | ||
1757 | u32 temp; | ||
1758 | temp = I915_READ(PCH_DREF_CONTROL); | ||
1759 | temp &= ~DREF_NONSPREAD_SOURCE_MASK; | ||
1760 | temp |= DREF_NONSPREAD_CK505_ENABLE; | ||
1761 | temp &= ~DREF_SSC_SOURCE_MASK; | ||
1762 | temp |= DREF_SSC_SOURCE_ENABLE; | ||
1763 | temp &= ~DREF_SSC1_ENABLE; | ||
1764 | /* if no eDP, disable source output to CPU */ | ||
1765 | temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK; | ||
1766 | temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE; | ||
1767 | I915_WRITE(PCH_DREF_CONTROL, temp); | ||
1768 | } | ||
1769 | |||
1248 | /* The LVDS pin pair needs to be on before the DPLLs are enabled. | 1770 | /* The LVDS pin pair needs to be on before the DPLLs are enabled. |
1249 | * This is an exception to the general rule that mode_set doesn't turn | 1771 | * This is an exception to the general rule that mode_set doesn't turn |
1250 | * things on. | 1772 | * things on. |
@@ -1276,8 +1798,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1276 | /* Wait for the clocks to stabilize. */ | 1798 | /* Wait for the clocks to stabilize. */ |
1277 | udelay(150); | 1799 | udelay(150); |
1278 | 1800 | ||
1279 | if (IS_I965G(dev)) { | 1801 | if (IS_I965G(dev) && !IS_IGDNG(dev)) { |
1280 | int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; | 1802 | sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; |
1281 | I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | | 1803 | I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | |
1282 | ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); | 1804 | ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); |
1283 | } else { | 1805 | } else { |
@@ -1303,9 +1825,25 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1303 | /* pipesrc and dspsize control the size that is scaled from, which should | 1825 | /* pipesrc and dspsize control the size that is scaled from, which should |
1304 | * always be the user's requested size. | 1826 | * always be the user's requested size. |
1305 | */ | 1827 | */ |
1306 | I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); | 1828 | if (!IS_IGDNG(dev)) { |
1307 | I915_WRITE(dsppos_reg, 0); | 1829 | I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) | |
1830 | (mode->hdisplay - 1)); | ||
1831 | I915_WRITE(dsppos_reg, 0); | ||
1832 | } | ||
1308 | I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); | 1833 | I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); |
1834 | |||
1835 | if (IS_IGDNG(dev)) { | ||
1836 | I915_WRITE(data_m1_reg, TU_SIZE(m_n.tu) | m_n.gmch_m); | ||
1837 | I915_WRITE(data_n1_reg, TU_SIZE(m_n.tu) | m_n.gmch_n); | ||
1838 | I915_WRITE(link_m1_reg, m_n.link_m); | ||
1839 | I915_WRITE(link_n1_reg, m_n.link_n); | ||
1840 | |||
1841 | /* enable FDI RX PLL too */ | ||
1842 | temp = I915_READ(fdi_rx_reg); | ||
1843 | I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE); | ||
1844 | udelay(200); | ||
1845 | } | ||
1846 | |||
1309 | I915_WRITE(pipeconf_reg, pipeconf); | 1847 | I915_WRITE(pipeconf_reg, pipeconf); |
1310 | I915_READ(pipeconf_reg); | 1848 | I915_READ(pipeconf_reg); |
1311 | 1849 | ||
@@ -1336,6 +1874,11 @@ void intel_crtc_load_lut(struct drm_crtc *crtc) | |||
1336 | if (!crtc->enabled) | 1874 | if (!crtc->enabled) |
1337 | return; | 1875 | return; |
1338 | 1876 | ||
1877 | /* use legacy palette for IGDNG */ | ||
1878 | if (IS_IGDNG(dev)) | ||
1879 | palreg = (intel_crtc->pipe == 0) ? LGC_PALETTE_A : | ||
1880 | LGC_PALETTE_B; | ||
1881 | |||
1339 | for (i = 0; i < 256; i++) { | 1882 | for (i = 0; i < 256; i++) { |
1340 | I915_WRITE(palreg + 4 * i, | 1883 | I915_WRITE(palreg + 4 * i, |
1341 | (intel_crtc->lut_r[i] << 16) | | 1884 | (intel_crtc->lut_r[i] << 16) | |
@@ -1885,10 +2428,12 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
1885 | intel_crt_init(dev); | 2428 | intel_crt_init(dev); |
1886 | 2429 | ||
1887 | /* Set up integrated LVDS */ | 2430 | /* Set up integrated LVDS */ |
1888 | if (IS_MOBILE(dev) && !IS_I830(dev)) | 2431 | if (IS_MOBILE(dev) && !IS_I830(dev) && !IS_IGDNG(dev)) |
1889 | intel_lvds_init(dev); | 2432 | intel_lvds_init(dev); |
1890 | 2433 | ||
1891 | if (IS_I9XX(dev)) { | 2434 | if (IS_IGDNG(dev)) { |
2435 | /* ignore for other outputs */ | ||
2436 | } else if (IS_I9XX(dev)) { | ||
1892 | int found; | 2437 | int found; |
1893 | u32 reg; | 2438 | u32 reg; |
1894 | 2439 | ||
@@ -1912,7 +2457,7 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
1912 | } else | 2457 | } else |
1913 | intel_dvo_init(dev); | 2458 | intel_dvo_init(dev); |
1914 | 2459 | ||
1915 | if (IS_I9XX(dev) && IS_MOBILE(dev)) | 2460 | if (IS_I9XX(dev) && IS_MOBILE(dev) && !IS_IGDNG(dev)) |
1916 | intel_tv_init(dev); | 2461 | intel_tv_init(dev); |
1917 | 2462 | ||
1918 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 2463 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |