diff options
| author | Francisco Jerez <currojerez@riseup.net> | 2009-12-17 12:57:44 -0500 |
|---|---|---|
| committer | Ben Skeggs <bskeggs@redhat.com> | 2010-01-10 18:06:35 -0500 |
| commit | 0829168b474663d8b13f6105368dbbf4a1a03256 (patch) | |
| tree | 86ac590464503b008e04ff3bdb820c24956ca69e | |
| parent | 11d6eb2af53395b25e1d6b8b79bb9a999c3e4c4d (diff) | |
drm/nouveau: Implement nv42-nv43 TV load detection.
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
| -rw-r--r-- | drivers/gpu/drm/nouveau/nv17_tv.c | 90 |
1 files changed, 89 insertions, 1 deletions
diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c index 5fa4242e4c7d..58b917c3341b 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.c +++ b/drivers/gpu/drm/nouveau/nv17_tv.c | |||
| @@ -33,15 +33,103 @@ | |||
| 33 | #include "nouveau_hw.h" | 33 | #include "nouveau_hw.h" |
| 34 | #include "nv17_tv.h" | 34 | #include "nv17_tv.h" |
| 35 | 35 | ||
| 36 | static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) | ||
| 37 | { | ||
| 38 | struct drm_device *dev = encoder->dev; | ||
| 39 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 40 | uint32_t testval, regoffset = nv04_dac_output_offset(encoder); | ||
| 41 | uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end, | ||
| 42 | fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c; | ||
| 43 | uint32_t sample = 0; | ||
| 44 | int head; | ||
| 45 | |||
| 46 | #define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20) | ||
| 47 | testval = RGB_TEST_DATA(0x82, 0xeb, 0x82); | ||
| 48 | if (dev_priv->vbios->tvdactestval) | ||
| 49 | testval = dev_priv->vbios->tvdactestval; | ||
| 50 | |||
| 51 | dacclk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset); | ||
| 52 | head = (dacclk & 0x100) >> 8; | ||
| 53 | |||
| 54 | /* Save the previous state. */ | ||
| 55 | gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1); | ||
| 56 | gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0); | ||
| 57 | fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL); | ||
| 58 | fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START); | ||
| 59 | fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END); | ||
| 60 | fp_control = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL); | ||
| 61 | test_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); | ||
| 62 | ctv_1c = NVReadRAMDAC(dev, head, 0x680c1c); | ||
| 63 | ctv_14 = NVReadRAMDAC(dev, head, 0x680c14); | ||
| 64 | ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c); | ||
| 65 | |||
| 66 | /* Prepare the DAC for load detection. */ | ||
| 67 | nv17_gpio_set(dev, DCB_GPIO_TVDAC1, true); | ||
| 68 | nv17_gpio_set(dev, DCB_GPIO_TVDAC0, true); | ||
| 69 | |||
| 70 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343); | ||
| 71 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047); | ||
| 72 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, 1183); | ||
| 73 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL, | ||
| 74 | NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS | | ||
| 75 | NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12 | | ||
| 76 | NV_PRAMDAC_FP_TG_CONTROL_READ_PROG | | ||
| 77 | NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS | | ||
| 78 | NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS); | ||
| 79 | |||
| 80 | NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, 0); | ||
| 81 | |||
| 82 | NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, | ||
| 83 | (dacclk & ~0xff) | 0x22); | ||
| 84 | msleep(1); | ||
| 85 | NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, | ||
| 86 | (dacclk & ~0xff) | 0x21); | ||
| 87 | |||
| 88 | NVWriteRAMDAC(dev, head, 0x680c1c, 1 << 20); | ||
| 89 | NVWriteRAMDAC(dev, head, 0x680c14, 4 << 16); | ||
| 90 | |||
| 91 | /* Sample pin 0x4 (usually S-video luma). */ | ||
| 92 | NVWriteRAMDAC(dev, head, 0x680c6c, testval >> 10 & 0x3ff); | ||
| 93 | msleep(20); | ||
| 94 | sample |= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset) | ||
| 95 | & 0x4 << 28; | ||
| 96 | |||
| 97 | /* Sample the remaining pins. */ | ||
| 98 | NVWriteRAMDAC(dev, head, 0x680c6c, testval & 0x3ff); | ||
| 99 | msleep(20); | ||
| 100 | sample |= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset) | ||
| 101 | & 0xa << 28; | ||
| 102 | |||
| 103 | /* Restore the previous state. */ | ||
| 104 | NVWriteRAMDAC(dev, head, 0x680c1c, ctv_1c); | ||
| 105 | NVWriteRAMDAC(dev, head, 0x680c14, ctv_14); | ||
| 106 | NVWriteRAMDAC(dev, head, 0x680c6c, ctv_6c); | ||
| 107 | NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, dacclk); | ||
| 108 | NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, test_ctrl); | ||
| 109 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL, fp_control); | ||
| 110 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end); | ||
| 111 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start); | ||
| 112 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal); | ||
| 113 | nv17_gpio_set(dev, DCB_GPIO_TVDAC1, gpio1); | ||
| 114 | nv17_gpio_set(dev, DCB_GPIO_TVDAC0, gpio0); | ||
| 115 | |||
| 116 | return sample; | ||
| 117 | } | ||
| 118 | |||
| 36 | static enum drm_connector_status | 119 | static enum drm_connector_status |
| 37 | nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) | 120 | nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) |
| 38 | { | 121 | { |
| 39 | struct drm_device *dev = encoder->dev; | 122 | struct drm_device *dev = encoder->dev; |
| 123 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 40 | struct drm_mode_config *conf = &dev->mode_config; | 124 | struct drm_mode_config *conf = &dev->mode_config; |
| 41 | struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); | 125 | struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); |
| 42 | struct dcb_entry *dcb = tv_enc->base.dcb; | 126 | struct dcb_entry *dcb = tv_enc->base.dcb; |
| 43 | 127 | ||
| 44 | tv_enc->pin_mask = nv17_dac_sample_load(encoder) >> 28 & 0xe; | 128 | if (dev_priv->chipset == 0x42 || |
| 129 | dev_priv->chipset == 0x43) | ||
| 130 | tv_enc->pin_mask = nv42_tv_sample_load(encoder) >> 28 & 0xe; | ||
| 131 | else | ||
| 132 | tv_enc->pin_mask = nv17_dac_sample_load(encoder) >> 28 & 0xe; | ||
| 45 | 133 | ||
| 46 | switch (tv_enc->pin_mask) { | 134 | switch (tv_enc->pin_mask) { |
| 47 | case 0x2: | 135 | case 0x2: |
