|
@@ -33,15 +33,103 @@
|
|
|
#include "nouveau_hw.h"
|
|
|
#include "nv17_tv.h"
|
|
|
|
|
|
+static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
|
|
|
+{
|
|
|
+ struct drm_device *dev = encoder->dev;
|
|
|
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
|
|
|
+ uint32_t testval, regoffset = nv04_dac_output_offset(encoder);
|
|
|
+ uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end,
|
|
|
+ fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c;
|
|
|
+ uint32_t sample = 0;
|
|
|
+ int head;
|
|
|
+
|
|
|
+#define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20)
|
|
|
+ testval = RGB_TEST_DATA(0x82, 0xeb, 0x82);
|
|
|
+ if (dev_priv->vbios->tvdactestval)
|
|
|
+ testval = dev_priv->vbios->tvdactestval;
|
|
|
+
|
|
|
+ dacclk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset);
|
|
|
+ head = (dacclk & 0x100) >> 8;
|
|
|
+
|
|
|
+ /* Save the previous state. */
|
|
|
+ gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1);
|
|
|
+ gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0);
|
|
|
+ fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL);
|
|
|
+ fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START);
|
|
|
+ fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END);
|
|
|
+ fp_control = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL);
|
|
|
+ test_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset);
|
|
|
+ ctv_1c = NVReadRAMDAC(dev, head, 0x680c1c);
|
|
|
+ ctv_14 = NVReadRAMDAC(dev, head, 0x680c14);
|
|
|
+ ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c);
|
|
|
+
|
|
|
+ /* Prepare the DAC for load detection. */
|
|
|
+ nv17_gpio_set(dev, DCB_GPIO_TVDAC1, true);
|
|
|
+ nv17_gpio_set(dev, DCB_GPIO_TVDAC0, true);
|
|
|
+
|
|
|
+ NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343);
|
|
|
+ NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047);
|
|
|
+ NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, 1183);
|
|
|
+ NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL,
|
|
|
+ NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS |
|
|
|
+ NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12 |
|
|
|
+ NV_PRAMDAC_FP_TG_CONTROL_READ_PROG |
|
|
|
+ NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS |
|
|
|
+ NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS);
|
|
|
+
|
|
|
+ NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, 0);
|
|
|
+
|
|
|
+ NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset,
|
|
|
+ (dacclk & ~0xff) | 0x22);
|
|
|
+ msleep(1);
|
|
|
+ NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset,
|
|
|
+ (dacclk & ~0xff) | 0x21);
|
|
|
+
|
|
|
+ NVWriteRAMDAC(dev, head, 0x680c1c, 1 << 20);
|
|
|
+ NVWriteRAMDAC(dev, head, 0x680c14, 4 << 16);
|
|
|
+
|
|
|
+ /* Sample pin 0x4 (usually S-video luma). */
|
|
|
+ NVWriteRAMDAC(dev, head, 0x680c6c, testval >> 10 & 0x3ff);
|
|
|
+ msleep(20);
|
|
|
+ sample |= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset)
|
|
|
+ & 0x4 << 28;
|
|
|
+
|
|
|
+ /* Sample the remaining pins. */
|
|
|
+ NVWriteRAMDAC(dev, head, 0x680c6c, testval & 0x3ff);
|
|
|
+ msleep(20);
|
|
|
+ sample |= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset)
|
|
|
+ & 0xa << 28;
|
|
|
+
|
|
|
+ /* Restore the previous state. */
|
|
|
+ NVWriteRAMDAC(dev, head, 0x680c1c, ctv_1c);
|
|
|
+ NVWriteRAMDAC(dev, head, 0x680c14, ctv_14);
|
|
|
+ NVWriteRAMDAC(dev, head, 0x680c6c, ctv_6c);
|
|
|
+ NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, dacclk);
|
|
|
+ NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, test_ctrl);
|
|
|
+ NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL, fp_control);
|
|
|
+ NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end);
|
|
|
+ NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start);
|
|
|
+ NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal);
|
|
|
+ nv17_gpio_set(dev, DCB_GPIO_TVDAC1, gpio1);
|
|
|
+ nv17_gpio_set(dev, DCB_GPIO_TVDAC0, gpio0);
|
|
|
+
|
|
|
+ return sample;
|
|
|
+}
|
|
|
+
|
|
|
static enum drm_connector_status
|
|
|
nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector)
|
|
|
{
|
|
|
struct drm_device *dev = encoder->dev;
|
|
|
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
|
|
|
struct drm_mode_config *conf = &dev->mode_config;
|
|
|
struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
|
|
|
struct dcb_entry *dcb = tv_enc->base.dcb;
|
|
|
|
|
|
- tv_enc->pin_mask = nv17_dac_sample_load(encoder) >> 28 & 0xe;
|
|
|
+ if (dev_priv->chipset == 0x42 ||
|
|
|
+ dev_priv->chipset == 0x43)
|
|
|
+ tv_enc->pin_mask = nv42_tv_sample_load(encoder) >> 28 & 0xe;
|
|
|
+ else
|
|
|
+ tv_enc->pin_mask = nv17_dac_sample_load(encoder) >> 28 & 0xe;
|
|
|
|
|
|
switch (tv_enc->pin_mask) {
|
|
|
case 0x2:
|