aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2009-04-07 19:16:42 -0400
committerKeith Packard <keithp@keithp.com>2009-06-18 18:54:07 -0400
commita4fc5ed69817c73e32571ad7837bb707f9890009 (patch)
tree1a54e8ca9917330359118c1709895c80d74c15af /drivers/gpu/drm/i915/intel_display.c
parentc31c4ba3437d98efa19710e30d694a1cfdf87aa5 (diff)
drm/i915: Add Display Port support
Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c107
1 files changed, 102 insertions, 5 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3e1c78162119..5af55aa0d7a6 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -29,6 +29,7 @@
29#include "intel_drv.h" 29#include "intel_drv.h"
30#include "i915_drm.h" 30#include "i915_drm.h"
31#include "i915_drv.h" 31#include "i915_drv.h"
32#include "intel_dp.h"
32 33
33#include "drm_crtc_helper.h" 34#include "drm_crtc_helper.h"
34 35
@@ -135,10 +136,11 @@ struct intel_limit {
135#define INTEL_LIMIT_G4X_HDMI_DAC 5 136#define INTEL_LIMIT_G4X_HDMI_DAC 5
136#define INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS 6 137#define INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS 6
137#define INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS 7 138#define INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS 7
138#define INTEL_LIMIT_IGD_SDVO_DAC 8 139#define INTEL_LIMIT_G4X_DISPLAY_PORT 8
139#define INTEL_LIMIT_IGD_LVDS 9 140#define INTEL_LIMIT_IGD_SDVO_DAC 9
140#define INTEL_LIMIT_IGDNG_SDVO_DAC 10 141#define INTEL_LIMIT_IGD_LVDS 10
141#define INTEL_LIMIT_IGDNG_LVDS 11 142#define INTEL_LIMIT_IGDNG_SDVO_DAC 11
143#define INTEL_LIMIT_IGDNG_LVDS 12
142 144
143/*The parameter is for SDVO on G4x platform*/ 145/*The parameter is for SDVO on G4x platform*/
144#define G4X_DOT_SDVO_MIN 25000 146#define G4X_DOT_SDVO_MIN 25000
@@ -218,6 +220,25 @@ struct intel_limit {
218#define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7 220#define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7
219#define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0 221#define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0
220 222
223/*The parameter is for DISPLAY PORT on G4x platform*/
224#define G4X_DOT_DISPLAY_PORT_MIN 161670
225#define G4X_DOT_DISPLAY_PORT_MAX 227000
226#define G4X_N_DISPLAY_PORT_MIN 1
227#define G4X_N_DISPLAY_PORT_MAX 2
228#define G4X_M_DISPLAY_PORT_MIN 97
229#define G4X_M_DISPLAY_PORT_MAX 108
230#define G4X_M1_DISPLAY_PORT_MIN 0x10
231#define G4X_M1_DISPLAY_PORT_MAX 0x12
232#define G4X_M2_DISPLAY_PORT_MIN 0x05
233#define G4X_M2_DISPLAY_PORT_MAX 0x06
234#define G4X_P_DISPLAY_PORT_MIN 10
235#define G4X_P_DISPLAY_PORT_MAX 20
236#define G4X_P1_DISPLAY_PORT_MIN 1
237#define G4X_P1_DISPLAY_PORT_MAX 2
238#define G4X_P2_DISPLAY_PORT_SLOW 10
239#define G4X_P2_DISPLAY_PORT_FAST 10
240#define G4X_P2_DISPLAY_PORT_LIMIT 0
241
221/* IGDNG */ 242/* IGDNG */
222/* as we calculate clock using (register_value + 2) for 243/* as we calculate clock using (register_value + 2) for
223 N/M1/M2, so here the range value for them is (actual_value-2). 244 N/M1/M2, so here the range value for them is (actual_value-2).
@@ -256,6 +277,10 @@ static bool
256intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, 277intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
257 int target, int refclk, intel_clock_t *best_clock); 278 int target, int refclk, intel_clock_t *best_clock);
258 279
280static bool
281intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc,
282 int target, int refclk, intel_clock_t *best_clock);
283
259static const intel_limit_t intel_limits[] = { 284static const intel_limit_t intel_limits[] = {
260 { /* INTEL_LIMIT_I8XX_DVO_DAC */ 285 { /* INTEL_LIMIT_I8XX_DVO_DAC */
261 .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, 286 .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX },
@@ -389,6 +414,28 @@ static const intel_limit_t intel_limits[] = {
389 }, 414 },
390 .find_pll = intel_g4x_find_best_PLL, 415 .find_pll = intel_g4x_find_best_PLL,
391 }, 416 },
417 { /* INTEL_LIMIT_G4X_DISPLAY_PORT */
418 .dot = { .min = G4X_DOT_DISPLAY_PORT_MIN,
419 .max = G4X_DOT_DISPLAY_PORT_MAX },
420 .vco = { .min = G4X_VCO_MIN,
421 .max = G4X_VCO_MAX},
422 .n = { .min = G4X_N_DISPLAY_PORT_MIN,
423 .max = G4X_N_DISPLAY_PORT_MAX },
424 .m = { .min = G4X_M_DISPLAY_PORT_MIN,
425 .max = G4X_M_DISPLAY_PORT_MAX },
426 .m1 = { .min = G4X_M1_DISPLAY_PORT_MIN,
427 .max = G4X_M1_DISPLAY_PORT_MAX },
428 .m2 = { .min = G4X_M2_DISPLAY_PORT_MIN,
429 .max = G4X_M2_DISPLAY_PORT_MAX },
430 .p = { .min = G4X_P_DISPLAY_PORT_MIN,
431 .max = G4X_P_DISPLAY_PORT_MAX },
432 .p1 = { .min = G4X_P1_DISPLAY_PORT_MIN,
433 .max = G4X_P1_DISPLAY_PORT_MAX},
434 .p2 = { .dot_limit = G4X_P2_DISPLAY_PORT_LIMIT,
435 .p2_slow = G4X_P2_DISPLAY_PORT_SLOW,
436 .p2_fast = G4X_P2_DISPLAY_PORT_FAST },
437 .find_pll = intel_find_pll_g4x_dp,
438 },
392 { /* INTEL_LIMIT_IGD_SDVO */ 439 { /* INTEL_LIMIT_IGD_SDVO */
393 .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, 440 .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX},
394 .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, 441 .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX },
@@ -478,6 +525,8 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc)
478 limit = &intel_limits[INTEL_LIMIT_G4X_HDMI_DAC]; 525 limit = &intel_limits[INTEL_LIMIT_G4X_HDMI_DAC];
479 } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) { 526 } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) {
480 limit = &intel_limits[INTEL_LIMIT_G4X_SDVO]; 527 limit = &intel_limits[INTEL_LIMIT_G4X_SDVO];
528 } else if (intel_pipe_has_type (crtc, INTEL_OUTPUT_DISPLAYPORT)) {
529 limit = &intel_limits[INTEL_LIMIT_G4X_DISPLAY_PORT];
481 } else /* The option is for other outputs */ 530 } else /* The option is for other outputs */
482 limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; 531 limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
483 532
@@ -764,6 +813,35 @@ out:
764 return found; 813 return found;
765} 814}
766 815
816/* DisplayPort has only two frequencies, 162MHz and 270MHz */
817static bool
818intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
819 int target, int refclk, intel_clock_t *best_clock)
820{
821 intel_clock_t clock;
822 if (target < 200000) {
823 clock.dot = 161670;
824 clock.p = 20;
825 clock.p1 = 2;
826 clock.p2 = 10;
827 clock.n = 0x01;
828 clock.m = 97;
829 clock.m1 = 0x10;
830 clock.m2 = 0x05;
831 } else {
832 clock.dot = 270000;
833 clock.p = 10;
834 clock.p1 = 1;
835 clock.p2 = 10;
836 clock.n = 0x02;
837 clock.m = 108;
838 clock.m1 = 0x12;
839 clock.m2 = 0x06;
840 }
841 memcpy(best_clock, &clock, sizeof(intel_clock_t));
842 return true;
843}
844
767void 845void
768intel_wait_for_vblank(struct drm_device *dev) 846intel_wait_for_vblank(struct drm_device *dev)
769{ 847{
@@ -1541,7 +1619,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
1541 intel_clock_t clock; 1619 intel_clock_t clock;
1542 u32 dpll = 0, fp = 0, dspcntr, pipeconf; 1620 u32 dpll = 0, fp = 0, dspcntr, pipeconf;
1543 bool ok, is_sdvo = false, is_dvo = false; 1621 bool ok, is_sdvo = false, is_dvo = false;
1544 bool is_crt = false, is_lvds = false, is_tv = false; 1622 bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
1545 struct drm_mode_config *mode_config = &dev->mode_config; 1623 struct drm_mode_config *mode_config = &dev->mode_config;
1546 struct drm_connector *connector; 1624 struct drm_connector *connector;
1547 const intel_limit_t *limit; 1625 const intel_limit_t *limit;
@@ -1585,6 +1663,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
1585 case INTEL_OUTPUT_ANALOG: 1663 case INTEL_OUTPUT_ANALOG:
1586 is_crt = true; 1664 is_crt = true;
1587 break; 1665 break;
1666 case INTEL_OUTPUT_DISPLAYPORT:
1667 is_dp = true;
1668 break;
1588 } 1669 }
1589 1670
1590 num_outputs++; 1671 num_outputs++;
@@ -1600,6 +1681,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
1600 } else { 1681 } else {
1601 refclk = 48000; 1682 refclk = 48000;
1602 } 1683 }
1684
1603 1685
1604 /* 1686 /*
1605 * Returns a set of divisors for the desired target clock with the given 1687 * Returns a set of divisors for the desired target clock with the given
@@ -1662,6 +1744,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
1662 else if (IS_IGDNG(dev)) 1744 else if (IS_IGDNG(dev))
1663 dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; 1745 dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
1664 } 1746 }
1747 if (is_dp)
1748 dpll |= DPLL_DVO_HIGH_SPEED;
1665 1749
1666 /* compute bitmask from p1 value */ 1750 /* compute bitmask from p1 value */
1667 if (IS_IGD(dev)) 1751 if (IS_IGD(dev))
@@ -1809,6 +1893,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
1809 I915_WRITE(lvds_reg, lvds); 1893 I915_WRITE(lvds_reg, lvds);
1810 I915_READ(lvds_reg); 1894 I915_READ(lvds_reg);
1811 } 1895 }
1896 if (is_dp)
1897 intel_dp_set_m_n(crtc, mode, adjusted_mode);
1812 1898
1813 I915_WRITE(fp_reg, fp); 1899 I915_WRITE(fp_reg, fp);
1814 I915_WRITE(dpll_reg, dpll); 1900 I915_WRITE(dpll_reg, dpll);
@@ -2475,6 +2561,8 @@ static void intel_setup_outputs(struct drm_device *dev)
2475 found = intel_sdvo_init(dev, SDVOB); 2561 found = intel_sdvo_init(dev, SDVOB);
2476 if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) 2562 if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
2477 intel_hdmi_init(dev, SDVOB); 2563 intel_hdmi_init(dev, SDVOB);
2564 if (!found && SUPPORTS_INTEGRATED_DP(dev))
2565 intel_dp_init(dev, DP_B);
2478 } 2566 }
2479 2567
2480 /* Before G4X SDVOC doesn't have its own detect register */ 2568 /* Before G4X SDVOC doesn't have its own detect register */
@@ -2487,7 +2575,11 @@ static void intel_setup_outputs(struct drm_device *dev)
2487 found = intel_sdvo_init(dev, SDVOC); 2575 found = intel_sdvo_init(dev, SDVOC);
2488 if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) 2576 if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
2489 intel_hdmi_init(dev, SDVOC); 2577 intel_hdmi_init(dev, SDVOC);
2578 if (!found && SUPPORTS_INTEGRATED_DP(dev))
2579 intel_dp_init(dev, DP_C);
2490 } 2580 }
2581 if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED))
2582 intel_dp_init(dev, DP_D);
2491 } else 2583 } else
2492 intel_dvo_init(dev); 2584 intel_dvo_init(dev);
2493 2585
@@ -2530,6 +2622,11 @@ static void intel_setup_outputs(struct drm_device *dev)
2530 (1 << 1)); 2622 (1 << 1));
2531 clone_mask = (1 << INTEL_OUTPUT_TVOUT); 2623 clone_mask = (1 << INTEL_OUTPUT_TVOUT);
2532 break; 2624 break;
2625 case INTEL_OUTPUT_DISPLAYPORT:
2626 crtc_mask = ((1 << 0) |
2627 (1 << 1));
2628 clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT);
2629 break;
2533 } 2630 }
2534 encoder->possible_crtcs = crtc_mask; 2631 encoder->possible_crtcs = crtc_mask;
2535 encoder->possible_clones = intel_connector_clones(dev, clone_mask); 2632 encoder->possible_clones = intel_connector_clones(dev, clone_mask);