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 "drmP.h"
  34#include "drm.h"
  35#include "drm_crtc.h"
  36#include "drm_edid.h"
  37#include "intel_drv.h"
  38#include "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 sdtv_csc_rgb = {
 330        .ry = 0x0000, .gy = 0x0f00, .by = 0x0000, .ay = 0x0166,
 331        .ru = 0x0000, .gu = 0x0000, .bu = 0x0f00, .au = 0x0166,
 332        .rv = 0x0f00, .gv = 0x0000, .bv = 0x0000, .av = 0x0166,
 333};
 334
 335static const struct color_conversion hdtv_csc_yprpb = {
 336        .ry = 0x05b3, .gy = 0x016e, .by = 0x0728, .ay = 0x0145,
 337        .ru = 0x07d5, .gu = 0x038b, .bu = 0x0100, .au = 0x0200,
 338        .rv = 0x0100, .gv = 0x03d1, .bv = 0x06bc, .av = 0x0200,
 339};
 340
 341static const struct color_conversion hdtv_csc_rgb = {
 342        .ry = 0x0000, .gy = 0x0f00, .by = 0x0000, .ay = 0x0166,
 343        .ru = 0x0000, .gu = 0x0000, .bu = 0x0f00, .au = 0x0166,
 344        .rv = 0x0f00, .gv = 0x0000, .bv = 0x0000, .av = 0x0166,
 345};
 346
 347static const struct video_levels component_levels = {
 348        .blank = 279, .black = 279, .burst = 0,
 349};
 350
 351
 352struct tv_mode {
 353        const char *name;
 354        int clock;
 355        int refresh; /* in millihertz (for precision) */
 356        u32 oversample;
 357        int hsync_end, hblank_start, hblank_end, htotal;
 358        bool progressive, trilevel_sync, component_only;
 359        int vsync_start_f1, vsync_start_f2, vsync_len;
 360        bool veq_ena;
 361        int veq_start_f1, veq_start_f2, veq_len;
 362        int vi_end_f1, vi_end_f2, nbr_end;
 363        bool burst_ena;
 364        int hburst_start, hburst_len;
 365        int vburst_start_f1, vburst_end_f1;
 366        int vburst_start_f2, vburst_end_f2;
 367        int vburst_start_f3, vburst_end_f3;
 368        int vburst_start_f4, vburst_end_f4;
 369        /*
 370         * subcarrier programming
 371         */
 372        int dda2_size, dda3_size, dda1_inc, dda2_inc, dda3_inc;
 373        u32 sc_reset;
 374        bool pal_burst;
 375        /*
 376         * blank/black levels
 377         */
 378        const struct video_levels *composite_levels, *svideo_levels;
 379        const struct color_conversion *composite_color, *svideo_color;
 380        const u32 *filter_table;
 381        int max_srcw;
 382};
 383
 384
 385/*
 386 * Sub carrier DDA
 387 *
 388 *  I think this works as follows:
 389 *
 390 *  subcarrier freq = pixel_clock * (dda1_inc + dda2_inc / dda2_size) / 4096
 391 *
 392 * Presumably, when dda3 is added in, it gets to adjust the dda2_inc value
 393 *
 394 * So,
 395 *  dda1_ideal = subcarrier/pixel * 4096
 396 *  dda1_inc = floor (dda1_ideal)
 397 *  dda2 = dda1_ideal - dda1_inc
 398 *
 399 *  then pick a ratio for dda2 that gives the closest approximation. If
 400 *  you can't get close enough, you can play with dda3 as well. This
 401 *  seems likely to happen when dda2 is small as the jumps would be larger
 402 *
 403 * To invert this,
 404 *
 405 *  pixel_clock = subcarrier * 4096 / (dda1_inc + dda2_inc / dda2_size)
 406 *
 407 * The constants below were all computed using a 107.520MHz clock
 408 */
 409
 410/**
 411 * Register programming values for TV modes.
 412 *
 413 * These values account for -1s required.
 414 */
 415
 416static const struct tv_mode tv_modes[] = {
 417        {
 418                .name           = "NTSC-M",
 419                .clock          = 108000,
 420                .refresh        = 29970,
 421                .oversample     = TV_OVERSAMPLE_8X,
 422                .component_only = 0,
 423                /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
 424
 425                .hsync_end      = 64,               .hblank_end         = 124,
 426                .hblank_start   = 836,              .htotal             = 857,
 427
 428                .progressive    = false,            .trilevel_sync = false,
 429
 430                .vsync_start_f1 = 6,                .vsync_start_f2     = 7,
 431                .vsync_len      = 6,
 432
 433                .veq_ena        = true,             .veq_start_f1       = 0,
 434                .veq_start_f2   = 1,                .veq_len            = 18,
 435
 436                .vi_end_f1      = 20,               .vi_end_f2          = 21,
 437                .nbr_end        = 240,
 438
 439                .burst_ena      = true,
 440                .hburst_start   = 72,               .hburst_len         = 34,
 441                .vburst_start_f1 = 9,               .vburst_end_f1      = 240,
 442                .vburst_start_f2 = 10,              .vburst_end_f2      = 240,
 443                .vburst_start_f3 = 9,               .vburst_end_f3      = 240,
 444                .vburst_start_f4 = 10,              .vburst_end_f4      = 240,
 445
 446                /* desired 3.5800000 actual 3.5800000 clock 107.52 */
 447                .dda1_inc       =    135,
 448                .dda2_inc       =  20800,           .dda2_size          =  27456,
 449                .dda3_inc       =      0,           .dda3_size          =      0,
 450                .sc_reset       = TV_SC_RESET_EVERY_4,
 451                .pal_burst      = false,
 452
 453                .composite_levels = &ntsc_m_levels_composite,
 454                .composite_color = &ntsc_m_csc_composite,
 455                .svideo_levels  = &ntsc_m_levels_svideo,
 456                .svideo_color = &ntsc_m_csc_svideo,
 457
 458                .filter_table = filter_table,
 459        },
 460        {
 461                .name           = "NTSC-443",
 462                .clock          = 108000,
 463                .refresh        = 29970,
 464                .oversample     = TV_OVERSAMPLE_8X,
 465                .component_only = 0,
 466                /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 4.43MHz */
 467                .hsync_end      = 64,               .hblank_end         = 124,
 468                .hblank_start   = 836,              .htotal             = 857,
 469
 470                .progressive    = false,            .trilevel_sync = false,
 471
 472                .vsync_start_f1 = 6,                .vsync_start_f2     = 7,
 473                .vsync_len      = 6,
 474
 475                .veq_ena        = true,             .veq_start_f1       = 0,
 476                .veq_start_f2   = 1,                .veq_len            = 18,
 477
 478                .vi_end_f1      = 20,               .vi_end_f2          = 21,
 479                .nbr_end        = 240,
 480
 481                .burst_ena      = true,
 482                .hburst_start   = 72,               .hburst_len         = 34,
 483                .vburst_start_f1 = 9,               .vburst_end_f1      = 240,
 484                .vburst_start_f2 = 10,              .vburst_end_f2      = 240,
 485                .vburst_start_f3 = 9,               .vburst_end_f3      = 240,
 486                .vburst_start_f4 = 10,              .vburst_end_f4      = 240,
 487
 488                /* desired 4.4336180 actual 4.4336180 clock 107.52 */
 489                .dda1_inc       =    168,
 490                .dda2_inc       =   4093,       .dda2_size      =  27456,
 491                .dda3_inc       =    310,       .dda3_size      =    525,
 492                .sc_reset   = TV_SC_RESET_NEVER,
 493                .pal_burst  = false,
 494
 495                .composite_levels = &ntsc_m_levels_composite,
 496                .composite_color = &ntsc_m_csc_composite,
 497                .svideo_levels  = &ntsc_m_levels_svideo,
 498                .svideo_color = &ntsc_m_csc_svideo,
 499
 500                .filter_table = filter_table,
 501        },
 502        {
 503                .name           = "NTSC-J",
 504                .clock          = 108000,
 505                .refresh        = 29970,
 506                .oversample     = TV_OVERSAMPLE_8X,
 507                .component_only = 0,
 508
 509                /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
 510                .hsync_end      = 64,               .hblank_end         = 124,
 511                .hblank_start = 836,        .htotal             = 857,
 512
 513                .progressive    = false,    .trilevel_sync = false,
 514
 515                .vsync_start_f1 = 6,        .vsync_start_f2     = 7,
 516                .vsync_len      = 6,
 517
 518                .veq_ena        = true,             .veq_start_f1       = 0,
 519                .veq_start_f2 = 1,          .veq_len            = 18,
 520
 521                .vi_end_f1      = 20,               .vi_end_f2          = 21,
 522                .nbr_end        = 240,
 523
 524                .burst_ena      = true,
 525                .hburst_start   = 72,               .hburst_len         = 34,
 526                .vburst_start_f1 = 9,               .vburst_end_f1      = 240,
 527                .vburst_start_f2 = 10,              .vburst_end_f2      = 240,
 528                .vburst_start_f3 = 9,               .vburst_end_f3      = 240,
 529                .vburst_start_f4 = 10,              .vburst_end_f4      = 240,
 530
 531                /* desired 3.5800000 actual 3.5800000 clock 107.52 */
 532                .dda1_inc       =    135,
 533                .dda2_inc       =  20800,           .dda2_size          =  27456,
 534                .dda3_inc       =      0,           .dda3_size          =      0,
 535                .sc_reset       = TV_SC_RESET_EVERY_4,
 536                .pal_burst      = false,
 537
 538                .composite_levels = &ntsc_j_levels_composite,
 539                .composite_color = &ntsc_j_csc_composite,
 540                .svideo_levels  = &ntsc_j_levels_svideo,
 541                .svideo_color = &ntsc_j_csc_svideo,
 542
 543                .filter_table = filter_table,
 544        },
 545        {
 546                .name           = "PAL-M",
 547                .clock          = 108000,
 548                .refresh        = 29970,
 549                .oversample     = TV_OVERSAMPLE_8X,
 550                .component_only = 0,
 551
 552                /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
 553                .hsync_end      = 64,             .hblank_end           = 124,
 554                .hblank_start = 836,      .htotal               = 857,
 555
 556                .progressive    = false,            .trilevel_sync = false,
 557
 558                .vsync_start_f1 = 6,                .vsync_start_f2     = 7,
 559                .vsync_len      = 6,
 560
 561                .veq_ena        = true,             .veq_start_f1       = 0,
 562                .veq_start_f2   = 1,                .veq_len            = 18,
 563
 564                .vi_end_f1      = 20,               .vi_end_f2          = 21,
 565                .nbr_end        = 240,
 566
 567                .burst_ena      = true,
 568                .hburst_start   = 72,               .hburst_len         = 34,
 569                .vburst_start_f1 = 9,               .vburst_end_f1      = 240,
 570                .vburst_start_f2 = 10,              .vburst_end_f2      = 240,
 571                .vburst_start_f3 = 9,               .vburst_end_f3      = 240,
 572                .vburst_start_f4 = 10,              .vburst_end_f4      = 240,
 573
 574                /* desired 3.5800000 actual 3.5800000 clock 107.52 */
 575                .dda1_inc       =    135,
 576                .dda2_inc       =  16704,           .dda2_size          =  27456,
 577                .dda3_inc       =      0,           .dda3_size          =      0,
 578                .sc_reset       = TV_SC_RESET_EVERY_8,
 579                .pal_burst  = true,
 580
 581                .composite_levels = &pal_m_levels_composite,
 582                .composite_color = &pal_m_csc_composite,
 583                .svideo_levels  = &pal_m_levels_svideo,
 584                .svideo_color = &pal_m_csc_svideo,
 585
 586                .filter_table = filter_table,
 587        },
 588        {
 589                /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
 590                .name       = "PAL-N",
 591                .clock          = 108000,
 592                .refresh        = 25000,
 593                .oversample     = TV_OVERSAMPLE_8X,
 594                .component_only = 0,
 595
 596                .hsync_end      = 64,               .hblank_end         = 128,
 597                .hblank_start = 844,        .htotal             = 863,
 598
 599                .progressive  = false,    .trilevel_sync = false,
 600
 601
 602                .vsync_start_f1 = 6,       .vsync_start_f2      = 7,
 603                .vsync_len      = 6,
 604
 605                .veq_ena        = true,             .veq_start_f1       = 0,
 606                .veq_start_f2   = 1,                .veq_len            = 18,
 607
 608                .vi_end_f1      = 24,               .vi_end_f2          = 25,
 609                .nbr_end        = 286,
 610
 611                .burst_ena      = true,
 612                .hburst_start = 73,                 .hburst_len         = 34,
 613                .vburst_start_f1 = 8,       .vburst_end_f1      = 285,
 614                .vburst_start_f2 = 8,       .vburst_end_f2      = 286,
 615                .vburst_start_f3 = 9,       .vburst_end_f3      = 286,
 616                .vburst_start_f4 = 9,       .vburst_end_f4      = 285,
 617
 618
 619                /* desired 4.4336180 actual 4.4336180 clock 107.52 */
 620                .dda1_inc       =    135,
 621                .dda2_inc       =  23578,       .dda2_size      =  27648,
 622                .dda3_inc       =    134,       .dda3_size      =    625,
 623                .sc_reset   = TV_SC_RESET_EVERY_8,
 624                .pal_burst  = true,
 625
 626                .composite_levels = &pal_n_levels_composite,
 627                .composite_color = &pal_n_csc_composite,
 628                .svideo_levels  = &pal_n_levels_svideo,
 629                .svideo_color = &pal_n_csc_svideo,
 630
 631                .filter_table = filter_table,
 632        },
 633        {
 634                /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
 635                .name       = "PAL",
 636                .clock          = 108000,
 637                .refresh        = 25000,
 638                .oversample     = TV_OVERSAMPLE_8X,
 639                .component_only = 0,
 640
 641                .hsync_end      = 64,               .hblank_end         = 142,
 642                .hblank_start   = 844,      .htotal             = 863,
 643
 644                .progressive    = false,    .trilevel_sync = false,
 645
 646                .vsync_start_f1 = 5,        .vsync_start_f2     = 6,
 647                .vsync_len      = 5,
 648
 649                .veq_ena        = true,             .veq_start_f1       = 0,
 650                .veq_start_f2   = 1,        .veq_len            = 15,
 651
 652                .vi_end_f1      = 24,               .vi_end_f2          = 25,
 653                .nbr_end        = 286,
 654
 655                .burst_ena      = true,
 656                .hburst_start   = 73,               .hburst_len         = 32,
 657                .vburst_start_f1 = 8,               .vburst_end_f1      = 285,
 658                .vburst_start_f2 = 8,               .vburst_end_f2      = 286,
 659                .vburst_start_f3 = 9,               .vburst_end_f3      = 286,
 660                .vburst_start_f4 = 9,               .vburst_end_f4      = 285,
 661
 662                /* desired 4.4336180 actual 4.4336180 clock 107.52 */
 663                .dda1_inc       =    168,
 664                .dda2_inc       =   4122,       .dda2_size      =  27648,
 665                .dda3_inc       =     67,       .dda3_size      =    625,
 666                .sc_reset   = TV_SC_RESET_EVERY_8,
 667                .pal_burst  = true,
 668
 669                .composite_levels = &pal_levels_composite,
 670                .composite_color = &pal_csc_composite,
 671                .svideo_levels  = &pal_levels_svideo,
 672                .svideo_color = &pal_csc_svideo,
 673
 674                .filter_table = filter_table,
 675        },
 676        {
 677                .name       = "480p@59.94Hz",
 678                .clock  = 107520,
 679                .refresh        = 59940,
 680                .oversample     = TV_OVERSAMPLE_4X,
 681                .component_only = 1,
 682
 683                .hsync_end      = 64,               .hblank_end         = 122,
 684                .hblank_start   = 842,              .htotal             = 857,
 685
 686                .progressive    = true,.trilevel_sync = false,
 687
 688                .vsync_start_f1 = 12,               .vsync_start_f2     = 12,
 689                .vsync_len      = 12,
 690
 691                .veq_ena        = false,
 692
 693                .vi_end_f1      = 44,               .vi_end_f2          = 44,
 694                .nbr_end        = 479,
 695
 696                .burst_ena      = false,
 697
 698                .filter_table = filter_table,
 699        },
 700        {
 701                .name       = "480p@60Hz",
 702                .clock  = 107520,
 703                .refresh        = 60000,
 704                .oversample     = TV_OVERSAMPLE_4X,
 705                .component_only = 1,
 706
 707                .hsync_end      = 64,               .hblank_end         = 122,
 708                .hblank_start   = 842,              .htotal             = 856,
 709
 710                .progressive    = true,.trilevel_sync = false,
 711
 712                .vsync_start_f1 = 12,               .vsync_start_f2     = 12,
 713                .vsync_len      = 12,
 714
 715                .veq_ena        = false,
 716
 717                .vi_end_f1      = 44,               .vi_end_f2          = 44,
 718                .nbr_end        = 479,
 719
 720                .burst_ena      = false,
 721
 722                .filter_table = filter_table,
 723        },
 724        {
 725                .name       = "576p",
 726                .clock  = 107520,
 727                .refresh        = 50000,
 728                .oversample     = TV_OVERSAMPLE_4X,
 729                .component_only = 1,
 730
 731                .hsync_end      = 64,               .hblank_end         = 139,
 732                .hblank_start   = 859,              .htotal             = 863,
 733
 734                .progressive    = true,         .trilevel_sync = false,
 735
 736                .vsync_start_f1 = 10,               .vsync_start_f2     = 10,
 737                .vsync_len      = 10,
 738
 739                .veq_ena        = false,
 740
 741                .vi_end_f1      = 48,               .vi_end_f2          = 48,
 742                .nbr_end        = 575,
 743
 744                .burst_ena      = false,
 745
 746                .filter_table = filter_table,
 747        },
 748        {
 749                .name       = "720p@60Hz",
 750                .clock          = 148800,
 751                .refresh        = 60000,
 752                .oversample     = TV_OVERSAMPLE_2X,
 753                .component_only = 1,
 754
 755                .hsync_end      = 80,               .hblank_end         = 300,
 756                .hblank_start   = 1580,             .htotal             = 1649,
 757
 758                .progressive    = true,             .trilevel_sync = true,
 759
 760                .vsync_start_f1 = 10,               .vsync_start_f2     = 10,
 761                .vsync_len      = 10,
 762
 763                .veq_ena        = false,
 764
 765                .vi_end_f1      = 29,               .vi_end_f2          = 29,
 766                .nbr_end        = 719,
 767
 768                .burst_ena      = false,
 769
 770                .filter_table = filter_table,
 771        },
 772        {
 773                .name       = "720p@59.94Hz",
 774                .clock          = 148800,
 775                .refresh        = 59940,
 776                .oversample     = TV_OVERSAMPLE_2X,
 777                .component_only = 1,
 778
 779                .hsync_end      = 80,               .hblank_end         = 300,
 780                .hblank_start   = 1580,             .htotal             = 1651,
 781
 782                .progressive    = true,             .trilevel_sync = true,
 783
 784                .vsync_start_f1 = 10,               .vsync_start_f2     = 10,
 785                .vsync_len      = 10,
 786
 787                .veq_ena        = false,
 788
 789                .vi_end_f1      = 29,               .vi_end_f2          = 29,
 790                .nbr_end        = 719,
 791
 792                .burst_ena      = false,
 793
 794                .filter_table = filter_table,
 795        },
 796        {
 797                .name       = "720p@50Hz",
 798                .clock          = 148800,
 799                .refresh        = 50000,
 800                .oversample     = TV_OVERSAMPLE_2X,
 801                .component_only = 1,
 802
 803                .hsync_end      = 80,               .hblank_end         = 300,
 804                .hblank_start   = 1580,             .htotal             = 1979,
 805
 806                .progressive    = true,                 .trilevel_sync = true,
 807
 808                .vsync_start_f1 = 10,               .vsync_start_f2     = 10,
 809                .vsync_len      = 10,
 810
 811                .veq_ena        = false,
 812
 813                .vi_end_f1      = 29,               .vi_end_f2          = 29,
 814                .nbr_end        = 719,
 815
 816                .burst_ena      = false,
 817
 818                .filter_table = filter_table,
 819                .max_srcw = 800
 820        },
 821        {
 822                .name       = "1080i@50Hz",
 823                .clock          = 148800,
 824                .refresh        = 25000,
 825                .oversample     = TV_OVERSAMPLE_2X,
 826                .component_only = 1,
 827
 828                .hsync_end      = 88,               .hblank_end         = 235,
 829                .hblank_start   = 2155,             .htotal             = 2639,
 830
 831                .progressive    = false,            .trilevel_sync = true,
 832
 833                .vsync_start_f1 = 4,              .vsync_start_f2     = 5,
 834                .vsync_len      = 10,
 835
 836                .veq_ena        = true,             .veq_start_f1       = 4,
 837                .veq_start_f2   = 4,        .veq_len            = 10,
 838
 839
 840                .vi_end_f1      = 21,           .vi_end_f2          = 22,
 841                .nbr_end        = 539,
 842
 843                .burst_ena      = false,
 844
 845                .filter_table = filter_table,
 846        },
 847        {
 848                .name       = "1080i@60Hz",
 849                .clock          = 148800,
 850                .refresh        = 30000,
 851                .oversample     = TV_OVERSAMPLE_2X,
 852                .component_only = 1,
 853
 854                .hsync_end      = 88,               .hblank_end         = 235,
 855                .hblank_start   = 2155,             .htotal             = 2199,
 856
 857                .progressive    = false,            .trilevel_sync = true,
 858
 859                .vsync_start_f1 = 4,               .vsync_start_f2     = 5,
 860                .vsync_len      = 10,
 861
 862                .veq_ena        = true,             .veq_start_f1       = 4,
 863                .veq_start_f2   = 4,                .veq_len            = 10,
 864
 865
 866                .vi_end_f1      = 21,               .vi_end_f2          = 22,
 867                .nbr_end        = 539,
 868
 869                .burst_ena      = false,
 870
 871                .filter_table = filter_table,
 872        },
 873        {
 874                .name       = "1080i@59.94Hz",
 875                .clock          = 148800,
 876                .refresh        = 29970,
 877                .oversample     = TV_OVERSAMPLE_2X,
 878                .component_only = 1,
 879
 880                .hsync_end      = 88,               .hblank_end         = 235,
 881                .hblank_start   = 2155,             .htotal             = 2201,
 882
 883                .progressive    = false,            .trilevel_sync = true,
 884
 885                .vsync_start_f1 = 4,            .vsync_start_f2    = 5,
 886                .vsync_len      = 10,
 887
 888                .veq_ena        = true,             .veq_start_f1       = 4,
 889                .veq_start_f2 = 4,                  .veq_len = 10,
 890
 891
 892                .vi_end_f1      = 21,           .vi_end_f2              = 22,
 893                .nbr_end        = 539,
 894
 895                .burst_ena      = false,
 896
 897                .filter_table = filter_table,
 898        },
 899};
 900
 901static struct intel_tv *enc_to_intel_tv(struct drm_encoder *encoder)
 902{
 903        return container_of(encoder, struct intel_tv, base.base);
 904}
 905
 906static struct intel_tv *intel_attached_tv(struct drm_connector *connector)
 907{
 908        return container_of(intel_attached_encoder(connector),
 909                            struct intel_tv,
 910                            base);
 911}
 912
 913static void
 914intel_tv_dpms(struct drm_encoder *encoder, int mode)
 915{
 916        struct drm_device *dev = encoder->dev;
 917        struct drm_i915_private *dev_priv = dev->dev_private;
 918
 919        switch(mode) {
 920        case DRM_MODE_DPMS_ON:
 921                I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE);
 922                break;
 923        case DRM_MODE_DPMS_STANDBY:
 924        case DRM_MODE_DPMS_SUSPEND:
 925        case DRM_MODE_DPMS_OFF:
 926                I915_WRITE(TV_CTL, I915_READ(TV_CTL) & ~TV_ENC_ENABLE);
 927                break;
 928        }
 929}
 930
 931static const struct tv_mode *
 932intel_tv_mode_lookup(const char *tv_format)
 933{
 934        int i;
 935
 936        for (i = 0; i < sizeof(tv_modes) / sizeof (tv_modes[0]); i++) {
 937                const struct tv_mode *tv_mode = &tv_modes[i];
 938
 939                if (!strcmp(tv_format, tv_mode->name))
 940                        return tv_mode;
 941        }
 942        return NULL;
 943}
 944
 945static const struct tv_mode *
 946intel_tv_mode_find(struct intel_tv *intel_tv)
 947{
 948        return intel_tv_mode_lookup(intel_tv->tv_format);
 949}
 950
 951static enum drm_mode_status
 952intel_tv_mode_valid(struct drm_connector *connector,
 953                    struct drm_display_mode *mode)
 954{
 955        struct intel_tv *intel_tv = intel_attached_tv(connector);
 956        const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
 957
 958        /* Ensure TV refresh is close to desired refresh */
 959        if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode) * 1000)
 960                                < 1000)
 961                return MODE_OK;
 962
 963        return MODE_CLOCK_RANGE;
 964}
 965
 966
 967static bool
 968intel_tv_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
 969                    struct drm_display_mode *adjusted_mode)
 970{
 971        struct drm_device *dev = encoder->dev;
 972        struct drm_mode_config *drm_config = &dev->mode_config;
 973        struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
 974        const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
 975        struct drm_encoder *other_encoder;
 976
 977        if (!tv_mode)
 978                return false;
 979
 980        /* FIXME: lock encoder list */
 981        list_for_each_entry(other_encoder, &drm_config->encoder_list, head) {
 982                if (other_encoder != encoder &&
 983                    other_encoder->crtc == encoder->crtc)
 984                        return false;
 985        }
 986
 987        adjusted_mode->clock = tv_mode->clock;
 988        return true;
 989}
 990
 991static void
 992intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 993                  struct drm_display_mode *adjusted_mode)
 994{
 995        struct drm_device *dev = encoder->dev;
 996        struct drm_i915_private *dev_priv = dev->dev_private;
 997        struct drm_crtc *crtc = encoder->crtc;
 998        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 999        struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
1000        const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
1001        u32 tv_ctl;
1002        u32 hctl1, hctl2, hctl3;
1003        u32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
1004        u32 scctl1, scctl2, scctl3;
1005        int i, j;
1006        const struct video_levels *video_levels;
1007        const struct color_conversion *color_conversion;
1008        bool burst_ena;
1009        int pipe = intel_crtc->pipe;
1010
1011        if (!tv_mode)
1012                return; /* can't happen (mode_prepare prevents this) */
1013
1014        tv_ctl = I915_READ(TV_CTL);
1015        tv_ctl &= TV_CTL_SAVE;
1016
1017        switch (intel_tv->type) {
1018        default:
1019        case DRM_MODE_CONNECTOR_Unknown:
1020        case DRM_MODE_CONNECTOR_Composite:
1021                tv_ctl |= TV_ENC_OUTPUT_COMPOSITE;
1022                video_levels = tv_mode->composite_levels;
1023                color_conversion = tv_mode->composite_color;
1024                burst_ena = tv_mode->burst_ena;
1025                break;
1026        case DRM_MODE_CONNECTOR_Component:
1027                tv_ctl |= TV_ENC_OUTPUT_COMPONENT;
1028                video_levels = &component_levels;
1029                if (tv_mode->burst_ena)
1030                        color_conversion = &sdtv_csc_yprpb;
1031                else
1032                        color_conversion = &hdtv_csc_yprpb;
1033                burst_ena = false;
1034                break;
1035        case DRM_MODE_CONNECTOR_SVIDEO:
1036                tv_ctl |= TV_ENC_OUTPUT_SVIDEO;
1037                video_levels = tv_mode->svideo_levels;
1038                color_conversion = tv_mode->svideo_color;
1039                burst_ena = tv_mode->burst_ena;
1040                break;
1041        }
1042        hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) |
1043                (tv_mode->htotal << TV_HTOTAL_SHIFT);
1044
1045        hctl2 = (tv_mode->hburst_start << 16) |
1046                (tv_mode->hburst_len << TV_HBURST_LEN_SHIFT);
1047
1048        if (burst_ena)
1049                hctl2 |= TV_BURST_ENA;
1050
1051        hctl3 = (tv_mode->hblank_start << TV_HBLANK_START_SHIFT) |
1052                (tv_mode->hblank_end << TV_HBLANK_END_SHIFT);
1053
1054        vctl1 = (tv_mode->nbr_end << TV_NBR_END_SHIFT) |
1055                (tv_mode->vi_end_f1 << TV_VI_END_F1_SHIFT) |
1056                (tv_mode->vi_end_f2 << TV_VI_END_F2_SHIFT);
1057
1058        vctl2 = (tv_mode->vsync_len << TV_VSYNC_LEN_SHIFT) |
1059                (tv_mode->vsync_start_f1 << TV_VSYNC_START_F1_SHIFT) |
1060                (tv_mode->vsync_start_f2 << TV_VSYNC_START_F2_SHIFT);
1061
1062        vctl3 = (tv_mode->veq_len << TV_VEQ_LEN_SHIFT) |
1063                (tv_mode->veq_start_f1 << TV_VEQ_START_F1_SHIFT) |
1064                (tv_mode->veq_start_f2 << TV_VEQ_START_F2_SHIFT);
1065
1066        if (tv_mode->veq_ena)
1067                vctl3 |= TV_EQUAL_ENA;
1068
1069        vctl4 = (tv_mode->vburst_start_f1 << TV_VBURST_START_F1_SHIFT) |
1070                (tv_mode->vburst_end_f1 << TV_VBURST_END_F1_SHIFT);
1071
1072        vctl5 = (tv_mode->vburst_start_f2 << TV_VBURST_START_F2_SHIFT) |
1073                (tv_mode->vburst_end_f2 << TV_VBURST_END_F2_SHIFT);
1074
1075        vctl6 = (tv_mode->vburst_start_f3 << TV_VBURST_START_F3_SHIFT) |
1076                (tv_mode->vburst_end_f3 << TV_VBURST_END_F3_SHIFT);
1077
1078        vctl7 = (tv_mode->vburst_start_f4 << TV_VBURST_START_F4_SHIFT) |
1079                (tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT);
1080
1081        if (intel_crtc->pipe == 1)
1082                tv_ctl |= TV_ENC_PIPEB_SELECT;
1083        tv_ctl |= tv_mode->oversample;
1084
1085        if (tv_mode->progressive)
1086                tv_ctl |= TV_PROGRESSIVE;
1087        if (tv_mode->trilevel_sync)
1088                tv_ctl |= TV_TRILEVEL_SYNC;
1089        if (tv_mode->pal_burst)
1090                tv_ctl |= TV_PAL_BURST;
1091
1092        scctl1 = 0;
1093        if (tv_mode->dda1_inc)
1094                scctl1 |= TV_SC_DDA1_EN;
1095        if (tv_mode->dda2_inc)
1096                scctl1 |= TV_SC_DDA2_EN;
1097        if (tv_mode->dda3_inc)
1098                scctl1 |= TV_SC_DDA3_EN;
1099        scctl1 |= tv_mode->sc_reset;
1100        if (video_levels)
1101                scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT;
1102        scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT;
1103
1104        scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
1105                tv_mode->dda2_inc << TV_SCDDA2_INC_SHIFT;
1106
1107        scctl3 = tv_mode->dda3_size << TV_SCDDA3_SIZE_SHIFT |
1108                tv_mode->dda3_inc << TV_SCDDA3_INC_SHIFT;
1109
1110        /* Enable two fixes for the chips that need them. */
1111        if (dev->pci_device < 0x2772)
1112                tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
1113
1114        I915_WRITE(TV_H_CTL_1, hctl1);
1115        I915_WRITE(TV_H_CTL_2, hctl2);
1116        I915_WRITE(TV_H_CTL_3, hctl3);
1117        I915_WRITE(TV_V_CTL_1, vctl1);
1118        I915_WRITE(TV_V_CTL_2, vctl2);
1119        I915_WRITE(TV_V_CTL_3, vctl3);
1120        I915_WRITE(TV_V_CTL_4, vctl4);
1121        I915_WRITE(TV_V_CTL_5, vctl5);
1122        I915_WRITE(TV_V_CTL_6, vctl6);
1123        I915_WRITE(TV_V_CTL_7, vctl7);
1124        I915_WRITE(TV_SC_CTL_1, scctl1);
1125        I915_WRITE(TV_SC_CTL_2, scctl2);
1126        I915_WRITE(TV_SC_CTL_3, scctl3);
1127
1128        if (color_conversion) {
1129                I915_WRITE(TV_CSC_Y, (color_conversion->ry << 16) |
1130                           color_conversion->gy);
1131                I915_WRITE(TV_CSC_Y2,(color_conversion->by << 16) |
1132                           color_conversion->ay);
1133                I915_WRITE(TV_CSC_U, (color_conversion->ru << 16) |
1134                           color_conversion->gu);
1135                I915_WRITE(TV_CSC_U2, (color_conversion->bu << 16) |
1136                           color_conversion->au);
1137                I915_WRITE(TV_CSC_V, (color_conversion->rv << 16) |
1138                           color_conversion->gv);
1139                I915_WRITE(TV_CSC_V2, (color_conversion->bv << 16) |
1140                           color_conversion->av);
1141        }
1142
1143        if (INTEL_INFO(dev)->gen >= 4)
1144                I915_WRITE(TV_CLR_KNOBS, 0x00404000);
1145        else
1146                I915_WRITE(TV_CLR_KNOBS, 0x00606000);
1147
1148        if (video_levels)
1149                I915_WRITE(TV_CLR_LEVEL,
1150                           ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
1151                            (video_levels->blank << TV_BLANK_LEVEL_SHIFT)));
1152        {
1153                int pipeconf_reg = PIPECONF(pipe);
1154                int dspcntr_reg = DSPCNTR(intel_crtc->plane);
1155                int pipeconf = I915_READ(pipeconf_reg);
1156                int dspcntr = I915_READ(dspcntr_reg);
1157                int dspbase_reg = DSPADDR(intel_crtc->plane);
1158                int xpos = 0x0, ypos = 0x0;
1159                unsigned int xsize, ysize;
1160                /* Pipe must be off here */
1161                I915_WRITE(dspcntr_reg, dspcntr & ~DISPLAY_PLANE_ENABLE);
1162                /* Flush the plane changes */
1163                I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
1164
1165                /* Wait for vblank for the disable to take effect */
1166                if (IS_GEN2(dev))
1167                        intel_wait_for_vblank(dev, intel_crtc->pipe);
1168
1169                I915_WRITE(pipeconf_reg, pipeconf & ~PIPECONF_ENABLE);
1170                /* Wait for vblank for the disable to take effect. */
1171                intel_wait_for_pipe_off(dev, intel_crtc->pipe);
1172
1173                /* Filter ctl must be set before TV_WIN_SIZE */
1174                I915_WRITE(TV_FILTER_CTL_1, TV_AUTO_SCALE);
1175                xsize = tv_mode->hblank_start - tv_mode->hblank_end;
1176                if (tv_mode->progressive)
1177                        ysize = tv_mode->nbr_end + 1;
1178                else
1179                        ysize = 2*tv_mode->nbr_end + 1;
1180
1181                xpos += intel_tv->margin[TV_MARGIN_LEFT];
1182                ypos += intel_tv->margin[TV_MARGIN_TOP];
1183                xsize -= (intel_tv->margin[TV_MARGIN_LEFT] +
1184                          intel_tv->margin[TV_MARGIN_RIGHT]);
1185                ysize -= (intel_tv->margin[TV_MARGIN_TOP] +
1186                          intel_tv->margin[TV_MARGIN_BOTTOM]);
1187                I915_WRITE(TV_WIN_POS, (xpos<<16)|ypos);
1188                I915_WRITE(TV_WIN_SIZE, (xsize<<16)|ysize);
1189
1190                I915_WRITE(pipeconf_reg, pipeconf);
1191                I915_WRITE(dspcntr_reg, dspcntr);
1192                /* Flush the plane changes */
1193                I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
1194        }
1195
1196        j = 0;
1197        for (i = 0; i < 60; i++)
1198                I915_WRITE(TV_H_LUMA_0 + (i<<2), tv_mode->filter_table[j++]);
1199        for (i = 0; i < 60; i++)
1200                I915_WRITE(TV_H_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]);
1201        for (i = 0; i < 43; i++)
1202                I915_WRITE(TV_V_LUMA_0 + (i<<2), tv_mode->filter_table[j++]);
1203        for (i = 0; i < 43; i++)
1204                I915_WRITE(TV_V_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]);
1205        I915_WRITE(TV_DAC, I915_READ(TV_DAC) & TV_DAC_SAVE);
1206        I915_WRITE(TV_CTL, tv_ctl);
1207}
1208
1209static const struct drm_display_mode reported_modes[] = {
1210        {
1211                .name = "NTSC 480i",
1212                .clock = 107520,
1213                .hdisplay = 1280,
1214                .hsync_start = 1368,
1215                .hsync_end = 1496,
1216                .htotal = 1712,
1217
1218                .vdisplay = 1024,
1219                .vsync_start = 1027,
1220                .vsync_end = 1034,
1221                .vtotal = 1104,
1222                .type = DRM_MODE_TYPE_DRIVER,
1223        },
1224};
1225
1226/**
1227 * Detects TV presence by checking for load.
1228 *
1229 * Requires that the current pipe's DPLL is active.
1230
1231 * \return true if TV is connected.
1232 * \return false if TV is disconnected.
1233 */
1234static int
1235intel_tv_detect_type (struct intel_tv *intel_tv,
1236                      struct drm_connector *connector)
1237{
1238        struct drm_encoder *encoder = &intel_tv->base.base;
1239        struct drm_device *dev = encoder->dev;
1240        struct drm_i915_private *dev_priv = dev->dev_private;
1241        unsigned long irqflags;
1242        u32 tv_ctl, save_tv_ctl;
1243        u32 tv_dac, save_tv_dac;
1244        int type;
1245
1246        /* Disable TV interrupts around load detect or we'll recurse */
1247        if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
1248                spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
1249                i915_disable_pipestat(dev_priv, 0,
1250                                      PIPE_HOTPLUG_INTERRUPT_ENABLE |
1251                                      PIPE_HOTPLUG_TV_INTERRUPT_ENABLE);
1252                spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
1253        }
1254
1255        save_tv_dac = tv_dac = I915_READ(TV_DAC);
1256        save_tv_ctl = tv_ctl = I915_READ(TV_CTL);
1257
1258        /* Poll for TV detection */
1259        tv_ctl &= ~(TV_ENC_ENABLE | TV_TEST_MODE_MASK);
1260        tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
1261
1262        tv_dac &= ~(TVDAC_SENSE_MASK | DAC_A_MASK | DAC_B_MASK | DAC_C_MASK);
1263        tv_dac |= (TVDAC_STATE_CHG_EN |
1264                   TVDAC_A_SENSE_CTL |
1265                   TVDAC_B_SENSE_CTL |
1266                   TVDAC_C_SENSE_CTL |
1267                   DAC_CTL_OVERRIDE |
1268                   DAC_A_0_7_V |
1269                   DAC_B_0_7_V |
1270                   DAC_C_0_7_V);
1271
1272        I915_WRITE(TV_CTL, tv_ctl);
1273        I915_WRITE(TV_DAC, tv_dac);
1274        POSTING_READ(TV_DAC);
1275
1276        intel_wait_for_vblank(intel_tv->base.base.dev,
1277                              to_intel_crtc(intel_tv->base.base.crtc)->pipe);
1278
1279        type = -1;
1280        if (wait_for((tv_dac = I915_READ(TV_DAC)) & TVDAC_STATE_CHG, 20) == 0) {
1281                DRM_DEBUG_KMS("TV detected: %x, %x\n", tv_ctl, tv_dac);
1282                /*
1283                 *  A B C
1284                 *  0 1 1 Composite
1285                 *  1 0 X svideo
1286                 *  0 0 0 Component
1287                 */
1288                if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
1289                        DRM_DEBUG_KMS("Detected Composite TV connection\n");
1290                        type = DRM_MODE_CONNECTOR_Composite;
1291                } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
1292                        DRM_DEBUG_KMS("Detected S-Video TV connection\n");
1293                        type = DRM_MODE_CONNECTOR_SVIDEO;
1294                } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
1295                        DRM_DEBUG_KMS("Detected Component TV connection\n");
1296                        type = DRM_MODE_CONNECTOR_Component;
1297                } else {
1298                        DRM_DEBUG_KMS("Unrecognised TV connection\n");
1299                }
1300        }
1301
1302        I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
1303        I915_WRITE(TV_CTL, save_tv_ctl);
1304
1305        /* Restore interrupt config */
1306        if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
1307                spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
1308                i915_enable_pipestat(dev_priv, 0,
1309                                     PIPE_HOTPLUG_INTERRUPT_ENABLE |
1310                                     PIPE_HOTPLUG_TV_INTERRUPT_ENABLE);
1311                spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
1312        }
1313
1314        return type;
1315}
1316
1317/*
1318 * Here we set accurate tv format according to connector type
1319 * i.e Component TV should not be assigned by NTSC or PAL
1320 */
1321static void intel_tv_find_better_format(struct drm_connector *connector)
1322{
1323        struct intel_tv *intel_tv = intel_attached_tv(connector);
1324        const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
1325        int i;
1326
1327        if ((intel_tv->type == DRM_MODE_CONNECTOR_Component) ==
1328                tv_mode->component_only)
1329                return;
1330
1331
1332        for (i = 0; i < sizeof(tv_modes) / sizeof(*tv_modes); i++) {
1333                tv_mode = tv_modes + i;
1334
1335                if ((intel_tv->type == DRM_MODE_CONNECTOR_Component) ==
1336                        tv_mode->component_only)
1337                        break;
1338        }
1339
1340        intel_tv->tv_format = tv_mode->name;
1341        drm_connector_property_set_value(connector,
1342                connector->dev->mode_config.tv_mode_property, i);
1343}
1344
1345/**
1346 * Detect the TV connection.
1347 *
1348 * Currently this always returns CONNECTOR_STATUS_UNKNOWN, as we need to be sure
1349 * we have a pipe programmed in order to probe the TV.
1350 */
1351static enum drm_connector_status
1352intel_tv_detect(struct drm_connector *connector, bool force)
1353{
1354        struct drm_display_mode mode;
1355        struct intel_tv *intel_tv = intel_attached_tv(connector);
1356        int type;
1357
1358        mode = reported_modes[0];
1359        drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V);
1360
1361        if (intel_tv->base.base.crtc && intel_tv->base.base.crtc->enabled) {
1362                type = intel_tv_detect_type(intel_tv, connector);
1363        } else if (force) {
1364                struct drm_crtc *crtc;
1365                int dpms_mode;
1366
1367                crtc = intel_get_load_detect_pipe(&intel_tv->base, connector,
1368                                                  &mode, &dpms_mode);
1369                if (crtc) {
1370                        type = intel_tv_detect_type(intel_tv, connector);
1371                        intel_release_load_detect_pipe(&intel_tv->base, connector,
1372                                                       dpms_mode);
1373                } else
1374                        return connector_status_unknown;
1375        } else
1376                return connector->status;
1377
1378        if (type < 0)
1379                return connector_status_disconnected;
1380
1381        intel_tv->type = type;
1382        intel_tv_find_better_format(connector);
1383
1384        return connector_status_connected;
1385}
1386
1387static const struct input_res {
1388        const char *name;
1389        int w, h;
1390} input_res_table[] = {
1391        {"640x480", 640, 480},
1392        {"800x600", 800, 600},
1393        {"1024x768", 1024, 768},
1394        {"1280x1024", 1280, 1024},
1395        {"848x480", 848, 480},
1396        {"1280x720", 1280, 720},
1397        {"1920x1080", 1920, 1080},
1398};
1399
1400/*
1401 * Chose preferred mode  according to line number of TV format
1402 */
1403static void
1404intel_tv_chose_preferred_modes(struct drm_connector *connector,
1405                               struct drm_display_mode *mode_ptr)
1406{
1407        struct intel_tv *intel_tv = intel_attached_tv(connector);
1408        const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
1409
1410        if (tv_mode->nbr_end < 480 && mode_ptr->vdisplay == 480)
1411                mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
1412        else if (tv_mode->nbr_end > 480) {
1413                if (tv_mode->progressive == true && tv_mode->nbr_end < 720) {
1414                        if (mode_ptr->vdisplay == 720)
1415                                mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
1416                } else if (mode_ptr->vdisplay == 1080)
1417                                mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
1418        }
1419}
1420
1421/**
1422 * Stub get_modes function.
1423 *
1424 * This should probably return a set of fixed modes, unless we can figure out
1425 * how to probe modes off of TV connections.
1426 */
1427
1428static int
1429intel_tv_get_modes(struct drm_connector *connector)
1430{
1431        struct drm_display_mode *mode_ptr;
1432        struct intel_tv *intel_tv = intel_attached_tv(connector);
1433        const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
1434        int j, count = 0;
1435        u64 tmp;
1436
1437        for (j = 0; j < ARRAY_SIZE(input_res_table);
1438             j++) {
1439                const struct input_res *input = &input_res_table[j];
1440                unsigned int hactive_s = input->w;
1441                unsigned int vactive_s = input->h;
1442
1443                if (tv_mode->max_srcw && input->w > tv_mode->max_srcw)
1444                        continue;
1445
1446                if (input->w > 1024 && (!tv_mode->progressive
1447                                        && !tv_mode->component_only))
1448                        continue;
1449
1450                mode_ptr = drm_mode_create(connector->dev);
1451                if (!mode_ptr)
1452                        continue;
1453                strncpy(mode_ptr->name, input->name, DRM_DISPLAY_MODE_LEN);
1454
1455                mode_ptr->hdisplay = hactive_s;
1456                mode_ptr->hsync_start = hactive_s + 1;
1457                mode_ptr->hsync_end = hactive_s + 64;
1458                if (mode_ptr->hsync_end <= mode_ptr->hsync_start)
1459                        mode_ptr->hsync_end = mode_ptr->hsync_start + 1;
1460                mode_ptr->htotal = hactive_s + 96;
1461
1462                mode_ptr->vdisplay = vactive_s;
1463                mode_ptr->vsync_start = vactive_s + 1;
1464                mode_ptr->vsync_end = vactive_s + 32;
1465                if (mode_ptr->vsync_end <= mode_ptr->vsync_start)
1466                        mode_ptr->vsync_end = mode_ptr->vsync_start  + 1;
1467                mode_ptr->vtotal = vactive_s + 33;
1468
1469                tmp = (u64) tv_mode->refresh * mode_ptr->vtotal;
1470                tmp *= mode_ptr->htotal;
1471                tmp = div_u64(tmp, 1000000);
1472                mode_ptr->clock = (int) tmp;
1473
1474                mode_ptr->type = DRM_MODE_TYPE_DRIVER;
1475                intel_tv_chose_preferred_modes(connector, mode_ptr);
1476                drm_mode_probed_add(connector, mode_ptr);
1477                count++;
1478        }
1479
1480        return count;
1481}
1482
1483static void
1484intel_tv_destroy (struct drm_connector *connector)
1485{
1486        drm_sysfs_connector_remove(connector);
1487        drm_connector_cleanup(connector);
1488        kfree(connector);
1489}
1490
1491
1492static int
1493intel_tv_set_property(struct drm_connector *connector, struct drm_property *property,
1494                      uint64_t val)
1495{
1496        struct drm_device *dev = connector->dev;
1497        struct intel_tv *intel_tv = intel_attached_tv(connector);
1498        struct drm_crtc *crtc = intel_tv->base.base.crtc;
1499        int ret = 0;
1500        bool changed = false;
1501
1502        ret = drm_connector_property_set_value(connector, property, val);
1503        if (ret < 0)
1504                goto out;
1505
1506        if (property == dev->mode_config.tv_left_margin_property &&
1507                intel_tv->margin[TV_MARGIN_LEFT] != val) {
1508                intel_tv->margin[TV_MARGIN_LEFT] = val;
1509                changed = true;
1510        } else if (property == dev->mode_config.tv_right_margin_property &&
1511                intel_tv->margin[TV_MARGIN_RIGHT] != val) {
1512                intel_tv->margin[TV_MARGIN_RIGHT] = val;
1513                changed = true;
1514        } else if (property == dev->mode_config.tv_top_margin_property &&
1515                intel_tv->margin[TV_MARGIN_TOP] != val) {
1516                intel_tv->margin[TV_MARGIN_TOP] = val;
1517                changed = true;
1518        } else if (property == dev->mode_config.tv_bottom_margin_property &&
1519                intel_tv->margin[TV_MARGIN_BOTTOM] != val) {
1520                intel_tv->margin[TV_MARGIN_BOTTOM] = val;
1521                changed = true;
1522        } else if (property == dev->mode_config.tv_mode_property) {
1523                if (val >= ARRAY_SIZE(tv_modes)) {
1524                        ret = -EINVAL;
1525                        goto out;
1526                }
1527                if (!strcmp(intel_tv->tv_format, tv_modes[val].name))
1528                        goto out;
1529
1530                intel_tv->tv_format = tv_modes[val].name;
1531                changed = true;
1532        } else {
1533                ret = -EINVAL;
1534                goto out;
1535        }
1536
1537        if (changed && crtc)
1538                drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
1539                                crtc->y, crtc->fb);
1540out:
1541        return ret;
1542}
1543
1544static const struct drm_encoder_helper_funcs intel_tv_helper_funcs = {
1545        .dpms = intel_tv_dpms,
1546        .mode_fixup = intel_tv_mode_fixup,
1547        .prepare = intel_encoder_prepare,
1548        .mode_set = intel_tv_mode_set,
1549        .commit = intel_encoder_commit,
1550};
1551
1552static const struct drm_connector_funcs intel_tv_connector_funcs = {
1553        .dpms = drm_helper_connector_dpms,
1554        .detect = intel_tv_detect,
1555        .destroy = intel_tv_destroy,
1556        .set_property = intel_tv_set_property,
1557        .fill_modes = drm_helper_probe_single_connector_modes,
1558};
1559
1560static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = {
1561        .mode_valid = intel_tv_mode_valid,
1562        .get_modes = intel_tv_get_modes,
1563        .best_encoder = intel_best_encoder,
1564};
1565
1566static const struct drm_encoder_funcs intel_tv_enc_funcs = {
1567        .destroy = intel_encoder_destroy,
1568};
1569
1570/*
1571 * Enumerate the child dev array parsed from VBT to check whether
1572 * the integrated TV is present.
1573 * If it is present, return 1.
1574 * If it is not present, return false.
1575 * If no child dev is parsed from VBT, it assumes that the TV is present.
1576 */
1577static int tv_is_present_in_vbt(struct drm_device *dev)
1578{
1579        struct drm_i915_private *dev_priv = dev->dev_private;
1580        struct child_device_config *p_child;
1581        int i, ret;
1582
1583        if (!dev_priv->child_dev_num)
1584                return 1;
1585
1586        ret = 0;
1587        for (i = 0; i < dev_priv->child_dev_num; i++) {
1588                p_child = dev_priv->child_dev + i;
1589                /*
1590                 * If the device type is not TV, continue.
1591                 */
1592                if (p_child->device_type != DEVICE_TYPE_INT_TV &&
1593                        p_child->device_type != DEVICE_TYPE_TV)
1594                        continue;
1595                /* Only when the addin_offset is non-zero, it is regarded
1596                 * as present.
1597                 */
1598                if (p_child->addin_offset) {
1599                        ret = 1;
1600                        break;
1601                }
1602        }
1603        return ret;
1604}
1605
1606void
1607intel_tv_init(struct drm_device *dev)
1608{
1609        struct drm_i915_private *dev_priv = dev->dev_private;
1610        struct drm_connector *connector;
1611        struct intel_tv *intel_tv;
1612        struct intel_encoder *intel_encoder;
1613        struct intel_connector *intel_connector;
1614        u32 tv_dac_on, tv_dac_off, save_tv_dac;
1615        char *tv_format_names[ARRAY_SIZE(tv_modes)];
1616        int i, initial_mode = 0;
1617
1618        if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
1619                return;
1620
1621        if (!tv_is_present_in_vbt(dev)) {
1622                DRM_DEBUG_KMS("Integrated TV is not present.\n");
1623                return;
1624        }
1625        /* Even if we have an encoder we may not have a connector */
1626        if (!dev_priv->int_tv_support)
1627                return;
1628
1629        /*
1630         * Sanity check the TV output by checking to see if the
1631         * DAC register holds a value
1632         */
1633        save_tv_dac = I915_READ(TV_DAC);
1634
1635        I915_WRITE(TV_DAC, save_tv_dac | TVDAC_STATE_CHG_EN);
1636        tv_dac_on = I915_READ(TV_DAC);
1637
1638        I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
1639        tv_dac_off = I915_READ(TV_DAC);
1640
1641        I915_WRITE(TV_DAC, save_tv_dac);
1642
1643        /*
1644         * If the register does not hold the state change enable
1645         * bit, (either as a 0 or a 1), assume it doesn't really
1646         * exist
1647         */
1648        if ((tv_dac_on & TVDAC_STATE_CHG_EN) == 0 ||
1649            (tv_dac_off & TVDAC_STATE_CHG_EN) != 0)
1650                return;
1651
1652        intel_tv = kzalloc(sizeof(struct intel_tv), GFP_KERNEL);
1653        if (!intel_tv) {
1654                return;
1655        }
1656
1657        intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
1658        if (!intel_connector) {
1659                kfree(intel_tv);
1660                return;
1661        }
1662
1663        intel_encoder = &intel_tv->base;
1664        connector = &intel_connector->base;
1665
1666        /* The documentation, for the older chipsets at least, recommend
1667         * using a polling method rather than hotplug detection for TVs.
1668         * This is because in order to perform the hotplug detection, the PLLs
1669         * for the TV must be kept alive increasing power drain and starving
1670         * bandwidth from other encoders. Notably for instance, it causes
1671         * pipe underruns on Crestline when this encoder is supposedly idle.
1672         *
1673         * More recent chipsets favour HDMI rather than integrated S-Video.
1674         */
1675        connector->polled = DRM_CONNECTOR_POLL_CONNECT;
1676
1677        drm_connector_init(dev, connector, &intel_tv_connector_funcs,
1678                           DRM_MODE_CONNECTOR_SVIDEO);
1679
1680        drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs,
1681                         DRM_MODE_ENCODER_TVDAC);
1682
1683        intel_connector_attach_encoder(intel_connector, intel_encoder);
1684        intel_encoder->type = INTEL_OUTPUT_TVOUT;
1685        intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
1686        intel_encoder->clone_mask = (1 << INTEL_TV_CLONE_BIT);
1687        intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1));
1688        intel_encoder->base.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
1689        intel_tv->type = DRM_MODE_CONNECTOR_Unknown;
1690
1691        /* BIOS margin values */
1692        intel_tv->margin[TV_MARGIN_LEFT] = 54;
1693        intel_tv->margin[TV_MARGIN_TOP] = 36;
1694        intel_tv->margin[TV_MARGIN_RIGHT] = 46;
1695        intel_tv->margin[TV_MARGIN_BOTTOM] = 37;
1696
1697        intel_tv->tv_format = tv_modes[initial_mode].name;
1698
1699        drm_encoder_helper_add(&intel_encoder->base, &intel_tv_helper_funcs);
1700        drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs);
1701        connector->interlace_allowed = false;
1702        connector->doublescan_allowed = false;
1703
1704        /* Create TV properties then attach current values */
1705        for (i = 0; i < ARRAY_SIZE(tv_modes); i++)
1706                tv_format_names[i] = (char *)tv_modes[i].name;
1707        drm_mode_create_tv_properties(dev,
1708                                      ARRAY_SIZE(tv_modes),
1709                                      tv_format_names);
1710
1711        drm_connector_attach_property(connector, dev->mode_config.tv_mode_property,
1712                                   initial_mode);
1713        drm_connector_attach_property(connector,
1714                                   dev->mode_config.tv_left_margin_property,
1715                                   intel_tv->margin[TV_MARGIN_LEFT]);
1716        drm_connector_attach_property(connector,
1717                                   dev->mode_config.tv_top_margin_property,
1718                                   intel_tv->margin[TV_MARGIN_TOP]);
1719        drm_connector_attach_property(connector,
1720                                   dev->mode_config.tv_right_margin_property,
1721                                   intel_tv->margin[TV_MARGIN_RIGHT]);
1722        drm_connector_attach_property(connector,
1723                                   dev->mode_config.tv_bottom_margin_property,
1724                                   intel_tv->margin[TV_MARGIN_BOTTOM]);
1725        drm_sysfs_connector_add(connector);
1726}
1727