linux/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2009 Francisco Jerez.
   3 * All Rights Reserved.
   4 *
   5 * Permission is hereby granted, free of charge, to any person obtaining
   6 * a copy of this software and associated documentation files (the
   7 * "Software"), to deal in the Software without restriction, including
   8 * without limitation the rights to use, copy, modify, merge, publish,
   9 * distribute, sublicense, and/or sell copies of the Software, and to
  10 * permit persons to whom the Software is furnished to do so, subject to
  11 * the following conditions:
  12 *
  13 * The above copyright notice and this permission notice (including the
  14 * next paragraph) shall be included in all copies or substantial
  15 * portions of the Software.
  16 *
  17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
  21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24 *
  25 */
  26
  27#include <drm/drm_crtc_helper.h>
  28#include <drm/drm_probe_helper.h>
  29#include "nouveau_drv.h"
  30#include "nouveau_reg.h"
  31#include "nouveau_encoder.h"
  32#include "nouveau_connector.h"
  33#include "nouveau_crtc.h"
  34#include "hw.h"
  35#include "tvnv17.h"
  36
  37MODULE_PARM_DESC(tv_norm, "Default TV norm.\n"
  38                 "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n"
  39                 "\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n"
  40                 "\t\tDefault: PAL\n"
  41                 "\t\t*NOTE* Ignored for cards with external TV encoders.");
  42static char *nouveau_tv_norm;
  43module_param_named(tv_norm, nouveau_tv_norm, charp, 0400);
  44
  45static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
  46{
  47        struct drm_device *dev = encoder->dev;
  48        struct nouveau_drm *drm = nouveau_drm(dev);
  49        struct nvkm_gpio *gpio = nvxx_gpio(&drm->client.device);
  50        uint32_t testval, regoffset = nv04_dac_output_offset(encoder);
  51        uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end,
  52                fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c;
  53        uint32_t sample = 0;
  54        int head;
  55
  56#define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20)
  57        testval = RGB_TEST_DATA(0x82, 0xeb, 0x82);
  58        if (drm->vbios.tvdactestval)
  59                testval = drm->vbios.tvdactestval;
  60
  61        dacclk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset);
  62        head = (dacclk & 0x100) >> 8;
  63
  64        /* Save the previous state. */
  65        gpio1 = nvkm_gpio_get(gpio, 0, DCB_GPIO_TVDAC1, 0xff);
  66        gpio0 = nvkm_gpio_get(gpio, 0, DCB_GPIO_TVDAC0, 0xff);
  67        fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL);
  68        fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START);
  69        fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END);
  70        fp_control = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL);
  71        test_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset);
  72        ctv_1c = NVReadRAMDAC(dev, head, 0x680c1c);
  73        ctv_14 = NVReadRAMDAC(dev, head, 0x680c14);
  74        ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c);
  75
  76        /* Prepare the DAC for load detection.  */
  77        nvkm_gpio_set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, true);
  78        nvkm_gpio_set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, true);
  79
  80        NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343);
  81        NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047);
  82        NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, 1183);
  83        NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL,
  84                      NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS |
  85                      NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12 |
  86                      NV_PRAMDAC_FP_TG_CONTROL_READ_PROG |
  87                      NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS |
  88                      NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS);
  89
  90        NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, 0);
  91
  92        NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset,
  93                      (dacclk & ~0xff) | 0x22);
  94        msleep(1);
  95        NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset,
  96                      (dacclk & ~0xff) | 0x21);
  97
  98        NVWriteRAMDAC(dev, head, 0x680c1c, 1 << 20);
  99        NVWriteRAMDAC(dev, head, 0x680c14, 4 << 16);
 100
 101        /* Sample pin 0x4 (usually S-video luma). */
 102        NVWriteRAMDAC(dev, head, 0x680c6c, testval >> 10 & 0x3ff);
 103        msleep(20);
 104        sample |= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset)
 105                & 0x4 << 28;
 106
 107        /* Sample the remaining pins. */
 108        NVWriteRAMDAC(dev, head, 0x680c6c, testval & 0x3ff);
 109        msleep(20);
 110        sample |= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset)
 111                & 0xa << 28;
 112
 113        /* Restore the previous state. */
 114        NVWriteRAMDAC(dev, head, 0x680c1c, ctv_1c);
 115        NVWriteRAMDAC(dev, head, 0x680c14, ctv_14);
 116        NVWriteRAMDAC(dev, head, 0x680c6c, ctv_6c);
 117        NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, dacclk);
 118        NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, test_ctrl);
 119        NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL, fp_control);
 120        NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end);
 121        NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start);
 122        NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal);
 123        nvkm_gpio_set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, gpio1);
 124        nvkm_gpio_set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, gpio0);
 125
 126        return sample;
 127}
 128
 129static bool
 130get_tv_detect_quirks(struct drm_device *dev, uint32_t *pin_mask)
 131{
 132        struct nouveau_drm *drm = nouveau_drm(dev);
 133        struct nvkm_device *device = nvxx_device(&drm->client.device);
 134
 135        if (device->quirk && device->quirk->tv_pin_mask) {
 136                *pin_mask = device->quirk->tv_pin_mask;
 137                return false;
 138        }
 139
 140        return true;
 141}
 142
 143static enum drm_connector_status
 144nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector)
 145{
 146        struct drm_device *dev = encoder->dev;
 147        struct nouveau_drm *drm = nouveau_drm(dev);
 148        struct drm_mode_config *conf = &dev->mode_config;
 149        struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
 150        struct dcb_output *dcb = tv_enc->base.dcb;
 151        bool reliable = get_tv_detect_quirks(dev, &tv_enc->pin_mask);
 152
 153        if (nv04_dac_in_use(encoder))
 154                return connector_status_disconnected;
 155
 156        if (reliable) {
 157                if (drm->client.device.info.chipset == 0x42 ||
 158                    drm->client.device.info.chipset == 0x43)
 159                        tv_enc->pin_mask =
 160                                nv42_tv_sample_load(encoder) >> 28 & 0xe;
 161                else
 162                        tv_enc->pin_mask =
 163                                nv17_dac_sample_load(encoder) >> 28 & 0xe;
 164        }
 165
 166        switch (tv_enc->pin_mask) {
 167        case 0x2:
 168        case 0x4:
 169                tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_Composite;
 170                break;
 171        case 0xc:
 172                tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_SVIDEO;
 173                break;
 174        case 0xe:
 175                if (dcb->tvconf.has_component_output)
 176                        tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_Component;
 177                else
 178                        tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_SCART;
 179                break;
 180        default:
 181                tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_Unknown;
 182                break;
 183        }
 184
 185        drm_object_property_set_value(&connector->base,
 186                                         conf->tv_subconnector_property,
 187                                         tv_enc->subconnector);
 188
 189        if (!reliable) {
 190                return connector_status_unknown;
 191        } else if (tv_enc->subconnector) {
 192                NV_INFO(drm, "Load detected on output %c\n",
 193                        '@' + ffs(dcb->or));
 194                return connector_status_connected;
 195        } else {
 196                return connector_status_disconnected;
 197        }
 198}
 199
 200static int nv17_tv_get_ld_modes(struct drm_encoder *encoder,
 201                                struct drm_connector *connector)
 202{
 203        struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
 204        const struct drm_display_mode *tv_mode;
 205        int n = 0;
 206
 207        for (tv_mode = nv17_tv_modes; tv_mode->hdisplay; tv_mode++) {
 208                struct drm_display_mode *mode;
 209
 210                mode = drm_mode_duplicate(encoder->dev, tv_mode);
 211
 212                mode->clock = tv_norm->tv_enc_mode.vrefresh *
 213                        mode->htotal / 1000 *
 214                        mode->vtotal / 1000;
 215
 216                if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
 217                        mode->clock *= 2;
 218
 219                if (mode->hdisplay == tv_norm->tv_enc_mode.hdisplay &&
 220                    mode->vdisplay == tv_norm->tv_enc_mode.vdisplay)
 221                        mode->type |= DRM_MODE_TYPE_PREFERRED;
 222
 223                drm_mode_probed_add(connector, mode);
 224                n++;
 225        }
 226
 227        return n;
 228}
 229
 230static int nv17_tv_get_hd_modes(struct drm_encoder *encoder,
 231                                struct drm_connector *connector)
 232{
 233        struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
 234        struct drm_display_mode *output_mode = &tv_norm->ctv_enc_mode.mode;
 235        struct drm_display_mode *mode;
 236        const struct {
 237                int hdisplay;
 238                int vdisplay;
 239        } modes[] = {
 240                { 640, 400 },
 241                { 640, 480 },
 242                { 720, 480 },
 243                { 720, 576 },
 244                { 800, 600 },
 245                { 1024, 768 },
 246                { 1280, 720 },
 247                { 1280, 1024 },
 248                { 1920, 1080 }
 249        };
 250        int i, n = 0;
 251
 252        for (i = 0; i < ARRAY_SIZE(modes); i++) {
 253                if (modes[i].hdisplay > output_mode->hdisplay ||
 254                    modes[i].vdisplay > output_mode->vdisplay)
 255                        continue;
 256
 257                if (modes[i].hdisplay == output_mode->hdisplay &&
 258                    modes[i].vdisplay == output_mode->vdisplay) {
 259                        mode = drm_mode_duplicate(encoder->dev, output_mode);
 260                        mode->type |= DRM_MODE_TYPE_PREFERRED;
 261
 262                } else {
 263                        mode = drm_cvt_mode(encoder->dev, modes[i].hdisplay,
 264                                            modes[i].vdisplay, 60, false,
 265                                            (output_mode->flags &
 266                                             DRM_MODE_FLAG_INTERLACE), false);
 267                }
 268
 269                /* CVT modes are sometimes unsuitable... */
 270                if (output_mode->hdisplay <= 720
 271                    || output_mode->hdisplay >= 1920) {
 272                        mode->htotal = output_mode->htotal;
 273                        mode->hsync_start = (mode->hdisplay + (mode->htotal
 274                                             - mode->hdisplay) * 9 / 10) & ~7;
 275                        mode->hsync_end = mode->hsync_start + 8;
 276                }
 277
 278                if (output_mode->vdisplay >= 1024) {
 279                        mode->vtotal = output_mode->vtotal;
 280                        mode->vsync_start = output_mode->vsync_start;
 281                        mode->vsync_end = output_mode->vsync_end;
 282                }
 283
 284                mode->type |= DRM_MODE_TYPE_DRIVER;
 285                drm_mode_probed_add(connector, mode);
 286                n++;
 287        }
 288
 289        return n;
 290}
 291
 292static int nv17_tv_get_modes(struct drm_encoder *encoder,
 293                             struct drm_connector *connector)
 294{
 295        struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
 296
 297        if (tv_norm->kind == CTV_ENC_MODE)
 298                return nv17_tv_get_hd_modes(encoder, connector);
 299        else
 300                return nv17_tv_get_ld_modes(encoder, connector);
 301}
 302
 303static int nv17_tv_mode_valid(struct drm_encoder *encoder,
 304                              struct drm_display_mode *mode)
 305{
 306        struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
 307
 308        if (tv_norm->kind == CTV_ENC_MODE) {
 309                struct drm_display_mode *output_mode =
 310                                                &tv_norm->ctv_enc_mode.mode;
 311
 312                if (mode->clock > 400000)
 313                        return MODE_CLOCK_HIGH;
 314
 315                if (mode->hdisplay > output_mode->hdisplay ||
 316                    mode->vdisplay > output_mode->vdisplay)
 317                        return MODE_BAD;
 318
 319                if ((mode->flags & DRM_MODE_FLAG_INTERLACE) !=
 320                    (output_mode->flags & DRM_MODE_FLAG_INTERLACE))
 321                        return MODE_NO_INTERLACE;
 322
 323                if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
 324                        return MODE_NO_DBLESCAN;
 325
 326        } else {
 327                const int vsync_tolerance = 600;
 328
 329                if (mode->clock > 70000)
 330                        return MODE_CLOCK_HIGH;
 331
 332                if (abs(drm_mode_vrefresh(mode) * 1000 -
 333                        tv_norm->tv_enc_mode.vrefresh) > vsync_tolerance)
 334                        return MODE_VSYNC;
 335
 336                /* The encoder takes care of the actual interlacing */
 337                if (mode->flags & DRM_MODE_FLAG_INTERLACE)
 338                        return MODE_NO_INTERLACE;
 339        }
 340
 341        return MODE_OK;
 342}
 343
 344static bool nv17_tv_mode_fixup(struct drm_encoder *encoder,
 345                               const struct drm_display_mode *mode,
 346                               struct drm_display_mode *adjusted_mode)
 347{
 348        struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
 349
 350        if (nv04_dac_in_use(encoder))
 351                return false;
 352
 353        if (tv_norm->kind == CTV_ENC_MODE)
 354                adjusted_mode->clock = tv_norm->ctv_enc_mode.mode.clock;
 355        else
 356                adjusted_mode->clock = 90000;
 357
 358        return true;
 359}
 360
 361static void  nv17_tv_dpms(struct drm_encoder *encoder, int mode)
 362{
 363        struct drm_device *dev = encoder->dev;
 364        struct nouveau_drm *drm = nouveau_drm(dev);
 365        struct nvkm_gpio *gpio = nvxx_gpio(&drm->client.device);
 366        struct nv17_tv_state *regs = &to_tv_enc(encoder)->state;
 367        struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
 368
 369        if (nouveau_encoder(encoder)->last_dpms == mode)
 370                return;
 371        nouveau_encoder(encoder)->last_dpms = mode;
 372
 373        NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n",
 374                 mode, nouveau_encoder(encoder)->dcb->index);
 375
 376        regs->ptv_200 &= ~1;
 377
 378        if (tv_norm->kind == CTV_ENC_MODE) {
 379                nv04_dfp_update_fp_control(encoder, mode);
 380
 381        } else {
 382                nv04_dfp_update_fp_control(encoder, DRM_MODE_DPMS_OFF);
 383
 384                if (mode == DRM_MODE_DPMS_ON)
 385                        regs->ptv_200 |= 1;
 386        }
 387
 388        nv_load_ptv(dev, regs, 200);
 389
 390        nvkm_gpio_set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, mode == DRM_MODE_DPMS_ON);
 391        nvkm_gpio_set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, mode == DRM_MODE_DPMS_ON);
 392
 393        nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
 394}
 395
 396static void nv17_tv_prepare(struct drm_encoder *encoder)
 397{
 398        struct drm_device *dev = encoder->dev;
 399        struct nouveau_drm *drm = nouveau_drm(dev);
 400        const struct drm_encoder_helper_funcs *helper = encoder->helper_private;
 401        struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
 402        int head = nouveau_crtc(encoder->crtc)->index;
 403        uint8_t *cr_lcd = &nv04_display(dev)->mode_reg.crtc_reg[head].CRTC[
 404                                                        NV_CIO_CRE_LCD__INDEX];
 405        uint32_t dacclk_off = NV_PRAMDAC_DACCLK +
 406                                        nv04_dac_output_offset(encoder);
 407        uint32_t dacclk;
 408
 409        helper->dpms(encoder, DRM_MODE_DPMS_OFF);
 410
 411        nv04_dfp_disable(dev, head);
 412
 413        /* Unbind any FP encoders from this head if we need the FP
 414         * stuff enabled. */
 415        if (tv_norm->kind == CTV_ENC_MODE) {
 416                struct drm_encoder *enc;
 417
 418                list_for_each_entry(enc, &dev->mode_config.encoder_list, head) {
 419                        struct dcb_output *dcb = nouveau_encoder(enc)->dcb;
 420
 421                        if ((dcb->type == DCB_OUTPUT_TMDS ||
 422                             dcb->type == DCB_OUTPUT_LVDS) &&
 423                             !enc->crtc &&
 424                             nv04_dfp_get_bound_head(dev, dcb) == head) {
 425                                nv04_dfp_bind_head(dev, dcb, head ^ 1,
 426                                                drm->vbios.fp.dual_link);
 427                        }
 428                }
 429
 430        }
 431
 432        if (tv_norm->kind == CTV_ENC_MODE)
 433                *cr_lcd |= 0x1 | (head ? 0x0 : 0x8);
 434
 435        /* Set the DACCLK register */
 436        dacclk = (NVReadRAMDAC(dev, 0, dacclk_off) & ~0x30) | 0x1;
 437
 438        if (drm->client.device.info.family == NV_DEVICE_INFO_V0_CURIE)
 439                dacclk |= 0x1a << 16;
 440
 441        if (tv_norm->kind == CTV_ENC_MODE) {
 442                dacclk |=  0x20;
 443
 444                if (head)
 445                        dacclk |= 0x100;
 446                else
 447                        dacclk &= ~0x100;
 448
 449        } else {
 450                dacclk |= 0x10;
 451
 452        }
 453
 454        NVWriteRAMDAC(dev, 0, dacclk_off, dacclk);
 455}
 456
 457static void nv17_tv_mode_set(struct drm_encoder *encoder,
 458                             struct drm_display_mode *drm_mode,
 459                             struct drm_display_mode *adjusted_mode)
 460{
 461        struct drm_device *dev = encoder->dev;
 462        struct nouveau_drm *drm = nouveau_drm(dev);
 463        int head = nouveau_crtc(encoder->crtc)->index;
 464        struct nv04_crtc_reg *regs = &nv04_display(dev)->mode_reg.crtc_reg[head];
 465        struct nv17_tv_state *tv_regs = &to_tv_enc(encoder)->state;
 466        struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
 467        int i;
 468
 469        regs->CRTC[NV_CIO_CRE_53] = 0x40; /* FP_HTIMING */
 470        regs->CRTC[NV_CIO_CRE_54] = 0; /* FP_VTIMING */
 471        regs->ramdac_630 = 0x2; /* turn off green mode (tv test pattern?) */
 472        regs->tv_setup = 1;
 473        regs->ramdac_8c0 = 0x0;
 474
 475        if (tv_norm->kind == TV_ENC_MODE) {
 476                tv_regs->ptv_200 = 0x13111100;
 477                if (head)
 478                        tv_regs->ptv_200 |= 0x10;
 479
 480                tv_regs->ptv_20c = 0x808010;
 481                tv_regs->ptv_304 = 0x2d00000;
 482                tv_regs->ptv_600 = 0x0;
 483                tv_regs->ptv_60c = 0x0;
 484                tv_regs->ptv_610 = 0x1e00000;
 485
 486                if (tv_norm->tv_enc_mode.vdisplay == 576) {
 487                        tv_regs->ptv_508 = 0x1200000;
 488                        tv_regs->ptv_614 = 0x33;
 489
 490                } else if (tv_norm->tv_enc_mode.vdisplay == 480) {
 491                        tv_regs->ptv_508 = 0xf00000;
 492                        tv_regs->ptv_614 = 0x13;
 493                }
 494
 495                if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_RANKINE) {
 496                        tv_regs->ptv_500 = 0xe8e0;
 497                        tv_regs->ptv_504 = 0x1710;
 498                        tv_regs->ptv_604 = 0x0;
 499                        tv_regs->ptv_608 = 0x0;
 500                } else {
 501                        if (tv_norm->tv_enc_mode.vdisplay == 576) {
 502                                tv_regs->ptv_604 = 0x20;
 503                                tv_regs->ptv_608 = 0x10;
 504                                tv_regs->ptv_500 = 0x19710;
 505                                tv_regs->ptv_504 = 0x68f0;
 506
 507                        } else if (tv_norm->tv_enc_mode.vdisplay == 480) {
 508                                tv_regs->ptv_604 = 0x10;
 509                                tv_regs->ptv_608 = 0x20;
 510                                tv_regs->ptv_500 = 0x4b90;
 511                                tv_regs->ptv_504 = 0x1b480;
 512                        }
 513                }
 514
 515                for (i = 0; i < 0x40; i++)
 516                        tv_regs->tv_enc[i] = tv_norm->tv_enc_mode.tv_enc[i];
 517
 518        } else {
 519                struct drm_display_mode *output_mode =
 520                                                &tv_norm->ctv_enc_mode.mode;
 521
 522                /* The registers in PRAMDAC+0xc00 control some timings and CSC
 523                 * parameters for the CTV encoder (It's only used for "HD" TV
 524                 * modes, I don't think I have enough working to guess what
 525                 * they exactly mean...), it's probably connected at the
 526                 * output of the FP encoder, but it also needs the analog
 527                 * encoder in its OR enabled and routed to the head it's
 528                 * using. It's enabled with the DACCLK register, bits [5:4].
 529                 */
 530                for (i = 0; i < 38; i++)
 531                        regs->ctv_regs[i] = tv_norm->ctv_enc_mode.ctv_regs[i];
 532
 533                regs->fp_horiz_regs[FP_DISPLAY_END] = output_mode->hdisplay - 1;
 534                regs->fp_horiz_regs[FP_TOTAL] = output_mode->htotal - 1;
 535                regs->fp_horiz_regs[FP_SYNC_START] =
 536                                                output_mode->hsync_start - 1;
 537                regs->fp_horiz_regs[FP_SYNC_END] = output_mode->hsync_end - 1;
 538                regs->fp_horiz_regs[FP_CRTC] = output_mode->hdisplay +
 539                        max((output_mode->hdisplay-600)/40 - 1, 1);
 540
 541                regs->fp_vert_regs[FP_DISPLAY_END] = output_mode->vdisplay - 1;
 542                regs->fp_vert_regs[FP_TOTAL] = output_mode->vtotal - 1;
 543                regs->fp_vert_regs[FP_SYNC_START] =
 544                                                output_mode->vsync_start - 1;
 545                regs->fp_vert_regs[FP_SYNC_END] = output_mode->vsync_end - 1;
 546                regs->fp_vert_regs[FP_CRTC] = output_mode->vdisplay - 1;
 547
 548                regs->fp_control = NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS |
 549                        NV_PRAMDAC_FP_TG_CONTROL_READ_PROG |
 550                        NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12;
 551
 552                if (output_mode->flags & DRM_MODE_FLAG_PVSYNC)
 553                        regs->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS;
 554                if (output_mode->flags & DRM_MODE_FLAG_PHSYNC)
 555                        regs->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS;
 556
 557                regs->fp_debug_0 = NV_PRAMDAC_FP_DEBUG_0_YWEIGHT_ROUND |
 558                        NV_PRAMDAC_FP_DEBUG_0_XWEIGHT_ROUND |
 559                        NV_PRAMDAC_FP_DEBUG_0_YINTERP_BILINEAR |
 560                        NV_PRAMDAC_FP_DEBUG_0_XINTERP_BILINEAR |
 561                        NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED |
 562                        NV_PRAMDAC_FP_DEBUG_0_YSCALE_ENABLE |
 563                        NV_PRAMDAC_FP_DEBUG_0_XSCALE_ENABLE;
 564
 565                regs->fp_debug_2 = 0;
 566
 567                regs->fp_margin_color = 0x801080;
 568
 569        }
 570}
 571
 572static void nv17_tv_commit(struct drm_encoder *encoder)
 573{
 574        struct drm_device *dev = encoder->dev;
 575        struct nouveau_drm *drm = nouveau_drm(dev);
 576        struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
 577        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 578        const struct drm_encoder_helper_funcs *helper = encoder->helper_private;
 579
 580        if (get_tv_norm(encoder)->kind == TV_ENC_MODE) {
 581                nv17_tv_update_rescaler(encoder);
 582                nv17_tv_update_properties(encoder);
 583        } else {
 584                nv17_ctv_update_rescaler(encoder);
 585        }
 586
 587        nv17_tv_state_load(dev, &to_tv_enc(encoder)->state);
 588
 589        /* This could use refinement for flatpanels, but it should work */
 590        if (drm->client.device.info.chipset < 0x44)
 591                NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL +
 592                                        nv04_dac_output_offset(encoder),
 593                                        0xf0000000);
 594        else
 595                NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL +
 596                                        nv04_dac_output_offset(encoder),
 597                                        0x00100000);
 598
 599        helper->dpms(encoder, DRM_MODE_DPMS_ON);
 600
 601        NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
 602                nv04_encoder_get_connector(nv_encoder)->base.name,
 603                nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 604}
 605
 606static void nv17_tv_save(struct drm_encoder *encoder)
 607{
 608        struct drm_device *dev = encoder->dev;
 609        struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
 610
 611        nouveau_encoder(encoder)->restore.output =
 612                                        NVReadRAMDAC(dev, 0,
 613                                        NV_PRAMDAC_DACCLK +
 614                                        nv04_dac_output_offset(encoder));
 615
 616        nv17_tv_state_save(dev, &tv_enc->saved_state);
 617
 618        tv_enc->state.ptv_200 = tv_enc->saved_state.ptv_200;
 619}
 620
 621static void nv17_tv_restore(struct drm_encoder *encoder)
 622{
 623        struct drm_device *dev = encoder->dev;
 624
 625        NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK +
 626                                nv04_dac_output_offset(encoder),
 627                                nouveau_encoder(encoder)->restore.output);
 628
 629        nv17_tv_state_load(dev, &to_tv_enc(encoder)->saved_state);
 630
 631        nouveau_encoder(encoder)->last_dpms = NV_DPMS_CLEARED;
 632}
 633
 634static int nv17_tv_create_resources(struct drm_encoder *encoder,
 635                                    struct drm_connector *connector)
 636{
 637        struct drm_device *dev = encoder->dev;
 638        struct nouveau_drm *drm = nouveau_drm(dev);
 639        struct drm_mode_config *conf = &dev->mode_config;
 640        struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
 641        struct dcb_output *dcb = nouveau_encoder(encoder)->dcb;
 642        int num_tv_norms = dcb->tvconf.has_component_output ? NUM_TV_NORMS :
 643                                                        NUM_LD_TV_NORMS;
 644        int i;
 645
 646        if (nouveau_tv_norm) {
 647                i = match_string(nv17_tv_norm_names, num_tv_norms,
 648                                 nouveau_tv_norm);
 649                if (i < 0)
 650                        NV_WARN(drm, "Invalid TV norm setting \"%s\"\n",
 651                                nouveau_tv_norm);
 652                else
 653                        tv_enc->tv_norm = i;
 654        }
 655
 656        drm_mode_create_tv_properties(dev, num_tv_norms, nv17_tv_norm_names);
 657
 658        drm_object_attach_property(&connector->base,
 659                                        conf->tv_select_subconnector_property,
 660                                        tv_enc->select_subconnector);
 661        drm_object_attach_property(&connector->base,
 662                                        conf->tv_subconnector_property,
 663                                        tv_enc->subconnector);
 664        drm_object_attach_property(&connector->base,
 665                                        conf->tv_mode_property,
 666                                        tv_enc->tv_norm);
 667        drm_object_attach_property(&connector->base,
 668                                        conf->tv_flicker_reduction_property,
 669                                        tv_enc->flicker);
 670        drm_object_attach_property(&connector->base,
 671                                        conf->tv_saturation_property,
 672                                        tv_enc->saturation);
 673        drm_object_attach_property(&connector->base,
 674                                        conf->tv_hue_property,
 675                                        tv_enc->hue);
 676        drm_object_attach_property(&connector->base,
 677                                        conf->tv_overscan_property,
 678                                        tv_enc->overscan);
 679
 680        return 0;
 681}
 682
 683static int nv17_tv_set_property(struct drm_encoder *encoder,
 684                                struct drm_connector *connector,
 685                                struct drm_property *property,
 686                                uint64_t val)
 687{
 688        struct drm_mode_config *conf = &encoder->dev->mode_config;
 689        struct drm_crtc *crtc = encoder->crtc;
 690        struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
 691        struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
 692        bool modes_changed = false;
 693
 694        if (property == conf->tv_overscan_property) {
 695                tv_enc->overscan = val;
 696                if (encoder->crtc) {
 697                        if (tv_norm->kind == CTV_ENC_MODE)
 698                                nv17_ctv_update_rescaler(encoder);
 699                        else
 700                                nv17_tv_update_rescaler(encoder);
 701                }
 702
 703        } else if (property == conf->tv_saturation_property) {
 704                if (tv_norm->kind != TV_ENC_MODE)
 705                        return -EINVAL;
 706
 707                tv_enc->saturation = val;
 708                nv17_tv_update_properties(encoder);
 709
 710        } else if (property == conf->tv_hue_property) {
 711                if (tv_norm->kind != TV_ENC_MODE)
 712                        return -EINVAL;
 713
 714                tv_enc->hue = val;
 715                nv17_tv_update_properties(encoder);
 716
 717        } else if (property == conf->tv_flicker_reduction_property) {
 718                if (tv_norm->kind != TV_ENC_MODE)
 719                        return -EINVAL;
 720
 721                tv_enc->flicker = val;
 722                if (encoder->crtc)
 723                        nv17_tv_update_rescaler(encoder);
 724
 725        } else if (property == conf->tv_mode_property) {
 726                if (connector->dpms != DRM_MODE_DPMS_OFF)
 727                        return -EINVAL;
 728
 729                tv_enc->tv_norm = val;
 730
 731                modes_changed = true;
 732
 733        } else if (property == conf->tv_select_subconnector_property) {
 734                if (tv_norm->kind != TV_ENC_MODE)
 735                        return -EINVAL;
 736
 737                tv_enc->select_subconnector = val;
 738                nv17_tv_update_properties(encoder);
 739
 740        } else {
 741                return -EINVAL;
 742        }
 743
 744        if (modes_changed) {
 745                drm_helper_probe_single_connector_modes(connector, 0, 0);
 746
 747                /* Disable the crtc to ensure a full modeset is
 748                 * performed whenever it's turned on again. */
 749                if (crtc)
 750                        drm_crtc_helper_set_mode(crtc, &crtc->mode,
 751                                                 crtc->x, crtc->y,
 752                                                 crtc->primary->fb);
 753        }
 754
 755        return 0;
 756}
 757
 758static void nv17_tv_destroy(struct drm_encoder *encoder)
 759{
 760        struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
 761
 762        drm_encoder_cleanup(encoder);
 763        kfree(tv_enc);
 764}
 765
 766static const struct drm_encoder_helper_funcs nv17_tv_helper_funcs = {
 767        .dpms = nv17_tv_dpms,
 768        .mode_fixup = nv17_tv_mode_fixup,
 769        .prepare = nv17_tv_prepare,
 770        .commit = nv17_tv_commit,
 771        .mode_set = nv17_tv_mode_set,
 772        .detect = nv17_tv_detect,
 773};
 774
 775static const struct drm_encoder_slave_funcs nv17_tv_slave_funcs = {
 776        .get_modes = nv17_tv_get_modes,
 777        .mode_valid = nv17_tv_mode_valid,
 778        .create_resources = nv17_tv_create_resources,
 779        .set_property = nv17_tv_set_property,
 780};
 781
 782static const struct drm_encoder_funcs nv17_tv_funcs = {
 783        .destroy = nv17_tv_destroy,
 784};
 785
 786int
 787nv17_tv_create(struct drm_connector *connector, struct dcb_output *entry)
 788{
 789        struct drm_device *dev = connector->dev;
 790        struct drm_encoder *encoder;
 791        struct nv17_tv_encoder *tv_enc = NULL;
 792
 793        tv_enc = kzalloc(sizeof(*tv_enc), GFP_KERNEL);
 794        if (!tv_enc)
 795                return -ENOMEM;
 796
 797        tv_enc->overscan = 50;
 798        tv_enc->flicker = 50;
 799        tv_enc->saturation = 50;
 800        tv_enc->hue = 0;
 801        tv_enc->tv_norm = TV_NORM_PAL;
 802        tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_Unknown;
 803        tv_enc->select_subconnector = DRM_MODE_SUBCONNECTOR_Automatic;
 804        tv_enc->pin_mask = 0;
 805
 806        encoder = to_drm_encoder(&tv_enc->base);
 807
 808        tv_enc->base.dcb = entry;
 809        tv_enc->base.or = ffs(entry->or) - 1;
 810
 811        drm_encoder_init(dev, encoder, &nv17_tv_funcs, DRM_MODE_ENCODER_TVDAC,
 812                         NULL);
 813        drm_encoder_helper_add(encoder, &nv17_tv_helper_funcs);
 814        to_encoder_slave(encoder)->slave_funcs = &nv17_tv_slave_funcs;
 815
 816        tv_enc->base.enc_save = nv17_tv_save;
 817        tv_enc->base.enc_restore = nv17_tv_restore;
 818
 819        encoder->possible_crtcs = entry->heads;
 820        encoder->possible_clones = 0;
 821
 822        nv17_tv_create_resources(encoder, connector);
 823        drm_connector_attach_encoder(connector, encoder);
 824        return 0;
 825}
 826