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