diff options
author | Alan Cox <alan@linux.intel.com> | 2012-08-08 09:54:41 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-08-23 19:29:12 -0400 |
commit | 220801bdb53ceeac01d021ac459d112acc7deb0b (patch) | |
tree | 87c64cbd330b26754922caca5c94c67082e8de0d /drivers | |
parent | 8695b612943561478fd22f28f45e5692e5d078db (diff) |
gma500/cdv: add the bits that don't need the new code
Based on bits from Yakui <yakui.zhao@intel.com>
We can import various little bits of code before we plumb it all
in and hopefully this way catch any regressions more easily.
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/gma500/cdv_device.c | 59 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/cdv_intel_display.c | 99 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/framebuffer.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/psb_intel_drv.h | 2 |
4 files changed, 161 insertions, 3 deletions
diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index b7e7b49d8f62..e2fff244a599 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c | |||
@@ -488,6 +488,65 @@ static void cdv_hotplug_enable(struct drm_device *dev, bool on) | |||
488 | } | 488 | } |
489 | } | 489 | } |
490 | 490 | ||
491 | static const char *force_audio_names[] = { | ||
492 | "off", | ||
493 | "auto", | ||
494 | "on", | ||
495 | }; | ||
496 | |||
497 | void cdv_intel_attach_force_audio_property(struct drm_connector *connector) | ||
498 | { | ||
499 | struct drm_device *dev = connector->dev; | ||
500 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
501 | struct drm_property *prop; | ||
502 | int i; | ||
503 | |||
504 | prop = dev_priv->force_audio_property; | ||
505 | if (prop == NULL) { | ||
506 | prop = drm_property_create(dev, DRM_MODE_PROP_ENUM, | ||
507 | "audio", | ||
508 | ARRAY_SIZE(force_audio_names)); | ||
509 | if (prop == NULL) | ||
510 | return; | ||
511 | |||
512 | for (i = 0; i < ARRAY_SIZE(force_audio_names); i++) | ||
513 | drm_property_add_enum(prop, i, i-1, force_audio_names[i]); | ||
514 | |||
515 | dev_priv->force_audio_property = prop; | ||
516 | } | ||
517 | drm_connector_attach_property(connector, prop, 0); | ||
518 | } | ||
519 | |||
520 | |||
521 | static const char *broadcast_rgb_names[] = { | ||
522 | "Full", | ||
523 | "Limited 16:235", | ||
524 | }; | ||
525 | |||
526 | void cdv_intel_attach_broadcast_rgb_property(struct drm_connector *connector) | ||
527 | { | ||
528 | struct drm_device *dev = connector->dev; | ||
529 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
530 | struct drm_property *prop; | ||
531 | int i; | ||
532 | |||
533 | prop = dev_priv->broadcast_rgb_property; | ||
534 | if (prop == NULL) { | ||
535 | prop = drm_property_create(dev, DRM_MODE_PROP_ENUM, | ||
536 | "Broadcast RGB", | ||
537 | ARRAY_SIZE(broadcast_rgb_names)); | ||
538 | if (prop == NULL) | ||
539 | return; | ||
540 | |||
541 | for (i = 0; i < ARRAY_SIZE(broadcast_rgb_names); i++) | ||
542 | drm_property_add_enum(prop, i, i, broadcast_rgb_names[i]); | ||
543 | |||
544 | dev_priv->broadcast_rgb_property = prop; | ||
545 | } | ||
546 | |||
547 | drm_connector_attach_property(connector, prop, 0); | ||
548 | } | ||
549 | |||
491 | /* Cedarview */ | 550 | /* Cedarview */ |
492 | static const struct psb_offset cdv_regmap[2] = { | 551 | static const struct psb_offset cdv_regmap[2] = { |
493 | { | 552 | { |
diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index f16169c95dec..2e0231e909ff 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c | |||
@@ -64,11 +64,16 @@ struct cdv_intel_limit_t { | |||
64 | static bool cdv_intel_find_best_PLL(const struct cdv_intel_limit_t *limit, | 64 | static bool cdv_intel_find_best_PLL(const struct cdv_intel_limit_t *limit, |
65 | struct drm_crtc *crtc, int target, int refclk, | 65 | struct drm_crtc *crtc, int target, int refclk, |
66 | struct cdv_intel_clock_t *best_clock); | 66 | struct cdv_intel_clock_t *best_clock); |
67 | static bool cdv_intel_find_dp_pll(const struct cdv_intel_limit_t *limit, struct drm_crtc *crtc, int target, | ||
68 | int refclk, | ||
69 | struct cdv_intel_clock_t *best_clock); | ||
67 | 70 | ||
68 | #define CDV_LIMIT_SINGLE_LVDS_96 0 | 71 | #define CDV_LIMIT_SINGLE_LVDS_96 0 |
69 | #define CDV_LIMIT_SINGLE_LVDS_100 1 | 72 | #define CDV_LIMIT_SINGLE_LVDS_100 1 |
70 | #define CDV_LIMIT_DAC_HDMI_27 2 | 73 | #define CDV_LIMIT_DAC_HDMI_27 2 |
71 | #define CDV_LIMIT_DAC_HDMI_96 3 | 74 | #define CDV_LIMIT_DAC_HDMI_96 3 |
75 | #define CDV_LIMIT_DP_27 4 | ||
76 | #define CDV_LIMIT_DP_100 5 | ||
72 | 77 | ||
73 | static const struct cdv_intel_limit_t cdv_intel_limits[] = { | 78 | static const struct cdv_intel_limit_t cdv_intel_limits[] = { |
74 | { /* CDV_SIGNLE_LVDS_96MHz */ | 79 | { /* CDV_SIGNLE_LVDS_96MHz */ |
@@ -123,6 +128,30 @@ static const struct cdv_intel_limit_t cdv_intel_limits[] = { | |||
123 | .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5}, | 128 | .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5}, |
124 | .find_pll = cdv_intel_find_best_PLL, | 129 | .find_pll = cdv_intel_find_best_PLL, |
125 | }, | 130 | }, |
131 | { /* CDV_DP_27MHz */ | ||
132 | .dot = {.min = 160000, .max = 272000}, | ||
133 | .vco = {.min = 1809000, .max = 3564000}, | ||
134 | .n = {.min = 1, .max = 1}, | ||
135 | .m = {.min = 67, .max = 132}, | ||
136 | .m1 = {.min = 0, .max = 0}, | ||
137 | .m2 = {.min = 65, .max = 130}, | ||
138 | .p = {.min = 5, .max = 90}, | ||
139 | .p1 = {.min = 1, .max = 9}, | ||
140 | .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 10}, | ||
141 | .find_pll = cdv_intel_find_dp_pll, | ||
142 | }, | ||
143 | { /* CDV_DP_100MHz */ | ||
144 | .dot = {.min = 160000, .max = 272000}, | ||
145 | .vco = {.min = 1800000, .max = 3600000}, | ||
146 | .n = {.min = 2, .max = 6}, | ||
147 | .m = {.min = 60, .max = 164}, | ||
148 | .m1 = {.min = 0, .max = 0}, | ||
149 | .m2 = {.min = 58, .max = 162}, | ||
150 | .p = {.min = 5, .max = 100}, | ||
151 | .p1 = {.min = 1, .max = 10}, | ||
152 | .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 10}, | ||
153 | .find_pll = cdv_intel_find_dp_pll, | ||
154 | } | ||
126 | }; | 155 | }; |
127 | 156 | ||
128 | #define _wait_for(COND, MS, W) ({ \ | 157 | #define _wait_for(COND, MS, W) ({ \ |
@@ -269,7 +298,7 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc, | |||
269 | ref_value &= ~(REF_CLK_MASK); | 298 | ref_value &= ~(REF_CLK_MASK); |
270 | 299 | ||
271 | /* use DPLL_A for pipeB on CRT/HDMI */ | 300 | /* use DPLL_A for pipeB on CRT/HDMI */ |
272 | if (pipe == 1 && !is_lvds) { | 301 | if (pipe == 1 && !is_lvds && !(ddi_select & DP_MASK)) { |
273 | DRM_DEBUG_KMS("use DPLLA for pipe B\n"); | 302 | DRM_DEBUG_KMS("use DPLLA for pipe B\n"); |
274 | ref_value |= REF_CLK_DPLLA; | 303 | ref_value |= REF_CLK_DPLLA; |
275 | } else { | 304 | } else { |
@@ -409,6 +438,11 @@ static const struct cdv_intel_limit_t *cdv_intel_limit(struct drm_crtc *crtc, | |||
409 | limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96]; | 438 | limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96]; |
410 | else | 439 | else |
411 | limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100]; | 440 | limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100]; |
441 | } else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { | ||
442 | if (refclk == 27000) | ||
443 | limit = &cdv_intel_limits[CDV_LIMIT_DP_27]; | ||
444 | else | ||
445 | limit = &cdv_intel_limits[CDV_LIMIT_DP_100]; | ||
412 | } else { | 446 | } else { |
413 | if (refclk == 27000) | 447 | if (refclk == 27000) |
414 | limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_27]; | 448 | limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_27]; |
@@ -510,6 +544,49 @@ static bool cdv_intel_find_best_PLL(const struct cdv_intel_limit_t *limit, | |||
510 | return err != target; | 544 | return err != target; |
511 | } | 545 | } |
512 | 546 | ||
547 | static bool cdv_intel_find_dp_pll(const struct cdv_intel_limit_t *limit, struct drm_crtc *crtc, int target, | ||
548 | int refclk, | ||
549 | struct cdv_intel_clock_t *best_clock) | ||
550 | { | ||
551 | struct cdv_intel_clock_t clock; | ||
552 | if (refclk == 27000) { | ||
553 | if (target < 200000) { | ||
554 | clock.p1 = 2; | ||
555 | clock.p2 = 10; | ||
556 | clock.n = 1; | ||
557 | clock.m1 = 0; | ||
558 | clock.m2 = 118; | ||
559 | } else { | ||
560 | clock.p1 = 1; | ||
561 | clock.p2 = 10; | ||
562 | clock.n = 1; | ||
563 | clock.m1 = 0; | ||
564 | clock.m2 = 98; | ||
565 | } | ||
566 | } else if (refclk == 100000) { | ||
567 | if (target < 200000) { | ||
568 | clock.p1 = 2; | ||
569 | clock.p2 = 10; | ||
570 | clock.n = 5; | ||
571 | clock.m1 = 0; | ||
572 | clock.m2 = 160; | ||
573 | } else { | ||
574 | clock.p1 = 1; | ||
575 | clock.p2 = 10; | ||
576 | clock.n = 5; | ||
577 | clock.m1 = 0; | ||
578 | clock.m2 = 133; | ||
579 | } | ||
580 | } else | ||
581 | return false; | ||
582 | clock.m = clock.m2 + 2; | ||
583 | clock.p = clock.p1 * clock.p2; | ||
584 | clock.vco = (refclk * clock.m) / clock.n; | ||
585 | clock.dot = clock.vco / clock.p; | ||
586 | memcpy(best_clock, &clock, sizeof(struct cdv_intel_clock_t)); | ||
587 | return true; | ||
588 | } | ||
589 | |||
513 | static int cdv_intel_pipe_set_base(struct drm_crtc *crtc, | 590 | static int cdv_intel_pipe_set_base(struct drm_crtc *crtc, |
514 | int x, int y, struct drm_framebuffer *old_fb) | 591 | int x, int y, struct drm_framebuffer *old_fb) |
515 | { | 592 | { |
@@ -963,7 +1040,7 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, | |||
963 | u32 dpll = 0, dspcntr, pipeconf; | 1040 | u32 dpll = 0, dspcntr, pipeconf; |
964 | bool ok; | 1041 | bool ok; |
965 | bool is_crt = false, is_lvds = false, is_tv = false; | 1042 | bool is_crt = false, is_lvds = false, is_tv = false; |
966 | bool is_hdmi = false; | 1043 | bool is_hdmi = false, is_dp = false; |
967 | struct drm_mode_config *mode_config = &dev->mode_config; | 1044 | struct drm_mode_config *mode_config = &dev->mode_config; |
968 | struct drm_connector *connector; | 1045 | struct drm_connector *connector; |
969 | const struct cdv_intel_limit_t *limit; | 1046 | const struct cdv_intel_limit_t *limit; |
@@ -991,6 +1068,9 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, | |||
991 | case INTEL_OUTPUT_HDMI: | 1068 | case INTEL_OUTPUT_HDMI: |
992 | is_hdmi = true; | 1069 | is_hdmi = true; |
993 | break; | 1070 | break; |
1071 | case INTEL_OUTPUT_DISPLAYPORT: | ||
1072 | is_dp = true; | ||
1073 | break; | ||
994 | default: | 1074 | default: |
995 | DRM_ERROR("invalid output type.\n"); | 1075 | DRM_ERROR("invalid output type.\n"); |
996 | return 0; | 1076 | return 0; |
@@ -1003,6 +1083,12 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1003 | else | 1083 | else |
1004 | /* high-end sku, 27/100 mhz */ | 1084 | /* high-end sku, 27/100 mhz */ |
1005 | refclk = 27000; | 1085 | refclk = 27000; |
1086 | if (is_dp) { | ||
1087 | if (pipe == 0) | ||
1088 | refclk = 27000; | ||
1089 | else | ||
1090 | refclk = 100000; | ||
1091 | } | ||
1006 | 1092 | ||
1007 | if (is_lvds && dev_priv->lvds_use_ssc) { | 1093 | if (is_lvds && dev_priv->lvds_use_ssc) { |
1008 | refclk = dev_priv->lvds_ssc_freq * 1000; | 1094 | refclk = dev_priv->lvds_ssc_freq * 1000; |
@@ -1028,6 +1114,15 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1028 | } | 1114 | } |
1029 | /* dpll |= PLL_REF_INPUT_DREFCLK; */ | 1115 | /* dpll |= PLL_REF_INPUT_DREFCLK; */ |
1030 | 1116 | ||
1117 | if (is_dp) { | ||
1118 | /*FIXME cdv_intel_dp_set_m_n(crtc, mode, adjusted_mode); */ | ||
1119 | } else { | ||
1120 | REG_WRITE(PIPE_GMCH_DATA_M(pipe), 0); | ||
1121 | REG_WRITE(PIPE_GMCH_DATA_N(pipe), 0); | ||
1122 | REG_WRITE(PIPE_DP_LINK_M(pipe), 0); | ||
1123 | REG_WRITE(PIPE_DP_LINK_N(pipe), 0); | ||
1124 | } | ||
1125 | |||
1031 | dpll |= DPLL_SYNCLOCK_ENABLE; | 1126 | dpll |= DPLL_SYNCLOCK_ENABLE; |
1032 | /* if (is_lvds) | 1127 | /* if (is_lvds) |
1033 | dpll |= DPLLB_MODE_LVDS; | 1128 | dpll |= DPLLB_MODE_LVDS; |
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 5732b5702e1c..2de6b1fcc135 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c | |||
@@ -764,6 +764,10 @@ static void psb_setup_outputs(struct drm_device *dev) | |||
764 | crtc_mask = dev_priv->ops->hdmi_mask; | 764 | crtc_mask = dev_priv->ops->hdmi_mask; |
765 | clone_mask = (1 << INTEL_OUTPUT_HDMI); | 765 | clone_mask = (1 << INTEL_OUTPUT_HDMI); |
766 | break; | 766 | break; |
767 | case INTEL_OUTPUT_DISPLAYPORT: | ||
768 | crtc_mask = (1 << 0) | (1 << 1); | ||
769 | clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT); | ||
770 | break; | ||
767 | } | 771 | } |
768 | encoder->possible_crtcs = crtc_mask; | 772 | encoder->possible_crtcs = crtc_mask; |
769 | encoder->possible_clones = | 773 | encoder->possible_clones = |
diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h index 73214e281fab..c574c0199103 100644 --- a/drivers/gpu/drm/gma500/psb_intel_drv.h +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h | |||
@@ -134,7 +134,7 @@ struct psb_intel_encoder { | |||
134 | u32 ddi_select; /* Channel info */ | 134 | u32 ddi_select; /* Channel info */ |
135 | #define DDI0_SELECT 0x01 | 135 | #define DDI0_SELECT 0x01 |
136 | #define DDI1_SELECT 0x02 | 136 | #define DDI1_SELECT 0x02 |
137 | #define DP_MASK 0x8000; | 137 | #define DP_MASK 0x8000 |
138 | #define DDI_MASK 0x03 | 138 | #define DDI_MASK 0x03 |
139 | void *dev_priv; /* For sdvo_priv, lvds_priv, etc... */ | 139 | void *dev_priv; /* For sdvo_priv, lvds_priv, etc... */ |
140 | 140 | ||