linux/drivers/gpu/drm/i915/intel_tv.c
<<
>>
Prefs
   1/*
   2 * Copyright © 2006-2008 Intel Corporation
   3 *   Jesse Barnes <jesse.barnes@intel.com>
   4 *
   5 * Permission is hereby granted, free of charge, to any person obtaining a
   6 * copy of this software and associated documentation files (the "Software"),
   7 * to deal in the Software without restriction, including without limitation
   8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   9 * and/or sell copies of the Software, and to permit persons to whom the
  10 * Software is furnished to do so, subject to the following conditions:
  11 *
  12 * The above copyright notice and this permission notice (including the next
  13 * paragraph) shall be included in all copies or substantial portions of the
  14 * Software.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22 * DEALINGS IN THE SOFTWARE.
  23 *
  24 * Authors:
  25 *    Eric Anholt <eric@anholt.net>
  26 *
  27 */
  28
  29/** @file
  30 * Integrated TV-out support for the 915GM and 945GM.
  31 */
  32
  33#include <drm/drmP.h>
  34#include <drm/drm_atomic_helper.h>
  35#include <drm/drm_crtc.h>
  36#include <drm/drm_edid.h>
  37#include "intel_drv.h"
  38#include <drm/i915_drm.h>
  39#include "i915_drv.h"
  40
  41enum tv_margin {
  42        TV_MARGIN_LEFT, TV_MARGIN_TOP,
  43        TV_MARGIN_RIGHT, TV_MARGIN_BOTTOM
  44};
  45
  46/** Private structure for the integrated TV support */
  47struct intel_tv {
  48        struct intel_encoder base;
  49
  50        int type;
  51        const char *tv_format;
  52        int margin[4];
  53        u32 save_TV_H_CTL_1;
  54        u32 save_TV_H_CTL_2;
  55        u32 save_TV_H_CTL_3;
  56        u32 save_TV_V_CTL_1;
  57        u32 save_TV_V_CTL_2;
  58        u32 save_TV_V_CTL_3;
  59        u32 save_TV_V_CTL_4;
  60        u32 save_TV_V_CTL_5;
  61        u32 save_TV_V_CTL_6;
  62        u32 save_TV_V_CTL_7;
  63        u32 save_TV_SC_CTL_1, save_TV_SC_CTL_2, save_TV_SC_CTL_3;
  64
  65        u32 save_TV_CSC_Y;
  66        u32 save_TV_CSC_Y2;
  67        u32 save_TV_CSC_U;
  68        u32 save_TV_CSC_U2;
  69        u32 save_TV_CSC_V;
  70        u32 save_TV_CSC_V2;
  71        u32 save_TV_CLR_KNOBS;
  72        u32 save_TV_CLR_LEVEL;
  73        u32 save_TV_WIN_POS;
  74        u32 save_TV_WIN_SIZE;
  75        u32 save_TV_FILTER_CTL_1;
  76        u32 save_TV_FILTER_CTL_2;
  77        u32 save_TV_FILTER_CTL_3;
  78
  79        u32 save_TV_H_LUMA[60];
  80        u32 save_TV_H_CHROMA[60];
  81        u32 save_TV_V_LUMA[43];
  82        u32 save_TV_V_CHROMA[43];
  83
  84        u32 save_TV_DAC;
  85        u32 save_TV_CTL;
  86};
  87
  88struct video_levels {
  89        u16 blank, black;
  90        u8 burst;
  91};
  92
  93struct color_conversion {
  94        u16 ry, gy, by, ay;
  95        u16 ru, gu, bu, au;
  96        u16 rv, gv, bv, av;
  97};
  98
  99static const u32 filter_table[] = {
 100        0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
 101        0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
 102        0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,
 103        0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,
 104        0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,
 105        0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,
 106        0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,
 107        0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,
 108        0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,
 109        0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,
 110        0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,
 111        0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,
 112        0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,
 113        0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,
 114        0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,
 115        0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
 116        0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
 117        0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,
 118        0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,
 119        0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,
 120        0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,
 121        0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,
 122        0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,
 123        0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,
 124        0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,
 125        0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,
 126        0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,
 127        0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,
 128        0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,
 129        0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,
 130        0x36403000, 0x2D002CC0, 0x30003640, 0x2D0036C0,
 131        0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,
 132        0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,
 133        0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,
 134        0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,
 135        0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,
 136        0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,
 137        0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,
 138        0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,
 139        0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,
 140        0x28003100, 0x28002F00, 0x00003100, 0x36403000,
 141        0x2D002CC0, 0x30003640, 0x2D0036C0,
 142        0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,
 143        0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,
 144        0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,
 145        0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,
 146        0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,
 147        0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,
 148        0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,
 149        0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,
 150        0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,
 151        0x28003100, 0x28002F00, 0x00003100,
 152};
 153
 154/*
 155 * Color conversion values have 3 separate fixed point formats:
 156 *
 157 * 10 bit fields (ay, au)
 158 *   1.9 fixed point (b.bbbbbbbbb)
 159 * 11 bit fields (ry, by, ru, gu, gv)
 160 *   exp.mantissa (ee.mmmmmmmmm)
 161 *   ee = 00 = 10^-1 (0.mmmmmmmmm)
 162 *   ee = 01 = 10^-2 (0.0mmmmmmmmm)
 163 *   ee = 10 = 10^-3 (0.00mmmmmmmmm)
 164 *   ee = 11 = 10^-4 (0.000mmmmmmmmm)
 165 * 12 bit fields (gy, rv, bu)
 166 *   exp.mantissa (eee.mmmmmmmmm)
 167 *   eee = 000 = 10^-1 (0.mmmmmmmmm)
 168 *   eee = 001 = 10^-2 (0.0mmmmmmmmm)
 169 *   eee = 010 = 10^-3 (0.00mmmmmmmmm)
 170 *   eee = 011 = 10^-4 (0.000mmmmmmmmm)
 171 *   eee = 100 = reserved
 172 *   eee = 101 = reserved
 173 *   eee = 110 = reserved
 174 *   eee = 111 = 10^0 (m.mmmmmmmm) (only usable for 1.0 representation)
 175 *
 176 * Saturation and contrast are 8 bits, with their own representation:
 177 * 8 bit field (saturation, contrast)
 178 *   exp.mantissa (ee.mmmmmm)
 179 *   ee = 00 = 10^-1 (0.mmmmmm)
 180 *   ee = 01 = 10^0 (m.mmmmm)
 181 *   ee = 10 = 10^1 (mm.mmmm)
 182 *   ee = 11 = 10^2 (mmm.mmm)
 183 *
 184 * Simple conversion function:
 185 *
 186 * static u32
 187 * float_to_csc_11(float f)
 188 * {
 189 *     u32 exp;
 190 *     u32 mant;
 191 *     u32 ret;
 192 *
 193 *     if (f < 0)
 194 *         f = -f;
 195 *
 196 *     if (f >= 1) {
 197 *         exp = 0x7;
 198 *         mant = 1 << 8;
 199 *     } else {
 200 *         for (exp = 0; exp < 3 && f < 0.5; exp++)
 201 *         f *= 2.0;
 202 *         mant = (f * (1 << 9) + 0.5);
 203 *         if (mant >= (1 << 9))
 204 *             mant = (1 << 9) - 1;
 205 *     }
 206 *     ret = (exp << 9) | mant;
 207 *     return ret;
 208 * }
 209 */
 210
 211/*
 212 * Behold, magic numbers!  If we plant them they might grow a big
 213 * s-video cable to the sky... or something.
 214 *
 215 * Pre-converted to appropriate hex value.
 216 */
 217
 218/*
 219 * PAL & NTSC values for composite & s-video connections
 220 */
 221static const struct color_conversion ntsc_m_csc_composite = {
 222        .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104,
 223        .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200,
 224        .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200,
 225};
 226
 227static const struct video_levels ntsc_m_levels_composite = {
 228        .blank = 225, .black = 267, .burst = 113,
 229};
 230
 231static const struct color_conversion ntsc_m_csc_svideo = {
 232        .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133,
 233        .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200,
 234        .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200,
 235};
 236
 237static const struct video_levels ntsc_m_levels_svideo = {
 238        .blank = 266, .black = 316, .burst = 133,
 239};
 240
 241static const struct color_conversion ntsc_j_csc_composite = {
 242        .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0119,
 243        .ru = 0x074c, .gu = 0x0546, .bu = 0x05ec, .au = 0x0200,
 244        .rv = 0x035a, .gv = 0x0322, .bv = 0x06e1, .av = 0x0200,
 245};
 246
 247static const struct video_levels ntsc_j_levels_composite = {
 248        .blank = 225, .black = 225, .burst = 113,
 249};
 250
 251static const struct color_conversion ntsc_j_csc_svideo = {
 252        .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x014c,
 253        .ru = 0x0788, .gu = 0x0581, .bu = 0x0322, .au = 0x0200,
 254        .rv = 0x0399, .gv = 0x0356, .bv = 0x070a, .av = 0x0200,
 255};
 256
 257static const struct video_levels ntsc_j_levels_svideo = {
 258        .blank = 266, .black = 266, .burst = 133,
 259};
 260
 261static const struct color_conversion pal_csc_composite = {
 262        .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0113,
 263        .ru = 0x0745, .gu = 0x053f, .bu = 0x05e1, .au = 0x0200,
 264        .rv = 0x0353, .gv = 0x031c, .bv = 0x06dc, .av = 0x0200,
 265};
 266
 267static const struct video_levels pal_levels_composite = {
 268        .blank = 237, .black = 237, .burst = 118,
 269};
 270
 271static const struct color_conversion pal_csc_svideo = {
 272        .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0145,
 273        .ru = 0x0780, .gu = 0x0579, .bu = 0x031c, .au = 0x0200,
 274        .rv = 0x0390, .gv = 0x034f, .bv = 0x0705, .av = 0x0200,
 275};
 276
 277static const struct video_levels pal_levels_svideo = {
 278        .blank = 280, .black = 280, .burst = 139,
 279};
 280
 281static const struct color_conversion pal_m_csc_composite = {
 282        .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104,
 283        .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200,
 284        .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200,
 285};
 286
 287static const struct video_levels pal_m_levels_composite = {
 288        .blank = 225, .black = 267, .burst = 113,
 289};
 290
 291static const struct color_conversion pal_m_csc_svideo = {
 292        .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133,
 293        .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200,
 294        .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200,
 295};
 296
 297static const struct video_levels pal_m_levels_svideo = {
 298        .blank = 266, .black = 316, .burst = 133,
 299};
 300
 301static const struct color_conversion pal_n_csc_composite = {
 302        .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104,
 303        .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200,
 304        .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200,
 305};
 306
 307static const struct video_levels pal_n_levels_composite = {
 308        .blank = 225, .black = 267, .burst = 118,
 309};
 310
 311static const struct color_conversion pal_n_csc_svideo = {
 312        .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133,
 313        .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200,
 314        .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200,
 315};
 316
 317static const struct video_levels pal_n_levels_svideo = {
 318        .blank = 266, .black = 316, .burst = 139,
 319};
 320
 321/*
 322 * Component connections
 323 */
 324static const struct color_conversion sdtv_csc_yprpb = {
 325        .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0145,
 326        .ru = 0x0559, .gu = 0x0353, .bu = 0x0100, .au = 0x0200,
 327        .rv = 0x0100, .gv = 0x03ad, .bv = 0x074d, .av = 0x0200,
 328};
 329
 330static const struct color_conversion hdtv_csc_yprpb = {
 331        .ry = 0x05b3, .gy = 0x016e, .by = 0x0728, .ay = 0x0145,
 332        .ru = 0x07d5, .gu = 0x038b, .bu = 0x0100, .au = 0x0200,
 333        .rv = 0x0100, .gv = 0x03d1, .bv = 0x06bc, .av = 0x0200,
 334};
 335
 336static const struct video_levels component_levels = {
 337        .blank = 279, .black = 279, .burst = 0,
 338};
 339
 340
 341struct tv_mode {
 342        const char *name;
 343
 344        u32 clock;
 345        u16 refresh; /* in millihertz (for precision) */
 346        u32 oversample;
 347        u8 hsync_end;
 348        u16 hblank_start, hblank_end, htotal;
 349        bool progressive : 1, trilevel_sync : 1, component_only : 1;
 350        u8 vsync_start_f1, vsync_start_f2, vsync_len;
 351        bool veq_ena : 1;
 352        u8 veq_start_f1, veq_start_f2, veq_len;
 353        u8 vi_end_f1, vi_end_f2;
 354        u16 nbr_end;
 355        bool burst_ena : 1;
 356        u8 hburst_start, hburst_len;
 357        u8 vburst_start_f1;
 358        u16 vburst_end_f1;
 359        u8 vburst_start_f2;
 360        u16 vburst_end_f2;
 361        u8 vburst_start_f3;
 362        u16 vburst_end_f3;
 363        u8 vburst_start_f4;
 364        u16 vburst_end_f4;
 365        /*
 366         * subcarrier programming
 367         */
 368        u16 dda2_size, dda3_size;
 369        u8 dda1_inc;
 370        u16 dda2_inc, dda3_inc;
 371        u32 sc_reset;
 372        bool pal_burst : 1;
 373        /*
 374         * blank/black levels
 375         */
 376        const struct video_levels *composite_levels, *svideo_levels;
 377        const struct color_conversion *composite_color, *svideo_color;
 378        const u32 *filter_table;
 379        u16 max_srcw;
 380};
 381
 382
 383/*
 384 * Sub carrier DDA
 385 *
 386 *  I think this works as follows:
 387 *
 388 *  subcarrier freq = pixel_clock * (dda1_inc + dda2_inc / dda2_size) / 4096
 389 *
 390 * Presumably, when dda3 is added in, it gets to adjust the dda2_inc value
 391 *
 392 * So,
 393 *  dda1_ideal = subcarrier/pixel * 4096
 394 *  dda1_inc = floor (dda1_ideal)
 395 *  dda2 = dda1_ideal - dda1_inc
 396 *
 397 *  then pick a ratio for dda2 that gives the closest approximation. If
 398 *  you can't get close enough, you can play with dda3 as well. This
 399 *  seems likely to happen when dda2 is small as the jumps would be larger
 400 *
 401 * To invert this,
 402 *
 403 *  pixel_clock = subcarrier * 4096 / (dda1_inc + dda2_inc / dda2_size)
 404 *
 405 * The constants below were all computed using a 107.520MHz clock
 406 */
 407
 408/**
 409 * Register programming values for TV modes.
 410 *
 411 * These values account for -1s required.
 412 */
 413
 414static const struct tv_mode tv_modes[] = {
 415        {
 416                .name           = "NTSC-M",
 417                .clock          = 108000,
 418                .refresh        = 59940,
 419                .oversample     = TV_OVERSAMPLE_8X,
 420                .component_only = 0,
 421                /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
 422
 423                .hsync_end      = 64,               .hblank_end         = 124,
 424                .hblank_start   = 836,              .htotal             = 857,
 425
 426                .progressive    = false,            .trilevel_sync = false,
 427
 428                .vsync_start_f1 = 6,                .vsync_start_f2     = 7,
 429                .vsync_len      = 6,
 430
 431                .veq_ena        = true,             .veq_start_f1       = 0,
 432                .veq_start_f2   = 1,                .veq_len            = 18,
 433
 434                .vi_end_f1      = 20,               .vi_end_f2          = 21,
 435                .nbr_end        = 240,
 436
 437                .burst_ena      = true,
 438                .hburst_start   = 72,               .hburst_len         = 34,
 439                .vburst_start_f1 = 9,               .vburst_end_f1      = 240,
 440                .vburst_start_f2 = 10,              .vburst_end_f2      = 240,
 441                .vburst_start_f3 = 9,               .vburst_end_f3      = 240,
 442                .vburst_start_f4 = 10,              .vburst_end_f4      = 240,
 443
 444                /* desired 3.5800000 actual 3.5800000 clock 107.52 */
 445                .dda1_inc       =    135,
 446                .dda2_inc       =  20800,           .dda2_size          =  27456,
 447                .dda3_inc       =      0,           .dda3_size          =      0,
 448                .sc_reset       = TV_SC_RESET_EVERY_4,
 449                .pal_burst      = false,
 450
 451                .composite_levels = &ntsc_m_levels_composite,
 452                .composite_color = &ntsc_m_csc_composite,
 453                .svideo_levels  = &ntsc_m_levels_svideo,
 454                .svideo_color = &ntsc_m_csc_svideo,
 455
 456                .filter_table = filter_table,
 457        },
 458        {
 459                .name           = "NTSC-443",
 460                .clock          = 108000,
 461                .refresh        = 59940,
 462                .oversample     = TV_OVERSAMPLE_8X,
 463                .component_only = 0,
 464                /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 4.43MHz */
 465                .hsync_end      = 64,               .hblank_end         = 124,
 466                .hblank_start   = 836,              .htotal             = 857,
 467
 468                .progressive    = false,            .trilevel_sync = false,
 469
 470                .vsync_start_f1 = 6,                .vsync_start_f2     = 7,
 471                .vsync_len      = 6,
 472
 473                .veq_ena        = true,             .veq_start_f1       = 0,
 474                .veq_start_f2   = 1,                .veq_len            = 18,
 475
 476                .vi_end_f1      = 20,               .vi_end_f2          = 21,
 477                .nbr_end        = 240,
 478
 479                .burst_ena      = true,
 480                .hburst_start   = 72,               .hburst_len         = 34,
 481                .vburst_start_f1 = 9,               .vburst_end_f1      = 240,
 482                .vburst_start_f2 = 10,              .vburst_end_f2      = 240,
 483                .vburst_start_f3 = 9,               .vburst_end_f3      = 240,
 484                .vburst_start_f4 = 10,              .vburst_end_f4      = 240,
 485
 486                /* desired 4.4336180 actual 4.4336180 clock 107.52 */
 487                .dda1_inc       =    168,
 488                .dda2_inc       =   4093,       .dda2_size      =  27456,
 489                .dda3_inc       =    310,       .dda3_size      =    525,
 490                .sc_reset   = TV_SC_RESET_NEVER,
 491                .pal_burst  = false,
 492
 493                .composite_levels = &ntsc_m_levels_composite,
 494                .composite_color = &ntsc_m_csc_composite,
 495                .svideo_levels  = &ntsc_m_levels_svideo,
 496                .svideo_color = &ntsc_m_csc_svideo,
 497
 498                .filter_table = filter_table,
 499        },
 500        {
 501                .name           = "NTSC-J",
 502                .clock          = 108000,
 503                .refresh        = 59940,
 504                .oversample     = TV_OVERSAMPLE_8X,
 505                .component_only = 0,
 506
 507                /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
 508                .hsync_end      = 64,               .hblank_end         = 124,
 509                .hblank_start = 836,        .htotal             = 857,
 510
 511                .progressive    = false,    .trilevel_sync = false,
 512
 513                .vsync_start_f1 = 6,        .vsync_start_f2     = 7,
 514                .vsync_len      = 6,
 515
 516                .veq_ena      = true,       .veq_start_f1       = 0,
 517                .veq_start_f2 = 1,          .veq_len            = 18,
 518
 519                .vi_end_f1      = 20,               .vi_end_f2          = 21,
 520                .nbr_end        = 240,
 521
 522                .burst_ena      = true,
 523                .hburst_start   = 72,               .hburst_len         = 34,
 524                .vburst_start_f1 = 9,               .vburst_end_f1      = 240,
 525                .vburst_start_f2 = 10,              .vburst_end_f2      = 240,
 526                .vburst_start_f3 = 9,               .vburst_end_f3      = 240,
 527                .vburst_start_f4 = 10,              .vburst_end_f4      = 240,
 528
 529                /* desired 3.5800000 actual 3.5800000 clock 107.52 */
 530                .dda1_inc       =    135,
 531                .dda2_inc       =  20800,           .dda2_size          =  27456,
 532                .dda3_inc       =      0,           .dda3_size          =      0,
 533                .sc_reset       = TV_SC_RESET_EVERY_4,
 534                .pal_burst      = false,
 535
 536                .composite_levels = &ntsc_j_levels_composite,
 537                .composite_color = &ntsc_j_csc_composite,
 538                .svideo_levels  = &ntsc_j_levels_svideo,
 539                .svideo_color = &ntsc_j_csc_svideo,
 540
 541                .filter_table = filter_table,
 542        },
 543        {
 544                .name           = "PAL-M",
 545                .clock          = 108000,
 546                .refresh        = 59940,
 547                .oversample     = TV_OVERSAMPLE_8X,
 548                .component_only = 0,
 549
 550                /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
 551                .hsync_end      = 64,             .hblank_end           = 124,
 552                .hblank_start = 836,      .htotal               = 857,
 553
 554                .progressive    = false,            .trilevel_sync = false,
 555
 556                .vsync_start_f1 = 6,                .vsync_start_f2     = 7,
 557                .vsync_len      = 6,
 558
 559                .veq_ena        = true,             .veq_start_f1       = 0,
 560                .veq_start_f2   = 1,                .veq_len            = 18,
 561
 562                .vi_end_f1      = 20,               .vi_end_f2          = 21,
 563                .nbr_end        = 240,
 564
 565                .burst_ena      = true,
 566                .hburst_start   = 72,               .hburst_len         = 34,
 567                .vburst_start_f1 = 9,               .vburst_end_f1      = 240,
 568                .vburst_start_f2 = 10,              .vburst_end_f2      = 240,
 569                .vburst_start_f3 = 9,               .vburst_end_f3      = 240,
 570                .vburst_start_f4 = 10,              .vburst_end_f4      = 240,
 571
 572                /* desired 3.5800000 actual 3.5800000 clock 107.52 */
 573                .dda1_inc       =    135,
 574                .dda2_inc       =  16704,           .dda2_size          =  27456,
 575                .dda3_inc       =      0,           .dda3_size          =      0,
 576                .sc_reset       = TV_SC_RESET_EVERY_8,
 577                .pal_burst  = true,
 578
 579                .composite_levels = &pal_m_levels_composite,
 580                .composite_color = &pal_m_csc_composite,
 581                .svideo_levels  = &pal_m_levels_svideo,
 582                .svideo_color = &pal_m_csc_svideo,
 583
 584                .filter_table = filter_table,
 585        },
 586        {
 587                /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
 588                .name       = "PAL-N",
 589                .clock          = 108000,
 590                .refresh        = 50000,
 591                .oversample     = TV_OVERSAMPLE_8X,
 592                .component_only = 0,
 593
 594                .hsync_end      = 64,               .hblank_end         = 128,
 595                .hblank_start = 844,        .htotal             = 863,
 596
 597                .progressive  = false,    .trilevel_sync = false,
 598
 599
 600                .vsync_start_f1 = 6,       .vsync_start_f2      = 7,
 601                .vsync_len      = 6,
 602
 603                .veq_ena        = true,             .veq_start_f1       = 0,
 604                .veq_start_f2   = 1,                .veq_len            = 18,
 605
 606                .vi_end_f1      = 24,               .vi_end_f2          = 25,
 607                .nbr_end        = 286,
 608
 609                .burst_ena      = true,
 610                .hburst_start = 73,         .hburst_len         = 34,
 611                .vburst_start_f1 = 8,       .vburst_end_f1      = 285,
 612                .vburst_start_f2 = 8,       .vburst_end_f2      = 286,
 613                .vburst_start_f3 = 9,       .vburst_end_f3      = 286,
 614                .vburst_start_f4 = 9,       .vburst_end_f4      = 285,
 615
 616
 617                /* desired 4.4336180 actual 4.4336180 clock 107.52 */
 618                .dda1_inc       =    135,
 619                .dda2_inc       =  23578,       .dda2_size      =  27648,
 620                .dda3_inc       =    134,       .dda3_size      =    625,
 621                .sc_reset   = TV_SC_RESET_EVERY_8,
 622                .pal_burst  = true,
 623
 624                .composite_levels = &pal_n_levels_composite,
 625                .composite_color = &pal_n_csc_composite,
 626                .svideo_levels  = &pal_n_levels_svideo,
 627                .svideo_color = &pal_n_csc_svideo,
 628
 629                .filter_table = filter_table,
 630        },
 631        {
 632                /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
 633                .name       = "PAL",
 634                .clock          = 108000,
 635                .refresh        = 50000,
 636                .oversample     = TV_OVERSAMPLE_8X,
 637                .component_only = 0,
 638
 639                .hsync_end      = 64,               .hblank_end         = 142,
 640                .hblank_start   = 844,      .htotal             = 863,
 641
 642                .progressive    = false,    .trilevel_sync = false,
 643
 644                .vsync_start_f1 = 5,        .vsync_start_f2     = 6,
 645                .vsync_len      = 5,
 646
 647                .veq_ena        = true,     .veq_start_f1       = 0,
 648                .veq_start_f2   = 1,        .veq_len            = 15,
 649
 650                .vi_end_f1      = 24,               .vi_end_f2          = 25,
 651                .nbr_end        = 286,
 652
 653                .burst_ena      = true,
 654                .hburst_start   = 73,               .hburst_len         = 32,
 655                .vburst_start_f1 = 8,               .vburst_end_f1      = 285,
 656                .vburst_start_f2 = 8,               .vburst_end_f2      = 286,
 657                .vburst_start_f3 = 9,               .vburst_end_f3      = 286,
 658                .vburst_start_f4 = 9,               .vburst_end_f4      = 285,
 659
 660                /* desired 4.4336180 actual 4.4336180 clock 107.52 */
 661                .dda1_inc       =    168,
 662                .dda2_inc       =   4122,       .dda2_size      =  27648,
 663                .dda3_inc       =     67,       .dda3_size      =    625,
 664                .sc_reset   = TV_SC_RESET_EVERY_8,
 665                .pal_burst  = true,
 666
 667                .composite_levels = &pal_levels_composite,
 668                .composite_color = &pal_csc_composite,
 669                .svideo_levels  = &pal_levels_svideo,
 670                .svideo_color = &pal_csc_svideo,
 671
 672                .filter_table = filter_table,
 673        },
 674        {
 675                .name       = "480p",
 676                .clock          = 107520,
 677                .refresh        = 59940,
 678                .oversample     = TV_OVERSAMPLE_4X,
 679                .component_only = 1,
 680
 681                .hsync_end      = 64,               .hblank_end         = 122,
 682                .hblank_start   = 842,              .htotal             = 857,
 683
 684                .progressive    = true,             .trilevel_sync = false,
 685
 686                .vsync_start_f1 = 12,               .vsync_start_f2     = 12,
 687                .vsync_len      = 12,
 688
 689                .veq_ena        = false,
 690
 691                .vi_end_f1      = 44,               .vi_end_f2          = 44,
 692                .nbr_end        = 479,
 693
 694                .burst_ena      = false,
 695
 696                .filter_table = filter_table,
 697        },
 698        {
 699                .name       = "576p",
 700                .clock          = 107520,
 701                .refresh        = 50000,
 702                .oversample     = TV_OVERSAMPLE_4X,
 703                .component_only = 1,
 704
 705                .hsync_end      = 64,               .hblank_end         = 139,
 706                .hblank_start   = 859,              .htotal             = 863,
 707
 708                .progressive    = true,             .trilevel_sync = false,
 709
 710                .vsync_start_f1 = 10,               .vsync_start_f2     = 10,
 711                .vsync_len      = 10,
 712
 713                .veq_ena        = false,
 714
 715                .vi_end_f1      = 48,               .vi_end_f2          = 48,
 716                .nbr_end        = 575,
 717
 718                .burst_ena      = false,
 719
 720                .filter_table = filter_table,
 721        },
 722        {
 723                .name       = "720p@60Hz",
 724                .clock          = 148800,
 725                .refresh        = 60000,
 726                .oversample     = TV_OVERSAMPLE_2X,
 727                .component_only = 1,
 728
 729                .hsync_end      = 80,               .hblank_end         = 300,
 730                .hblank_start   = 1580,             .htotal             = 1649,
 731
 732                .progressive    = true,             .trilevel_sync = true,
 733
 734                .vsync_start_f1 = 10,               .vsync_start_f2     = 10,
 735                .vsync_len      = 10,
 736
 737                .veq_ena        = false,
 738
 739                .vi_end_f1      = 29,               .vi_end_f2          = 29,
 740                .nbr_end        = 719,
 741
 742                .burst_ena      = false,
 743
 744                .filter_table = filter_table,
 745        },
 746        {
 747                .name       = "720p@50Hz",
 748                .clock          = 148800,
 749                .refresh        = 50000,
 750                .oversample     = TV_OVERSAMPLE_2X,
 751                .component_only = 1,
 752
 753                .hsync_end      = 80,               .hblank_end         = 300,
 754                .hblank_start   = 1580,             .htotal             = 1979,
 755
 756                .progressive    = true,             .trilevel_sync = true,
 757
 758                .vsync_start_f1 = 10,               .vsync_start_f2     = 10,
 759                .vsync_len      = 10,
 760
 761                .veq_ena        = false,
 762
 763                .vi_end_f1      = 29,               .vi_end_f2          = 29,
 764                .nbr_end        = 719,
 765
 766                .burst_ena      = false,
 767
 768                .filter_table = filter_table,
 769                .max_srcw = 800
 770        },
 771        {
 772                .name       = "1080i@50Hz",
 773                .clock          = 148800,
 774                .refresh        = 50000,
 775                .oversample     = TV_OVERSAMPLE_2X,
 776                .component_only = 1,
 777
 778                .hsync_end      = 88,               .hblank_end         = 235,
 779                .hblank_start   = 2155,             .htotal             = 2639,
 780
 781                .progressive    = false,          .trilevel_sync = true,
 782
 783                .vsync_start_f1 = 4,              .vsync_start_f2     = 5,
 784                .vsync_len      = 10,
 785
 786                .veq_ena        = true,     .veq_start_f1       = 4,
 787                .veq_start_f2   = 4,        .veq_len            = 10,
 788
 789
 790                .vi_end_f1      = 21,           .vi_end_f2          = 22,
 791                .nbr_end        = 539,
 792
 793                .burst_ena      = false,
 794
 795                .filter_table = filter_table,
 796        },
 797        {
 798                .name       = "1080i@60Hz",
 799                .clock          = 148800,
 800                .refresh        = 60000,
 801                .oversample     = TV_OVERSAMPLE_2X,
 802                .component_only = 1,
 803
 804                .hsync_end      = 88,               .hblank_end         = 235,
 805                .hblank_start   = 2155,             .htotal             = 2199,
 806
 807                .progressive    = false,            .trilevel_sync = true,
 808
 809                .vsync_start_f1 = 4,               .vsync_start_f2     = 5,
 810                .vsync_len      = 10,
 811
 812                .veq_ena        = true,             .veq_start_f1       = 4,
 813                .veq_start_f2   = 4,                .veq_len            = 10,
 814
 815
 816                .vi_end_f1      = 21,               .vi_end_f2          = 22,
 817                .nbr_end        = 539,
 818
 819                .burst_ena      = false,
 820
 821                .filter_table = filter_table,
 822        },
 823};
 824
 825static struct intel_tv *enc_to_tv(struct intel_encoder *encoder)
 826{
 827        return container_of(encoder, struct intel_tv, base);
 828}
 829
 830static struct intel_tv *intel_attached_tv(struct drm_connector *connector)
 831{
 832        return enc_to_tv(intel_attached_encoder(connector));
 833}
 834
 835static bool
 836intel_tv_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe)
 837{
 838        struct drm_device *dev = encoder->base.dev;
 839        struct drm_i915_private *dev_priv = to_i915(dev);
 840        u32 tmp = I915_READ(TV_CTL);
 841
 842        if (!(tmp & TV_ENC_ENABLE))
 843                return false;
 844
 845        *pipe = PORT_TO_PIPE(tmp);
 846
 847        return true;
 848}
 849
 850static void
 851intel_enable_tv(struct intel_encoder *encoder,
 852                struct intel_crtc_state *pipe_config,
 853                struct drm_connector_state *conn_state)
 854{
 855        struct drm_device *dev = encoder->base.dev;
 856        struct drm_i915_private *dev_priv = to_i915(dev);
 857
 858        /* Prevents vblank waits from timing out in intel_tv_detect_type() */
 859        intel_wait_for_vblank(dev_priv,
 860                              to_intel_crtc(encoder->base.crtc)->pipe);
 861
 862        I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE);
 863}
 864
 865static void
 866intel_disable_tv(struct intel_encoder *encoder,
 867                 struct intel_crtc_state *old_crtc_state,
 868                 struct drm_connector_state *old_conn_state)
 869{
 870        struct drm_device *dev = encoder->base.dev;
 871        struct drm_i915_private *dev_priv = to_i915(dev);
 872
 873        I915_WRITE(TV_CTL, I915_READ(TV_CTL) & ~TV_ENC_ENABLE);
 874}
 875
 876static const struct tv_mode *
 877intel_tv_mode_lookup(const char *tv_format)
 878{
 879        int i;
 880
 881        for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
 882                const struct tv_mode *tv_mode = &tv_modes[i];
 883
 884                if (!strcmp(tv_format, tv_mode->name))
 885                        return tv_mode;
 886        }
 887        return NULL;
 888}
 889
 890static const struct tv_mode *
 891intel_tv_mode_find(struct intel_tv *intel_tv)
 892{
 893        return intel_tv_mode_lookup(intel_tv->tv_format);
 894}
 895
 896static enum drm_mode_status
 897intel_tv_mode_valid(struct drm_connector *connector,
 898                    struct drm_display_mode *mode)
 899{
 900        struct intel_tv *intel_tv = intel_attached_tv(connector);
 901        const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
 902        int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
 903
 904        if (mode->clock > max_dotclk)
 905                return MODE_CLOCK_HIGH;
 906
 907        /* Ensure TV refresh is close to desired refresh */
 908        if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode) * 1000)
 909                                < 1000)
 910                return MODE_OK;
 911
 912        return MODE_CLOCK_RANGE;
 913}
 914
 915
 916static void
 917intel_tv_get_config(struct intel_encoder *encoder,
 918                    struct intel_crtc_state *pipe_config)
 919{
 920        pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock;
 921}
 922
 923static bool
 924intel_tv_compute_config(struct intel_encoder *encoder,
 925                        struct intel_crtc_state *pipe_config,
 926                        struct drm_connector_state *conn_state)
 927{
 928        struct intel_tv *intel_tv = enc_to_tv(encoder);
 929        const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
 930
 931        if (!tv_mode)
 932                return false;
 933
 934        pipe_config->base.adjusted_mode.crtc_clock = tv_mode->clock;
 935        DRM_DEBUG_KMS("forcing bpc to 8 for TV\n");
 936        pipe_config->pipe_bpp = 8*3;
 937
 938        /* TV has it's own notion of sync and other mode flags, so clear them. */
 939        pipe_config->base.adjusted_mode.flags = 0;
 940
 941        /*
 942         * FIXME: We don't check whether the input mode is actually what we want
 943         * or whether userspace is doing something stupid.
 944         */
 945
 946        return true;
 947}
 948
 949static void
 950set_tv_mode_timings(struct drm_i915_private *dev_priv,
 951                    const struct tv_mode *tv_mode,
 952                    bool burst_ena)
 953{
 954        u32 hctl1, hctl2, hctl3;
 955        u32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
 956
 957        hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) |
 958                (tv_mode->htotal << TV_HTOTAL_SHIFT);
 959
 960        hctl2 = (tv_mode->hburst_start << 16) |
 961                (tv_mode->hburst_len << TV_HBURST_LEN_SHIFT);
 962
 963        if (burst_ena)
 964                hctl2 |= TV_BURST_ENA;
 965
 966        hctl3 = (tv_mode->hblank_start << TV_HBLANK_START_SHIFT) |
 967                (tv_mode->hblank_end << TV_HBLANK_END_SHIFT);
 968
 969        vctl1 = (tv_mode->nbr_end << TV_NBR_END_SHIFT) |
 970                (tv_mode->vi_end_f1 << TV_VI_END_F1_SHIFT) |
 971                (tv_mode->vi_end_f2 << TV_VI_END_F2_SHIFT);
 972
 973        vctl2 = (tv_mode->vsync_len << TV_VSYNC_LEN_SHIFT) |
 974                (tv_mode->vsync_start_f1 << TV_VSYNC_START_F1_SHIFT) |
 975                (tv_mode->vsync_start_f2 << TV_VSYNC_START_F2_SHIFT);
 976
 977        vctl3 = (tv_mode->veq_len << TV_VEQ_LEN_SHIFT) |
 978                (tv_mode->veq_start_f1 << TV_VEQ_START_F1_SHIFT) |
 979                (tv_mode->veq_start_f2 << TV_VEQ_START_F2_SHIFT);
 980
 981        if (tv_mode->veq_ena)
 982                vctl3 |= TV_EQUAL_ENA;
 983
 984        vctl4 = (tv_mode->vburst_start_f1 << TV_VBURST_START_F1_SHIFT) |
 985                (tv_mode->vburst_end_f1 << TV_VBURST_END_F1_SHIFT);
 986
 987        vctl5 = (tv_mode->vburst_start_f2 << TV_VBURST_START_F2_SHIFT) |
 988                (tv_mode->vburst_end_f2 << TV_VBURST_END_F2_SHIFT);
 989
 990        vctl6 = (tv_mode->vburst_start_f3 << TV_VBURST_START_F3_SHIFT) |
 991                (tv_mode->vburst_end_f3 << TV_VBURST_END_F3_SHIFT);
 992
 993        vctl7 = (tv_mode->vburst_start_f4 << TV_VBURST_START_F4_SHIFT) |
 994                (tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT);
 995
 996        I915_WRITE(TV_H_CTL_1, hctl1);
 997        I915_WRITE(TV_H_CTL_2, hctl2);
 998        I915_WRITE(TV_H_CTL_3, hctl3);
 999        I915_WRITE(TV_V_CTL_1, vctl1);
