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