aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_ddi.c
diff options
context:
space:
mode:
authorPaulo Zanoni <paulo.r.zanoni@intel.com>2012-10-26 17:05:52 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-11-11 17:51:08 -0500
commit00c09d70df6b30c980f20facc1db3def3f5a637e (patch)
tree740478e3bb71cdc18ae91ba03e9f3ef9513c3d46 /drivers/gpu/drm/i915/intel_ddi.c
parentbcbc889bc44a781577479939490f6b7452d5b808 (diff)
drm/i915: create the DDI encoder
Now intel_ddi_init is just like intel_hdmi_init and intel_dp_init: it inits the encoder and then calls the proper init_connector functions. Notice that for non-eDP ports we call both HDMI and DP connector init, so we have 2 connectors attached to each DDI encoder. After this change, intel_hdmi_init and intel_dp_init are only called by Ivy Bridge and earlier, while hardware containing DDI outputs should call intel_ddi_init. Also added/removed quite a few "static" keywords due to the fact that some function pointers were moved from intel_dp.c and intel_hdmi.c to intel_ddi.c. DP finally works on Haswell now! \o/ Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Reviewed-by: Damien Lespiau <damien.lespiau@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ddi.c')
-rw-r--r--drivers/gpu/drm/i915/intel_ddi.c143
1 files changed, 106 insertions, 37 deletions
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 58a529d9f1e3..67bd6ba64a35 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -64,7 +64,7 @@ static enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
64 int type = intel_encoder->type; 64 int type = intel_encoder->type;
65 65
66 if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP || 66 if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP ||
67 type == INTEL_OUTPUT_HDMI) { 67 type == INTEL_OUTPUT_HDMI || type == INTEL_OUTPUT_UNKNOWN) {
68 struct intel_digital_port *intel_dig_port = 68 struct intel_digital_port *intel_dig_port =
69 enc_to_dig_port(encoder); 69 enc_to_dig_port(encoder);
70 return intel_dig_port->port; 70 return intel_dig_port->port;
@@ -227,35 +227,6 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
227 DRM_DEBUG_KMS("FDI train done.\n"); 227 DRM_DEBUG_KMS("FDI train done.\n");
228} 228}
229 229
230/* For DDI connections, it is possible to support different outputs over the
231 * same DDI port, such as HDMI or DP or even VGA via FDI. So we don't know by
232 * the time the output is detected what exactly is on the other end of it. This
233 * function aims at providing support for this detection and proper output
234 * configuration.
235 */
236void intel_ddi_init(struct drm_device *dev, enum port port)
237{
238 /* For now, we don't do any proper output detection and assume that we
239 * handle HDMI only */
240
241 switch(port){
242 case PORT_A:
243 DRM_DEBUG_DRIVER("Found digital output on DDI port A\n");
244 intel_dp_init(dev, DDI_BUF_CTL_A, PORT_A);
245 break;
246 /* Assume that the ports B, C and D are working in HDMI mode for now */
247 case PORT_B:
248 case PORT_C:
249 case PORT_D:
250 intel_hdmi_init(dev, DDI_BUF_CTL(port), port);
251 break;
252 default:
253 DRM_DEBUG_DRIVER("No handlers defined for port %d, skipping DDI initialization\n",
254 port);
255 break;
256 }
257}
258
259/* WRPLL clock dividers */ 230/* WRPLL clock dividers */
260struct wrpll_tmds_clock { 231struct wrpll_tmds_clock {
261 u32 clock; 232 u32 clock;
@@ -642,9 +613,9 @@ static const struct wrpll_tmds_clock wrpll_tmds_clock_table[] = {
642 {298000, 2, 21, 19}, 613 {298000, 2, 21, 19},
643}; 614};
644 615
645void intel_ddi_mode_set(struct drm_encoder *encoder, 616static void intel_ddi_mode_set(struct drm_encoder *encoder,
646 struct drm_display_mode *mode, 617 struct drm_display_mode *mode,
647 struct drm_display_mode *adjusted_mode) 618 struct drm_display_mode *adjusted_mode)
648{ 619{
649 struct drm_crtc *crtc = encoder->crtc; 620 struct drm_crtc *crtc = encoder->crtc;
650 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 621 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -1192,7 +1163,7 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc)
1192 TRANS_CLK_SEL_DISABLED); 1163 TRANS_CLK_SEL_DISABLED);
1193} 1164}
1194 1165
1195void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) 1166static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
1196{ 1167{
1197 struct drm_encoder *encoder = &intel_encoder->base; 1168 struct drm_encoder *encoder = &intel_encoder->base;
1198 struct drm_crtc *crtc = encoder->crtc; 1169 struct drm_crtc *crtc = encoder->crtc;
@@ -1234,7 +1205,7 @@ static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
1234 DRM_ERROR("Timeout waiting for DDI BUF %c idle bit\n", port_name(port)); 1205 DRM_ERROR("Timeout waiting for DDI BUF %c idle bit\n", port_name(port));
1235} 1206}
1236 1207
1237void intel_ddi_post_disable(struct intel_encoder *intel_encoder) 1208static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
1238{ 1209{
1239 struct drm_encoder *encoder = &intel_encoder->base; 1210 struct drm_encoder *encoder = &intel_encoder->base;
1240 struct drm_i915_private *dev_priv = encoder->dev->dev_private; 1211 struct drm_i915_private *dev_priv = encoder->dev->dev_private;
@@ -1267,7 +1238,7 @@ void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
1267 I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE); 1238 I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
1268} 1239}
1269 1240
1270void intel_enable_ddi(struct intel_encoder *intel_encoder) 1241static void intel_enable_ddi(struct intel_encoder *intel_encoder)
1271{ 1242{
1272 struct drm_encoder *encoder = &intel_encoder->base; 1243 struct drm_encoder *encoder = &intel_encoder->base;
1273 struct drm_device *dev = encoder->dev; 1244 struct drm_device *dev = encoder->dev;
@@ -1288,7 +1259,7 @@ void intel_enable_ddi(struct intel_encoder *intel_encoder)
1288 } 1259 }
1289} 1260}
1290 1261
1291void intel_disable_ddi(struct intel_encoder *intel_encoder) 1262static void intel_disable_ddi(struct intel_encoder *intel_encoder)
1292{ 1263{
1293 struct drm_encoder *encoder = &intel_encoder->base; 1264 struct drm_encoder *encoder = &intel_encoder->base;
1294 int type = intel_encoder->type; 1265 int type = intel_encoder->type;
@@ -1371,3 +1342,101 @@ void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder)
1371 1342
1372 udelay(600); 1343 udelay(600);
1373} 1344}
1345
1346static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder)
1347{
1348 struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
1349 int type = intel_encoder->type;
1350
1351 if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP)
1352 intel_dp_check_link_status(intel_dp);
1353}
1354
1355static void intel_ddi_destroy(struct drm_encoder *encoder)
1356{
1357 /* HDMI has nothing special to destroy, so we can go with this. */
1358 intel_dp_encoder_destroy(encoder);
1359}
1360
1361static bool intel_ddi_mode_fixup(struct drm_encoder *encoder,
1362 const struct drm_display_mode *mode,
1363 struct drm_display_mode *adjusted_mode)
1364{
1365 struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
1366 int type = intel_encoder->type;
1367
1368 WARN(type == INTEL_OUTPUT_UNKNOWN, "mode_fixup() on unknown output!\n");
1369
1370 if (type == INTEL_OUTPUT_HDMI)
1371 return intel_hdmi_mode_fixup(encoder, mode, adjusted_mode);
1372 else
1373 return intel_dp_mode_fixup(encoder, mode, adjusted_mode);
1374}
1375
1376static const struct drm_encoder_funcs intel_ddi_funcs = {
1377 .destroy = intel_ddi_destroy,
1378};
1379
1380static const struct drm_encoder_helper_funcs intel_ddi_helper_funcs = {
1381 .mode_fixup = intel_ddi_mode_fixup,
1382 .mode_set = intel_ddi_mode_set,
1383 .disable = intel_encoder_noop,
1384};
1385
1386void intel_ddi_init(struct drm_device *dev, enum port port)
1387{
1388 struct intel_digital_port *intel_dig_port;
1389 struct intel_encoder *intel_encoder;
1390 struct drm_encoder *encoder;
1391 struct intel_connector *hdmi_connector = NULL;
1392 struct intel_connector *dp_connector = NULL;
1393
1394 intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL);
1395 if (!intel_dig_port)
1396 return;
1397
1398 dp_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
1399 if (!dp_connector) {
1400 kfree(intel_dig_port);
1401 return;
1402 }
1403
1404 if (port != PORT_A) {
1405 hdmi_connector = kzalloc(sizeof(struct intel_connector),
1406 GFP_KERNEL);
1407 if (!hdmi_connector) {
1408 kfree(dp_connector);
1409 kfree(intel_dig_port);
1410 return;
1411 }
1412 }
1413
1414 intel_encoder = &intel_dig_port->base;
1415 encoder = &intel_encoder->base;
1416
1417 drm_encoder_init(dev, encoder, &intel_ddi_funcs,
1418 DRM_MODE_ENCODER_TMDS);
1419 drm_encoder_helper_add(encoder, &intel_ddi_helper_funcs);
1420
1421 intel_encoder->enable = intel_enable_ddi;
1422 intel_encoder->pre_enable = intel_ddi_pre_enable;
1423 intel_encoder->disable = intel_disable_ddi;
1424 intel_encoder->post_disable = intel_ddi_post_disable;
1425 intel_encoder->get_hw_state = intel_ddi_get_hw_state;
1426
1427 intel_dig_port->port = port;
1428 if (hdmi_connector)
1429 intel_dig_port->hdmi.sdvox_reg = DDI_BUF_CTL(port);
1430 else
1431 intel_dig_port->hdmi.sdvox_reg = 0;
1432 intel_dig_port->dp.output_reg = DDI_BUF_CTL(port);
1433
1434 intel_encoder->type = INTEL_OUTPUT_UNKNOWN;
1435 intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
1436 intel_encoder->cloneable = false;
1437 intel_encoder->hot_plug = intel_ddi_hot_plug;
1438
1439 if (hdmi_connector)
1440 intel_hdmi_init_connector(intel_dig_port, hdmi_connector);
1441 intel_dp_init_connector(intel_dig_port, dp_connector);
1442}