diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_sdvo.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 101 |
1 files changed, 44 insertions, 57 deletions
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 812fe7b06f87..701372e512a8 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
@@ -99,32 +99,13 @@ struct intel_sdvo { | |||
99 | */ | 99 | */ |
100 | uint16_t hotplug_active; | 100 | uint16_t hotplug_active; |
101 | 101 | ||
102 | /** | ||
103 | * This is set if we're going to treat the device as TV-out. | ||
104 | * | ||
105 | * While we have these nice friendly flags for output types that ought | ||
106 | * to decide this for us, the S-Video output on our HDMI+S-Video card | ||
107 | * shows up as RGB1 (VGA). | ||
108 | */ | ||
109 | bool is_tv; | ||
110 | |||
111 | enum port port; | 102 | enum port port; |
112 | 103 | ||
113 | /** | ||
114 | * This is set if we treat the device as HDMI, instead of DVI. | ||
115 | */ | ||
116 | bool is_hdmi; | ||
117 | bool has_hdmi_monitor; | 104 | bool has_hdmi_monitor; |
118 | bool has_hdmi_audio; | 105 | bool has_hdmi_audio; |
119 | bool rgb_quant_range_selectable; | 106 | bool rgb_quant_range_selectable; |
120 | 107 | ||
121 | /** | 108 | /** |
122 | * This is set if we detect output of sdvo device as LVDS and | ||
123 | * have a valid fixed mode to use with the panel. | ||
124 | */ | ||
125 | bool is_lvds; | ||
126 | |||
127 | /** | ||
128 | * This is sdvo fixed pannel mode pointer | 109 | * This is sdvo fixed pannel mode pointer |
129 | */ | 110 | */ |
130 | struct drm_display_mode *sdvo_lvds_fixed_mode; | 111 | struct drm_display_mode *sdvo_lvds_fixed_mode; |
@@ -172,6 +153,11 @@ struct intel_sdvo_connector { | |||
172 | 153 | ||
173 | /* this is to get the range of margin.*/ | 154 | /* this is to get the range of margin.*/ |
174 | u32 max_hscan, max_vscan; | 155 | u32 max_hscan, max_vscan; |
156 | |||
157 | /** | ||
158 | * This is set if we treat the device as HDMI, instead of DVI. | ||
159 | */ | ||
160 | bool is_hdmi; | ||
175 | }; | 161 | }; |
176 | 162 | ||
177 | struct intel_sdvo_connector_state { | 163 | struct intel_sdvo_connector_state { |
@@ -766,6 +752,7 @@ static bool intel_sdvo_get_input_timing(struct intel_sdvo *intel_sdvo, | |||
766 | 752 | ||
767 | static bool | 753 | static bool |
768 | intel_sdvo_create_preferred_input_timing(struct intel_sdvo *intel_sdvo, | 754 | intel_sdvo_create_preferred_input_timing(struct intel_sdvo *intel_sdvo, |
755 | struct intel_sdvo_connector *intel_sdvo_connector, | ||
769 | uint16_t clock, | 756 | uint16_t clock, |
770 | uint16_t width, | 757 | uint16_t width, |
771 | uint16_t height) | 758 | uint16_t height) |
@@ -778,7 +765,7 @@ intel_sdvo_create_preferred_input_timing(struct intel_sdvo *intel_sdvo, | |||
778 | args.height = height; | 765 | args.height = height; |
779 | args.interlace = 0; | 766 | args.interlace = 0; |
780 | 767 | ||
781 | if (intel_sdvo->is_lvds && | 768 | if (IS_LVDS(intel_sdvo_connector) && |
782 | (intel_sdvo->sdvo_lvds_fixed_mode->hdisplay != width || | 769 | (intel_sdvo->sdvo_lvds_fixed_mode->hdisplay != width || |
783 | intel_sdvo->sdvo_lvds_fixed_mode->vdisplay != height)) | 770 | intel_sdvo->sdvo_lvds_fixed_mode->vdisplay != height)) |
784 | args.scaled = 1; | 771 | args.scaled = 1; |
@@ -1067,6 +1054,7 @@ intel_sdvo_set_output_timings_from_mode(struct intel_sdvo *intel_sdvo, | |||
1067 | */ | 1054 | */ |
1068 | static bool | 1055 | static bool |
1069 | intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo, | 1056 | intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo, |
1057 | struct intel_sdvo_connector *intel_sdvo_connector, | ||
1070 | const struct drm_display_mode *mode, | 1058 | const struct drm_display_mode *mode, |
1071 | struct drm_display_mode *adjusted_mode) | 1059 | struct drm_display_mode *adjusted_mode) |
1072 | { | 1060 | { |
@@ -1077,6 +1065,7 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo, | |||
1077 | return false; | 1065 | return false; |
1078 | 1066 | ||
1079 | if (!intel_sdvo_create_preferred_input_timing(intel_sdvo, | 1067 | if (!intel_sdvo_create_preferred_input_timing(intel_sdvo, |
1068 | intel_sdvo_connector, | ||
1080 | mode->clock / 10, | 1069 | mode->clock / 10, |
1081 | mode->hdisplay, | 1070 | mode->hdisplay, |
1082 | mode->vdisplay)) | 1071 | mode->vdisplay)) |
@@ -1127,6 +1116,8 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder, | |||
1127 | struct intel_sdvo *intel_sdvo = to_sdvo(encoder); | 1116 | struct intel_sdvo *intel_sdvo = to_sdvo(encoder); |
1128 | struct intel_sdvo_connector_state *intel_sdvo_state = | 1117 | struct intel_sdvo_connector_state *intel_sdvo_state = |
1129 | to_intel_sdvo_connector_state(conn_state); | 1118 | to_intel_sdvo_connector_state(conn_state); |
1119 | struct intel_sdvo_connector *intel_sdvo_connector = | ||
1120 | to_intel_sdvo_connector(conn_state->connector); | ||
1130 | struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; | 1121 | struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; |
1131 | struct drm_display_mode *mode = &pipe_config->base.mode; | 1122 | struct drm_display_mode *mode = &pipe_config->base.mode; |
1132 | 1123 | ||
@@ -1142,20 +1133,22 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder, | |||
1142 | * timings, even though this isn't really the right place in | 1133 | * timings, even though this isn't really the right place in |
1143 | * the sequence to do it. Oh well. | 1134 | * the sequence to do it. Oh well. |
1144 | */ | 1135 | */ |
1145 | if (intel_sdvo->is_tv) { | 1136 | if (IS_TV(intel_sdvo_connector)) { |
1146 | if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, mode)) | 1137 | if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, mode)) |
1147 | return false; | 1138 | return false; |
1148 | 1139 | ||
1149 | (void) intel_sdvo_get_preferred_input_mode(intel_sdvo, | 1140 | (void) intel_sdvo_get_preferred_input_mode(intel_sdvo, |
1141 | intel_sdvo_connector, | ||
1150 | mode, | 1142 | mode, |
1151 | adjusted_mode); | 1143 | adjusted_mode); |
1152 | pipe_config->sdvo_tv_clock = true; | 1144 | pipe_config->sdvo_tv_clock = true; |
1153 | } else if (intel_sdvo->is_lvds) { | 1145 | } else if (IS_LVDS(intel_sdvo_connector)) { |
1154 | if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, | 1146 | if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, |
1155 | intel_sdvo->sdvo_lvds_fixed_mode)) | 1147 | intel_sdvo->sdvo_lvds_fixed_mode)) |
1156 | return false; | 1148 | return false; |
1157 | 1149 | ||
1158 | (void) intel_sdvo_get_preferred_input_mode(intel_sdvo, | 1150 | (void) intel_sdvo_get_preferred_input_mode(intel_sdvo, |
1151 | intel_sdvo_connector, | ||
1159 | mode, | 1152 | mode, |
1160 | adjusted_mode); | 1153 | adjusted_mode); |
1161 | } | 1154 | } |
@@ -1194,11 +1187,11 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder, | |||
1194 | } | 1187 | } |
1195 | 1188 | ||
1196 | /* Clock computation needs to happen after pixel multiplier. */ | 1189 | /* Clock computation needs to happen after pixel multiplier. */ |
1197 | if (intel_sdvo->is_tv) | 1190 | if (IS_TV(intel_sdvo_connector)) |
1198 | i9xx_adjust_sdvo_tv_clock(pipe_config); | 1191 | i9xx_adjust_sdvo_tv_clock(pipe_config); |
1199 | 1192 | ||
1200 | /* Set user selected PAR to incoming mode's member */ | 1193 | /* Set user selected PAR to incoming mode's member */ |
1201 | if (intel_sdvo->is_hdmi) | 1194 | if (intel_sdvo_connector->is_hdmi) |
1202 | adjusted_mode->picture_aspect_ratio = conn_state->picture_aspect_ratio; | 1195 | adjusted_mode->picture_aspect_ratio = conn_state->picture_aspect_ratio; |
1203 | 1196 | ||
1204 | return true; | 1197 | return true; |
@@ -1275,6 +1268,8 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, | |||
1275 | const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode; | 1268 | const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode; |
1276 | const struct intel_sdvo_connector_state *sdvo_state = | 1269 | const struct intel_sdvo_connector_state *sdvo_state = |
1277 | to_intel_sdvo_connector_state(conn_state); | 1270 | to_intel_sdvo_connector_state(conn_state); |
1271 | const struct intel_sdvo_connector *intel_sdvo_connector = | ||
1272 | to_intel_sdvo_connector(conn_state->connector); | ||
1278 | const struct drm_display_mode *mode = &crtc_state->base.mode; | 1273 | const struct drm_display_mode *mode = &crtc_state->base.mode; |
1279 | struct intel_sdvo *intel_sdvo = to_sdvo(intel_encoder); | 1274 | struct intel_sdvo *intel_sdvo = to_sdvo(intel_encoder); |
1280 | u32 sdvox; | 1275 | u32 sdvox; |
@@ -1304,7 +1299,7 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, | |||
1304 | return; | 1299 | return; |
1305 | 1300 | ||
1306 | /* lvds has a special fixed output timing. */ | 1301 | /* lvds has a special fixed output timing. */ |
1307 | if (intel_sdvo->is_lvds) | 1302 | if (IS_LVDS(intel_sdvo_connector)) |
1308 | intel_sdvo_get_dtd_from_mode(&output_dtd, | 1303 | intel_sdvo_get_dtd_from_mode(&output_dtd, |
1309 | intel_sdvo->sdvo_lvds_fixed_mode); | 1304 | intel_sdvo->sdvo_lvds_fixed_mode); |
1310 | else | 1305 | else |
@@ -1325,13 +1320,13 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, | |||
1325 | } else | 1320 | } else |
1326 | intel_sdvo_set_encode(intel_sdvo, SDVO_ENCODE_DVI); | 1321 | intel_sdvo_set_encode(intel_sdvo, SDVO_ENCODE_DVI); |
1327 | 1322 | ||
1328 | if (intel_sdvo->is_tv && | 1323 | if (IS_TV(intel_sdvo_connector) && |
1329 | !intel_sdvo_set_tv_format(intel_sdvo, conn_state)) | 1324 | !intel_sdvo_set_tv_format(intel_sdvo, conn_state)) |
1330 | return; | 1325 | return; |
1331 | 1326 | ||
1332 | intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); | 1327 | intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); |
1333 | 1328 | ||
1334 | if (intel_sdvo->is_tv || intel_sdvo->is_lvds) | 1329 | if (IS_TV(intel_sdvo_connector) || IS_LVDS(intel_sdvo_connector)) |
1335 | input_dtd.part2.sdvo_flags = intel_sdvo->dtd_sdvo_flags; | 1330 | input_dtd.part2.sdvo_flags = intel_sdvo->dtd_sdvo_flags; |
1336 | if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd)) | 1331 | if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd)) |
1337 | DRM_INFO("Setting input timings on %s failed\n", | 1332 | DRM_INFO("Setting input timings on %s failed\n", |
@@ -1630,6 +1625,8 @@ intel_sdvo_mode_valid(struct drm_connector *connector, | |||
1630 | struct drm_display_mode *mode) | 1625 | struct drm_display_mode *mode) |
1631 | { | 1626 | { |
1632 | struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); | 1627 | struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); |
1628 | struct intel_sdvo_connector *intel_sdvo_connector = | ||
1629 | to_intel_sdvo_connector(connector); | ||
1633 | int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; | 1630 | int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; |
1634 | 1631 | ||
1635 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) | 1632 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) |
@@ -1644,7 +1641,7 @@ intel_sdvo_mode_valid(struct drm_connector *connector, | |||
1644 | if (mode->clock > max_dotclk) | 1641 | if (mode->clock > max_dotclk) |
1645 | return MODE_CLOCK_HIGH; | 1642 | return MODE_CLOCK_HIGH; |
1646 | 1643 | ||
1647 | if (intel_sdvo->is_lvds) { | 1644 | if (IS_LVDS(intel_sdvo_connector)) { |
1648 | if (mode->hdisplay > intel_sdvo->sdvo_lvds_fixed_mode->hdisplay) | 1645 | if (mode->hdisplay > intel_sdvo->sdvo_lvds_fixed_mode->hdisplay) |
1649 | return MODE_PANEL; | 1646 | return MODE_PANEL; |
1650 | 1647 | ||
@@ -1759,6 +1756,8 @@ static enum drm_connector_status | |||
1759 | intel_sdvo_tmds_sink_detect(struct drm_connector *connector) | 1756 | intel_sdvo_tmds_sink_detect(struct drm_connector *connector) |
1760 | { | 1757 | { |
1761 | struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); | 1758 | struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); |
1759 | struct intel_sdvo_connector *intel_sdvo_connector = | ||
1760 | to_intel_sdvo_connector(connector); | ||
1762 | enum drm_connector_status status; | 1761 | enum drm_connector_status status; |
1763 | struct edid *edid; | 1762 | struct edid *edid; |
1764 | 1763 | ||
@@ -1797,7 +1796,7 @@ intel_sdvo_tmds_sink_detect(struct drm_connector *connector) | |||
1797 | /* DDC bus is shared, match EDID to connector type */ | 1796 | /* DDC bus is shared, match EDID to connector type */ |
1798 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { | 1797 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { |
1799 | status = connector_status_connected; | 1798 | status = connector_status_connected; |
1800 | if (intel_sdvo->is_hdmi) { | 1799 | if (intel_sdvo_connector->is_hdmi) { |
1801 | intel_sdvo->has_hdmi_monitor = drm_detect_hdmi_monitor(edid); | 1800 | intel_sdvo->has_hdmi_monitor = drm_detect_hdmi_monitor(edid); |
1802 | intel_sdvo->has_hdmi_audio = drm_detect_monitor_audio(edid); | 1801 | intel_sdvo->has_hdmi_audio = drm_detect_monitor_audio(edid); |
1803 | intel_sdvo->rgb_quant_range_selectable = | 1802 | intel_sdvo->rgb_quant_range_selectable = |
@@ -1875,17 +1874,6 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) | |||
1875 | ret = connector_status_connected; | 1874 | ret = connector_status_connected; |
1876 | } | 1875 | } |
1877 | 1876 | ||
1878 | /* May update encoder flag for like clock for SDVO TV, etc.*/ | ||
1879 | if (ret == connector_status_connected) { | ||
1880 | intel_sdvo->is_tv = false; | ||
1881 | intel_sdvo->is_lvds = false; | ||
1882 | |||
1883 | if (response & SDVO_TV_MASK) | ||
1884 | intel_sdvo->is_tv = true; | ||
1885 | if (response & SDVO_LVDS_MASK) | ||
1886 | intel_sdvo->is_lvds = intel_sdvo->sdvo_lvds_fixed_mode != NULL; | ||
1887 | } | ||
1888 | |||
1889 | return ret; | 1877 | return ret; |
1890 | } | 1878 | } |
1891 | 1879 | ||
@@ -2054,16 +2042,6 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) | |||
2054 | * arranged in priority order. | 2042 | * arranged in priority order. |
2055 | */ | 2043 | */ |
2056 | intel_ddc_get_modes(connector, &intel_sdvo->ddc); | 2044 | intel_ddc_get_modes(connector, &intel_sdvo->ddc); |
2057 | |||
2058 | list_for_each_entry(newmode, &connector->probed_modes, head) { | ||
2059 | if (newmode->type & DRM_MODE_TYPE_PREFERRED) { | ||
2060 | intel_sdvo->sdvo_lvds_fixed_mode = | ||
2061 | drm_mode_duplicate(connector->dev, newmode); | ||
2062 | |||
2063 | intel_sdvo->is_lvds = true; | ||
2064 | break; | ||
2065 | } | ||
2066 | } | ||
2067 | } | 2045 | } |
2068 | 2046 | ||
2069 | static int intel_sdvo_get_modes(struct drm_connector *connector) | 2047 | static int intel_sdvo_get_modes(struct drm_connector *connector) |
@@ -2555,7 +2533,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) | |||
2555 | if (INTEL_GEN(dev_priv) >= 4 && | 2533 | if (INTEL_GEN(dev_priv) >= 4 && |
2556 | intel_sdvo_is_hdmi_connector(intel_sdvo, device)) { | 2534 | intel_sdvo_is_hdmi_connector(intel_sdvo, device)) { |
2557 | connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; | 2535 | connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; |
2558 | intel_sdvo->is_hdmi = true; | 2536 | intel_sdvo_connector->is_hdmi = true; |
2559 | } | 2537 | } |
2560 | 2538 | ||
2561 | if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) { | 2539 | if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) { |
@@ -2563,7 +2541,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) | |||
2563 | return false; | 2541 | return false; |
2564 | } | 2542 | } |
2565 | 2543 | ||
2566 | if (intel_sdvo->is_hdmi) | 2544 | if (intel_sdvo_connector->is_hdmi) |
2567 | intel_sdvo_add_hdmi_properties(intel_sdvo, intel_sdvo_connector); | 2545 | intel_sdvo_add_hdmi_properties(intel_sdvo, intel_sdvo_connector); |
2568 | 2546 | ||
2569 | return true; | 2547 | return true; |
@@ -2591,8 +2569,6 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) | |||
2591 | intel_sdvo->controlled_output |= type; | 2569 | intel_sdvo->controlled_output |= type; |
2592 | intel_sdvo_connector->output_flag = type; | 2570 | intel_sdvo_connector->output_flag = type; |
2593 | 2571 | ||
2594 | intel_sdvo->is_tv = true; | ||
2595 | |||
2596 | if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) { | 2572 | if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) { |
2597 | kfree(intel_sdvo_connector); | 2573 | kfree(intel_sdvo_connector); |
2598 | return false; | 2574 | return false; |
@@ -2654,6 +2630,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) | |||
2654 | struct drm_connector *connector; | 2630 | struct drm_connector *connector; |
2655 | struct intel_connector *intel_connector; | 2631 | struct intel_connector *intel_connector; |
2656 | struct intel_sdvo_connector *intel_sdvo_connector; | 2632 | struct intel_sdvo_connector *intel_sdvo_connector; |
2633 | struct drm_display_mode *mode; | ||
2657 | 2634 | ||
2658 | DRM_DEBUG_KMS("initialising LVDS device %d\n", device); | 2635 | DRM_DEBUG_KMS("initialising LVDS device %d\n", device); |
2659 | 2636 | ||
@@ -2682,6 +2659,19 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) | |||
2682 | if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) | 2659 | if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) |
2683 | goto err; | 2660 | goto err; |
2684 | 2661 | ||
2662 | intel_sdvo_get_lvds_modes(connector); | ||
2663 | |||
2664 | list_for_each_entry(mode, &connector->probed_modes, head) { | ||
2665 | if (mode->type & DRM_MODE_TYPE_PREFERRED) { | ||
2666 | intel_sdvo->sdvo_lvds_fixed_mode = | ||
2667 | drm_mode_duplicate(connector->dev, mode); | ||
2668 | break; | ||
2669 | } | ||
2670 | } | ||
2671 | |||
2672 | if (!intel_sdvo->sdvo_lvds_fixed_mode) | ||
2673 | goto err; | ||
2674 | |||
2685 | return true; | 2675 | return true; |
2686 | 2676 | ||
2687 | err: | 2677 | err: |
@@ -2692,9 +2682,6 @@ err: | |||
2692 | static bool | 2682 | static bool |
2693 | intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags) | 2683 | intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags) |
2694 | { | 2684 | { |
2695 | intel_sdvo->is_tv = false; | ||
2696 | intel_sdvo->is_lvds = false; | ||
2697 | |||
2698 | /* SDVO requires XXX1 function may not exist unless it has XXX0 function.*/ | 2685 | /* SDVO requires XXX1 function may not exist unless it has XXX0 function.*/ |
2699 | 2686 | ||
2700 | if (flags & SDVO_OUTPUT_TMDS0) | 2687 | if (flags & SDVO_OUTPUT_TMDS0) |