aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nv04_dfp.c
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@riseup.net>2010-07-20 10:48:08 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-08-05 18:34:59 -0400
commit4a9f822fe1a6ca5de7d8cdd5efbead3b9ab4283b (patch)
tree201e0191a1414ff04fe867e2bc6b2dfae8809fe3 /drivers/gpu/drm/nouveau/nv04_dfp.c
parentd2f4e89254b5816925a207a221e6b26100357eea (diff)
drm/nv17-nv4x: Attempt to init some external TMDS transmitters.
sil164 and friends are the most common, usually they just need to be poked once because a fixed configuration is enough for any modes and clocks, so they worked without this patch if the BIOS had done a good job on POST. Display couldn't survive a suspend/resume cycle though. Unfortunately, BIOS scripts are useless here. Signed-off-by: Francisco Jerez <currojerez@riseup.net> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv04_dfp.c')
-rw-r--r--drivers/gpu/drm/nouveau/nv04_dfp.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c
index 3311f3a8c81..9871570d2ff 100644
--- a/drivers/gpu/drm/nouveau/nv04_dfp.c
+++ b/drivers/gpu/drm/nouveau/nv04_dfp.c
@@ -34,6 +34,8 @@
34#include "nouveau_hw.h" 34#include "nouveau_hw.h"
35#include "nvreg.h" 35#include "nvreg.h"
36 36
37#include "i2c/sil164.h"
38
37#define FP_TG_CONTROL_ON (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS | \ 39#define FP_TG_CONTROL_ON (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS | \
38 NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS | \ 40 NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS | \
39 NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS) 41 NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS)
@@ -429,6 +431,11 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
429 else 431 else
430 NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000); 432 NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000);
431 433
434 /* Init external transmitters */
435 if (get_slave_funcs(encoder))
436 get_slave_funcs(encoder)->mode_set(encoder, &nv_encoder->mode,
437 &nv_encoder->mode);
438
432 helper->dpms(encoder, DRM_MODE_DPMS_ON); 439 helper->dpms(encoder, DRM_MODE_DPMS_ON);
433 440
434 NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", 441 NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n",
@@ -550,10 +557,41 @@ static void nv04_dfp_destroy(struct drm_encoder *encoder)
550 557
551 NV_DEBUG_KMS(encoder->dev, "\n"); 558 NV_DEBUG_KMS(encoder->dev, "\n");
552 559
560 if (get_slave_funcs(encoder))
561 get_slave_funcs(encoder)->destroy(encoder);
562
553 drm_encoder_cleanup(encoder); 563 drm_encoder_cleanup(encoder);
554 kfree(nv_encoder); 564 kfree(nv_encoder);
555} 565}
556 566
567static void nv04_tmds_slave_init(struct drm_encoder *encoder)
568{
569 struct drm_device *dev = encoder->dev;
570 struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
571 struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, 2);
572 struct i2c_board_info info[] = {
573 {
574 .type = "sil164",
575 .addr = (dcb->tmdsconf.slave_addr == 0x7 ? 0x3a : 0x38),
576 .platform_data = &(struct sil164_encoder_params) {
577 SIL164_INPUT_EDGE_RISING
578 }
579 },
580 { }
581 };
582 int type;
583
584 if (!nv_gf4_disp_arch(dev) || !i2c)
585 return;
586
587 type = nouveau_i2c_identify(dev, "TMDS transmitter", info, 2);
588 if (type < 0)
589 return;
590
591 drm_i2c_encoder_init(dev, to_encoder_slave(encoder),
592 &i2c->adapter, &info[type]);
593}
594
557static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = { 595static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = {
558 .dpms = nv04_lvds_dpms, 596 .dpms = nv04_lvds_dpms,
559 .save = nv04_dfp_save, 597 .save = nv04_dfp_save,
@@ -616,6 +654,10 @@ nv04_dfp_create(struct drm_connector *connector, struct dcb_entry *entry)
616 encoder->possible_crtcs = entry->heads; 654 encoder->possible_crtcs = entry->heads;
617 encoder->possible_clones = 0; 655 encoder->possible_clones = 0;
618 656
657 if (entry->type == OUTPUT_TMDS &&
658 entry->location != DCB_LOC_ON_CHIP)
659 nv04_tmds_slave_init(encoder);
660
619 drm_mode_connector_attach_encoder(connector, encoder); 661 drm_mode_connector_attach_encoder(connector, encoder);
620 return 0; 662 return 0;
621} 663}