1000        I915_WRITE(TV_V_CTL_2, vctl2);
1001        I915_WRITE(TV_V_CTL_3, vctl3);
1002        I915_WRITE(TV_V_CTL_4, vctl4);
1003        I915_WRITE(TV_V_CTL_5, vctl5);
1004        I915_WRITE(TV_V_CTL_6, vctl6);
1005        I915_WRITE(TV_V_CTL_7, vctl7);
1006}
1007
1008static void set_color_conversion(struct drm_i915_private *dev_priv,
1009                                 const struct color_conversion *color_conversion)
1010{
1011        if (!color_conversion)
1012                return;
1013
1014        I915_WRITE(TV_CSC_Y, (color_conversion->ry << 16) |
1015                   color_conversion->gy);
1016        I915_WRITE(TV_CSC_Y2, (color_conversion->by << 16) |
1017                   color_conversion->ay);
1018        I915_WRITE(TV_CSC_U, (color_conversion->ru << 16) |
1019                   color_conversion->gu);
1020        I915_WRITE(TV_CSC_U2, (color_conversion->bu << 16) |
1021                   color_conversion->au);
1022        I915_WRITE(TV_CSC_V, (color_conversion->rv << 16) |
1023                   color_conversion->gv);
1024        I915_WRITE(TV_CSC_V2, (color_conversion->bv << 16) |
1025                   color_conversion->av);
1026}
1027
1028static void intel_tv_pre_enable(struct intel_encoder *encoder,
1029                                struct intel_crtc_state *pipe_config,
1030                                struct drm_connector_state *conn_state)
1031{
1032        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1033        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
1034        struct intel_tv *intel_tv = enc_to_tv(encoder);
1035        const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
1036        u32 tv_ctl;
1037        u32 scctl1, scctl2, scctl3;
1038        int i, j;
1039        const struct video_levels *video_levels;
1040        const struct color_conversion *color_conversion;
1041        bool burst_ena;
1042        int xpos = 0x0, ypos = 0x0;
1043        unsigned int xsize, ysize;
1044
1045        if (!tv_mode)
1046                return; /* can't happen (mode_prepare prevents this) */
1047
1048        tv_ctl = I915_READ(TV_CTL);
1049        tv_ctl &= TV_CTL_SAVE;
1050
1051        switch (intel_tv->type) {
1052        default:
1053        case DRM_MODE_CONNECTOR_Unknown:
1054        case DRM_MODE_CONNECTOR_Composite:
1055                tv_ctl |= TV_ENC_OUTPUT_COMPOSITE;
1056                video_levels = tv_mode->composite_levels;
1057                color_conversion = tv_mode->composite_color;
1058                burst_ena = tv_mode->burst_ena;
1059                break;
1060        case DRM_MODE_CONNECTOR_Component:
1061                tv_ctl |= TV_ENC_OUTPUT_COMPONENT;
1062                video_levels = &component_levels;
1063                if (tv_mode->burst_ena)
1064                        color_conversion = &sdtv_csc_yprpb;
1065                else
1066                        color_conversion = &hdtv_csc_yprpb;
1067                burst_ena = false;
1068                break;
1069        case DRM_MODE_CONNECTOR_SVIDEO:
1070                tv_ctl |= TV_ENC_OUTPUT_SVIDEO;
1071                video_levels = tv_mode->svideo_levels;
1072                color_conversion = tv_mode->svideo_color;
1073                burst_ena = tv_mode->burst_ena;
1074                break;
1075        }
1076
1077        if (intel_crtc->pipe == 1)
1078                tv_ctl |= TV_ENC_PIPEB_SELECT;
1079        tv_ctl |= tv_mode->oversample;
1080
1081        if (tv_mode->progressive)
1082                tv_ctl |= TV_PROGRESSIVE;
1083        if (tv_mode->trilevel_sync)
1084                tv_ctl |= TV_TRILEVEL_SYNC;
1085        if (tv_mode->pal_burst)
1086                tv_ctl |= TV_PAL_BURST;
1087
1088        scctl1 = 0;
1089        if (tv_mode->dda1_inc)
1090                scctl1 |= TV_SC_DDA1_EN;
1091        if (tv_mode->dda2_inc)
1092                scctl1 |= TV_SC_DDA2_EN;
1093        if (tv_mode->dda3_inc)
1094                scctl1 |= TV_SC_DDA3_EN;
1095        scctl1 |= tv_mode->sc_reset;
1096        if (video_levels)
1097                scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT;
1098        scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT;
1099
1100        scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
1101                tv_mode->dda2_inc << TV_SCDDA2_INC_SHIFT;
1102
1103        scctl3 = tv_mode->dda3_size << TV_SCDDA3_SIZE_SHIFT |
1104                tv_mode->dda3_inc << TV_SCDDA3_INC_SHIFT;
1105
1106        /* Enable two fixes for the chips that need them. */
1107        if (IS_I915GM(dev_priv))
1108                tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
1109
1110        set_tv_mode_timings(dev_priv, tv_mode, burst_ena);
1111
1112        I915_WRITE(TV_SC_CTL_1, scctl1);
1113        I915_WRITE(TV_SC_CTL_2, scctl2);
1114        I915_WRITE(TV_SC_CTL_3, scctl3);
1115
1116        set_color_conversion(dev_priv, color_conversion);
1117
1118        if (INTEL_GEN(dev_priv) >= 4)
1119                I915_WRITE(TV_CLR_KNOBS, 0x00404000);
1120        else
1121                I915_WRITE(TV_CLR_KNOBS, 0x00606000);
1122
1123        if (video_levels)
1124                I915_WRITE(TV_CLR_LEVEL,
1125                           ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
1126                            (video_levels->blank << TV_BLANK_LEVEL_SHIFT)));
1127
1128        assert_pipe_disabled(dev_priv, intel_crtc->pipe);
1129
1130        /* Filter ctl must be set before TV_WIN_SIZE */
1131        I915_WRITE(TV_FILTER_CTL_1, TV_AUTO_SCALE);
1132        xsize = tv_mode->hblank_start - tv_mode->hblank_end;
1133        if (tv_mode->progressive)
1134                ysize = tv_mode->nbr_end + 1;
1135        else
1136                ysize = 2*tv_mode->nbr_end + 1;
1137
1138        xpos += intel_tv->margin[TV_MARGIN_LEFT];
1139        ypos += intel_tv->margin[TV_MARGIN_TOP];
1140        xsize -= (intel_tv->margin[TV_MARGIN_LEFT] +
1141                  intel_tv->margin[TV_MARGIN_RIGHT]);
1142        ysize -= (intel_tv->margin[TV_MARGIN_TOP] +
1143                  intel_tv->margin[TV_MARGIN_BOTTOM]);
1144        I915_WRITE(TV_WIN_POS, (xpos<<16)|ypos);
1145        I915_WRITE(TV_WIN_SIZE, (xsize<<16)|ysize);
1146
1147        j = 0;
1148        for (i = 0; i < 60; i++)
1149                I915_WRITE(TV_H_LUMA(i), tv_mode->filter_table[j++]);
1150        for (i = 0; i < 60; i++)
1151                I915_WRITE(TV_H_CHROMA(i), tv_mode->filter_table[j++]);
1152        for (i = 0; i < 43; i++)
1153                I915_WRITE(TV_V_LUMA(i), tv_mode->filter_table[j++]);
1154        for (i = 0; i < 43; i++)
1155                I915_WRITE(TV_V_CHROMA(i), tv_mode->filter_table[j++]);
1156        I915_WRITE(TV_DAC, I915_READ(TV_DAC) & TV_DAC_SAVE);
1157        I915_WRITE(TV_CTL, tv_ctl);
1158}
1159
1160static const struct drm_display_mode reported_modes[] = {
1161        {
1162                .name = "NTSC 480i",
1163                .clock = 107520,
1164                .hdisplay = 1280,
1165                .hsync_start = 1368,
1166                .hsync_end = 1496,
1167                .htotal = 1712,
1168
1169                .vdisplay = 1024,
1170                .vsync_start = 1027,
1171                .vsync_end = 1034,
1172                .vtotal = 1104,
1173                .type = DRM_MODE_TYPE_DRIVER,
1174        },
1175};
1176
1177/**
1178 * Detects TV presence by checking for load.
1179 *
1180 * Requires that the current pipe's DPLL is active.
1181
1182 * \return true if TV is connected.
1183 * \return false if TV is disconnected.
1184 */
1185static int
1186intel_tv_detect_type(struct intel_tv *intel_tv,
1187                      struct drm_connector *connector)
1188{
1189        struct drm_crtc *crtc = connector->state->crtc;
1190        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1191        struct drm_device *dev = connector->dev;
1192        struct drm_i915_private *dev_priv = to_i915(dev);
1193        u32 tv_ctl, save_tv_ctl;
1194        u32 tv_dac, save_tv_dac;
1195        int type;
1196
1197        /* Disable TV interrupts around load detect or we'll recurse */
1198        if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
1199                spin_lock_irq(&dev_priv->irq_lock);
1200                i915_disable_pipestat(dev_priv, 0,
1201                                      PIPE_HOTPLUG_INTERRUPT_STATUS |
1202                                      PIPE_HOTPLUG_TV_INTERRUPT_STATUS);
1203                spin_unlock_irq(&dev_priv->irq_lock);
1204        }
1205
1206        save_tv_dac = tv_dac = I915_READ(TV_DAC);
1207        save_tv_ctl = tv_ctl = I915_READ(TV_CTL);
1208
1209        /* Poll for TV detection */
1210        tv_ctl &= ~(TV_ENC_ENABLE | TV_TEST_MODE_MASK);
1211        tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
1212        if (intel_crtc->pipe == 1)
1213                tv_ctl |= TV_ENC_PIPEB_SELECT;
1214        else
1215                tv_ctl &= ~TV_ENC_PIPEB_SELECT;
1216
1217        tv_dac &= ~(TVDAC_SENSE_MASK | DAC_A_MASK | DAC_B_MASK | DAC_C_MASK);
1218        tv_dac |= (TVDAC_STATE_CHG_EN |
1219                   TVDAC_A_SENSE_CTL |
1220                   TVDAC_B_SENSE_CTL |
1221                   TVDAC_C_SENSE_CTL |
1222                   DAC_CTL_OVERRIDE |
1223                   DAC_A_0_7_V |
1224                   DAC_B_0_7_V |
1225                   DAC_C_0_7_V);
1226
1227
1228        /*
1229         * The TV sense state should be cleared to zero on cantiga platform. Otherwise
1230         * the TV is misdetected. This is hardware requirement.
1231         */
1232        if (IS_GM45(dev_priv))
1233                tv_dac &= ~(TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL |
1234                            TVDAC_B_SENSE_CTL | TVDAC_C_SENSE_CTL);
1235
1236        I915_WRITE(TV_CTL, tv_ctl);
1237        I915_WRITE(TV_DAC, tv_dac);
1238        POSTING_READ(TV_DAC);
1239
1240        intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
1241
1242        type = -1;
1243        tv_dac = I915_READ(TV_DAC);
1244        DRM_DEBUG_KMS("TV detected: %x, %x\n", tv_ctl, tv_dac);
1245        /*
1246         *  A B C
1247         *  0 1 1 Composite
1248         *  1 0 X svideo
1249         *  0 0 0 Component
1250         */
1251        if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
1252                DRM_DEBUG_KMS("Detected Composite TV connection\n");
1253                type = DRM_MODE_CONNECTOR_Composite;
1254        } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
1255                DRM_DEBUG_KMS("Detected S-Video TV connection\n");
1256                type = DRM_MODE_CONNECTOR_SVIDEO;
1257        } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
1258                DRM_DEBUG_KMS("Detected Component TV connection\n");
1259                type = DRM_MODE_CONNECTOR_Component;
1260        } else {
1261                DRM_DEBUG_KMS("Unrecognised TV connection\n");
1262                type = -1;
1263        }
1264
1265        I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
1266        I915_WRITE(TV_CTL, save_tv_ctl);
1267        POSTING_READ(TV_CTL);
1268
1269        /* For unknown reasons the hw barfs if we don't do this vblank wait. */
1270        intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
1271
1272        /* Restore interrupt config */
1273        if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
1274                spin_lock_irq(&dev_priv->irq_lock);
1275                i915_enable_pipestat(dev_priv, 0,
1276                                     PIPE_HOTPLUG_INTERRUPT_STATUS |
1277                                     PIPE_HOTPLUG_TV_INTERRUPT_STATUS);
1278                spin_unlock_irq(&dev_priv->irq_lock);
1279        }
1280
1281        return type;
1282}
1283
1284/*
1285 * Here we set accurate tv format according to connector type
1286 * i.e Component TV should not be assigned by NTSC or PAL
1287 */
1288static void intel_tv_find_better_format(struct drm_connector *connector)
1289{
1290        struct intel_tv *intel_tv = intel_attached_tv(connector);
1291        const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
1292        int i;
1293
1294        if ((intel_tv->type == DRM_MODE_CONNECTOR_Component) ==
1295                tv_mode->component_only)
1296                return;
1297
1298
1299        for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
1300                tv_mode = tv_modes + i;
1301
1302                if ((intel_tv->type == DRM_MODE_CONNECTOR_Component) ==
1303                        tv_mode->component_only)
1304                        break;
1305        }
1306
1307        intel_tv->tv_format = tv_mode->name;
1308        drm_object_property_set_value(&connector->base,
1309                connector->dev->mode_config.tv_mode_property, i);
1310}
1311
1312/**
1313 * Detect the TV connection.
1314 *
1315 * Currently this always returns CONNECTOR_STATUS_UNKNOWN, as we need to be sure
1316 * we have a pipe programmed in order to probe the TV.
1317 */
1318static enum drm_connector_status
1319intel_tv_detect(struct drm_connector *connector, bool force)
1320{
1321        struct drm_display_mode mode;
1322        struct intel_tv *intel_tv = intel_attached_tv(connector);
1323        enum drm_connector_status status;
1324        int type;
1325
1326        DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n",
1327                      connector->base.id, connector->name,
1328                      force);
1329
1330        mode = reported_modes[0];
1331
1332        if (force) {
1333                struct intel_load_detect_pipe tmp;
1334                struct drm_modeset_acquire_ctx ctx;
1335
1336                drm_modeset_acquire_init(&ctx, 0);
1337
1338                if (intel_get_load_detect_pipe(connector, &mode, &tmp, &ctx)) {
1339                        type = intel_tv_detect_type(intel_tv, connector);
1340                        intel_release_load_detect_pipe(connector, &tmp, &ctx);
1341                        status = type < 0 ?
1342                                connector_status_disconnected :
1343                                connector_status_connected;
1344                } else
1345                        status = connector_status_unknown;
1346
1347                drm_modeset_drop_locks(&ctx);
1348                drm_modeset_acquire_fini(&ctx);
1349        } else
1350                return connector->status;
1351
1352        if (status != connector_status_connected)
1353                return status;
1354
1355        intel_tv->type = type;
1356        intel_tv_find_better_format(connector);
1357
1358        return connector_status_connected;
1359}
1360
1361static const struct input_res {
1362        const char *name;
1363        int w, h;
1364} input_res_table[] = {
1365        {"640x480", 640, 480},
1366        {"800x600", 800, 600},
1367        {"1024x768", 1024, 768},
1368        {"1280x1024", 1280, 1024},
1369        {"848x480", 848, 480},
1370        {"1280x720", 1280, 720},
1371        {"1920x1080", 1920, 1080},
1372};
1373
1374/*
1375 * Chose preferred mode  according to line number of TV format
1376 */
1377static void
1378intel_tv_chose_preferred_modes(struct drm_connector *connector,
1379                               struct drm_display_mode *mode_ptr)
1380{
1381        struct intel_tv *intel_tv = intel_attached_tv(connector);
1382        const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
1383
1384        if (tv_mode->nbr_end < 480 && mode_ptr->vdisplay == 480)
1385                mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
1386        else if (tv_mode->nbr_end > 480) {
1387                if (tv_mode->progressive == true && tv_mode->nbr_end < 720) {
1388                        if (mode_ptr->vdisplay == 720)
1389                                mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
1390                } else if (mode_ptr->vdisplay == 1080)
1391                                mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
1392        }
1393}
1394
1395/**
1396 * Stub get_modes function.
1397 *
1398 * This should probably return a set of fixed modes, unless we can figure out
1399 * how to probe modes off of TV connections.
1400 */
1401
1402static int
1403intel_tv_get_modes(struct drm_connector *connector)
1404{
1405        struct drm_display_mode *mode_ptr;
1406        struct intel_tv *intel_tv = intel_attached_tv(connector);
1407        const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
1408        int j, count = 0;
1409        u64 tmp;
1410
1411        for (j = 0; j < ARRAY_SIZE(input_res_table);
1412             j++) {
1413                const struct input_res *input = &input_res_table[j];
1414                unsigned int hactive_s = input->w;
1415                unsigned int vactive_s = input->h;
1416
1417                if (tv_mode->max_srcw && input->w > tv_mode->max_srcw)
1418                        continue;
1419
1420                if (input->w > 1024 && (!tv_mode->progressive
1421                                        && !tv_mode->component_only))
1422                        continue;
1423
1424                mode_ptr = drm_mode_create(connector->dev);
1425                if (!mode_ptr)
1426                        continue;
1427                strncpy(mode_ptr->name, input->name, DRM_DISPLAY_MODE_LEN);
1428                mode_ptr->name[DRM_DISPLAY_MODE_LEN - 1] = '\0';
1429
1430                mode_ptr->hdisplay = hactive_s;
1431                mode_ptr->hsync_start = hactive_s + 1;
1432                mode_ptr->hsync_end = hactive_s + 64;
1433                if (mode_ptr->hsync_end <= mode_ptr->hsync_start)
1434                        mode_ptr->hsync_end = mode_ptr->hsync_start + 1;
1435                mode_ptr->htotal = hactive_s + 96;
1436
1437                mode_ptr->vdisplay = vactive_s;
1438                mode_ptr->vsync_start = vactive_s + 1;
1439                mode_ptr->vsync_end = vactive_s + 32;
1440                if (mode_ptr->vsync_end <= mode_ptr->vsync_start)
1441                        mode_ptr->vsync_end = mode_ptr->vsync_start  + 1;
1442                mode_ptr->vtotal = vactive_s + 33;
1443
1444                tmp = (u64) tv_mode->refresh * mode_ptr->vtotal;
1445                tmp *= mode_ptr->htotal;
1446                tmp = div_u64(tmp, 1000000);
1447                mode_ptr->clock = (int) tmp;
1448
1449                mode_ptr->type = DRM_MODE_TYPE_DRIVER;
1450                intel_tv_chose_preferred_modes(connector, mode_ptr);
1451                drm_mode_probed_add(connector, mode_ptr);
1452                count++;
1453        }
1454
1455        return count;
1456}
1457
1458static void
1459intel_tv_destroy(struct drm_connector *connector)
1460{
1461        drm_connector_cleanup(connector);
1462        kfree(connector);
1463}
1464
1465
1466static int
1467intel_tv_set_property(struct drm_connector *connector, struct drm_property *property,
1468                      uint64_t val)
1469{
1470        struct drm_device *dev = connector->dev;
1471        struct intel_tv *intel_tv = intel_attached_tv(connector);
1472        struct drm_crtc *crtc = intel_tv->base.base.crtc;
1473        int ret = 0;
1474        bool changed = false;
1475
1476        ret = drm_object_property_set_value(&connector->base, property, val);
1477        if (ret < 0)
1478                goto out;
1479
1480        if (property == dev->mode_config.tv_left_margin_property &&
1481                intel_tv->margin[TV_MARGIN_LEFT] != val) {
1482                intel_tv->margin[TV_MARGIN_LEFT] = val;
1483                changed = true;
1484        } else if (property == dev->mode_config.tv_right_margin_property &&
1485                intel_tv->margin[TV_MARGIN_RIGHT] != val) {
1486                intel_tv->margin[TV_MARGIN_RIGHT] = val;
1487                changed = true;
1488        } else if (property == dev->mode_config.tv_top_margin_property &&
1489                intel_tv->margin[TV_MARGIN_TOP] != val) {
1490                intel_tv->margin[TV_MARGIN_TOP] = val;
1491                changed = true;
1492        } else if (property == dev->mode_config.tv_bottom_margin_property &&
1493                intel_tv->margin[TV_MARGIN_BOTTOM] != val) {
1494                intel_tv->margin[TV_MARGIN_BOTTOM] = val;
1495                changed = true;
1496        } else if (property == dev->mode_config.tv_mode_property) {
1497                if (val >= ARRAY_SIZE(tv_modes)) {
1498                        ret = -EINVAL;
1499                        goto out;
1500                }
1501                if (!strcmp(intel_tv->tv_format, tv_modes[val].name))
1502                        goto out;
1503
1504                intel_tv->tv_format = tv_modes[val].name;
1505                changed = true;
1506        } else {
1507                ret = -EINVAL;
1508                goto out;
1509        }
1510
1511        if (changed && crtc)
1512                intel_crtc_restore_mode(crtc);
1513out:
1514        return ret;
1515}
1516
1517static const struct drm_connector_funcs intel_tv_connector_funcs = {
1518        .dpms = drm_atomic_helper_connector_dpms,
1519        .detect = intel_tv_detect,
1520        .late_register = intel_connector_register,
1521        .early_unregister = intel_connector_unregister,
1522        .destroy = intel_tv_destroy,
1523        .set_property = intel_tv_set_property,
1524        .atomic_get_property = intel_connector_atomic_get_property,
1525        .fill_modes = drm_helper_probe_single_connector_modes,
1526        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1527        .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1528};
1529
1530static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = {
1531        .mode_valid = intel_tv_mode_valid,
1532        .get_modes = intel_tv_get_modes,
1533};
1534
1535static const struct drm_encoder_funcs intel_tv_enc_funcs = {
1536        .destroy = intel_encoder_destroy,
1537};
1538
1539void
1540intel_tv_init(struct drm_device *dev)
1541{
1542        struct drm_i915_private *dev_priv = to_i915(dev);
1543        struct drm_connector *connector;
1544        struct intel_tv *intel_tv;
1545        struct intel_encoder *intel_encoder;
1546        struct intel_connector *intel_connector;
1547        u32 tv_dac_on, tv_dac_off, save_tv_dac;
1548        const char *tv_format_names[ARRAY_SIZE(tv_modes)];
1549        int i, initial_mode = 0;
1550
1551        if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
1552                return;
1553
1554        if (!intel_bios_is_tv_present(dev_priv)) {
1555                DRM_DEBUG_KMS("Integrated TV is not present.\n");
1556                return;
1557        }
1558
1559        /*
1560         * Sanity check the TV output by checking to see if the
1561         * DAC register holds a value
1562         */
1563        save_tv_dac = I915_READ(TV_DAC);
1564
1565        I915_WRITE(TV_DAC, save_tv_dac | TVDAC_STATE_CHG_EN);
1566        tv_dac_on = I915_READ(TV_DAC);
1567
1568        I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
1569        tv_dac_off = I915_READ(TV_DAC);
1570
1571        I915_WRITE(TV_DAC, save_tv_dac);
1572
1573        /*
1574         * If the register does not hold the state change enable
1575         * bit, (either as a 0 or a 1), assume it doesn't really
1576         * exist
1577         */
1578        if ((tv_dac_on & TVDAC_STATE_CHG_EN) == 0 ||
1579            (tv_dac_off & TVDAC_STATE_CHG_EN) != 0)
1580                return;
1581
1582        intel_tv = kzalloc(sizeof(*intel_tv), GFP_KERNEL);
1583        if (!intel_tv) {
1584                return;
1585        }
1586
1587        intel_connector = intel_connector_alloc();
1588        if (!intel_connector) {
1589                kfree(intel_tv);
1590                return;
1591        }
1592
1593        intel_encoder = &intel_tv->base;
1594        connector = &intel_connector->base;
1595
1596        /* The documentation, for the older chipsets at least, recommend
1597         * using a polling method rather than hotplug detection for TVs.
1598         * This is because in order to perform the hotplug detection, the PLLs
1599         * for the TV must be kept alive increasing power drain and starving
1600         * bandwidth from other encoders. Notably for instance, it causes
1601         * pipe underruns on Crestline when this encoder is supposedly idle.
1602         *
1603         * More recent chipsets favour HDMI rather than integrated S-Video.
1604         */
1605        intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
1606
1607        drm_connector_init(dev, connector, &intel_tv_connector_funcs,
1608                           DRM_MODE_CONNECTOR_SVIDEO);
1609
1610        drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs,
1611                         DRM_MODE_ENCODER_TVDAC, "TV");
1612
1613        intel_encoder->compute_config = intel_tv_compute_config;
1614        intel_encoder->get_config = intel_tv_get_config;
1615        intel_encoder->pre_enable = intel_tv_pre_enable;
1616        intel_encoder->enable = intel_enable_tv;
1617        intel_encoder->disable = intel_disable_tv;
1618        intel_encoder->get_hw_state = intel_tv_get_hw_state;
1619        intel_connector->get_hw_state = intel_connector_get_hw_state;
1620
1621        intel_connector_attach_encoder(intel_connector, intel_encoder);
1622
1623        intel_encoder->type = INTEL_OUTPUT_TVOUT;
1624        intel_encoder->port = PORT_NONE;
1625        intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
1626        intel_encoder->cloneable = 0;
1627        intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1));
1628        intel_tv->type = DRM_MODE_CONNECTOR_Unknown;
1629
1630        /* BIOS margin values */
1631        intel_tv->margin[TV_MARGIN_LEFT] = 54;
1632        intel_tv->margin[TV_MARGIN_TOP] = 36;
1633        intel_tv->margin[TV_MARGIN_RIGHT] = 46;
1634        intel_tv->margin[TV_MARGIN_BOTTOM] = 37;
1635
1636        intel_tv->tv_format = tv_modes[initial_mode].name;
1637
1638        drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs);
1639        connector->interlace_allowed = false;
1640        connector->doublescan_allowed = false;
1641
1642        /* Create TV properties then attach current values */
1643        for (i = 0; i < ARRAY_SIZE(tv_modes); i++)
1644                tv_format_names[i] = tv_modes[i].name;
1645        drm_mode_create_tv_properties(dev,
1646                                      ARRAY_SIZE(tv_modes),
1647                                      tv_format_names);
1648
1649        drm_object_attach_property(&connector->base, dev->mode_config.tv_mode_property,
1650                                   initial_mode);
1651        drm_object_attach_property(&connector->base,
1652                                   dev->mode_config.tv_left_margin_property,
1653                                   intel_tv->margin[TV_MARGIN_LEFT]);
1654        drm_object_attach_property(&connector->base,
1655                                   dev->mode_config.tv_top_margin_property,
1656                                   intel_tv->margin[TV_MARGIN_TOP]);
1657        drm_object_attach_property(&connector->base,
1658                                   dev->mode_config.tv_right_margin_property,
1659                                   intel_tv->margin[TV_MARGIN_RIGHT]);
1660        drm_object_attach_property(&connector->base,
1661                                   dev->mode_config.tv_bottom_margin_property,
1662                                   intel_tv->margin[TV_MARGIN_BOTTOM]);
1663}
1664