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