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
1010        if (!tv_mode)
1011                return; /* can't happen (mode_prepare prevents this) */
1012
1013        tv_ctl = I915_READ(TV_CTL);
1014        tv_ctl &= TV_CTL_SAVE;
1015
1016        switch (intel_tv->type) {
1017        default:
1018        case DRM_MODE_CONNECTOR_Unknown:
1019        case DRM_MODE_CONNECTOR_Composite:
1020                tv_ctl |= TV_ENC_OUTPUT_COMPOSITE;
1021                video_levels = tv_mode->composite_levels;
1022                color_conversion = tv_mode->composite_color;
1023                burst_ena = tv_mode->burst_ena;
1024                break;
1025        case DRM_MODE_CONNECTOR_Component:
1026                tv_ctl |= TV_ENC_OUTPUT_COMPONENT;
1027                video_levels = &component_levels;
1028                if (tv_mode->burst_ena)
1029                        color_conversion = &sdtv_csc_yprpb;
1030                else
1031                        color_conversion = &hdtv_csc_yprpb;
1032                burst_ena = false;
1033                break;
1034        case DRM_MODE_CONNECTOR_SVIDEO:
1035                tv_ctl |= TV_ENC_OUTPUT_SVIDEO;
1036                video_levels = tv_mode->svideo_levels;
1037                color_conversion = tv_mode->svideo_color;
1038                burst_ena = tv_mode->burst_ena;
1039                break;
1040        }
1041        hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) |
1042                (tv_mode->htotal << TV_HTOTAL_SHIFT);
1043
1044        hctl2 = (tv_mode->hburst_start << 16) |
1045                (tv_mode->hburst_len << TV_HBURST_LEN_SHIFT);
1046
1047        if (burst_ena)
1048                hctl2 |= TV_BURST_ENA;
1049
1050        hctl3 = (tv_mode->hblank_start << TV_HBLANK_START_SHIFT) |
1051                (tv_mode->hblank_end << TV_HBLANK_END_SHIFT);
1052
1053        vctl1 = (tv_mode->nbr_end << TV_NBR_END_SHIFT) |
1054                (tv_mode->vi_end_f1 << TV_VI_END_F1_SHIFT) |
1055                (tv_mode->vi_end_f2 << TV_VI_END_F2_SHIFT);
1056
1057        vctl2 = (tv_mode->vsync_len << TV_VSYNC_LEN_SHIFT) |
1058                (tv_mode->vsync_start_f1 << TV_VSYNC_START_F1_SHIFT) |
1059                (tv_mode->vsync_start_f2 << TV_VSYNC_START_F2_SHIFT);
1060
1061        vctl3 = (tv_mode->veq_len << TV_VEQ_LEN_SHIFT) |
1062                (tv_mode->veq_start_f1 << TV_VEQ_START_F1_SHIFT) |
1063                (tv_mode->veq_start_f2 << TV_VEQ_START_F2_SHIFT);
1064
1065        if (tv_mode->veq_ena)
1066                vctl3 |= TV_EQUAL_ENA;
1067
1068        vctl4 = (tv_mode->vburst_start_f1 << TV_VBURST_START_F1_SHIFT) |
1069                (tv_mode->vburst_end_f1 << TV_VBURST_END_F1_SHIFT);
1070
1071        vctl5 = (tv_mode->vburst_start_f2 << TV_VBURST_START_F2_SHIFT) |
1072                (tv_mode->vburst_end_f2 << TV_VBURST_END_F2_SHIFT);
1073
1074        vctl6 = (tv_mode->vburst_start_f3 << TV_VBURST_START_F3_SHIFT) |
1075                (tv_mode->vburst_end_f3 << TV_VBURST_END_F3_SHIFT);
1076
1077        vctl7 = (tv_mode->vburst_start_f4 << TV_VBURST_START_F4_SHIFT) |
1078                (tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT);
1079
1080        if (intel_crtc->pipe == 1)
1081                tv_ctl |= TV_ENC_PIPEB_SELECT;
1082        tv_ctl |= tv_mode->oversample;
1083
1084        if (tv_mode->progressive)
1085                tv_ctl |= TV_PROGRESSIVE;
1086        if (tv_mode->trilevel_sync)
1087                tv_ctl |= TV_TRILEVEL_SYNC;
1088        if (tv_mode->pal_burst)
1089                tv_ctl |= TV_PAL_BURST;
1090
1091        scctl1 = 0;
1092        if (tv_mode->dda1_inc)
1093                scctl1 |= TV_SC_DDA1_EN;
1094        if (tv_mode->dda2_inc)
1095                scctl1 |= TV_SC_DDA2_EN;
1096        if (tv_mode->dda3_inc)
1097                scctl1 |= TV_SC_DDA3_EN;
1098        scctl1 |= tv_mode->sc_reset;
1099        if (video_levels)
1100                scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT;
1101        scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT;
1102
1103        scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
1104                tv_mode->dda2_inc << TV_SCDDA2_INC_SHIFT;
1105
1106        scctl3 = tv_mode->dda3_size << TV_SCDDA3_SIZE_SHIFT |
1107                tv_mode->dda3_inc << TV_SCDDA3_INC_SHIFT;
1108
1109        /* Enable two fixes for the chips that need them. */
1110        if (dev->pci_device < 0x2772)
1111                tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
1112
1113        I915_WRITE(TV_H_CTL_1, hctl1);
1114        I915_WRITE(TV_H_CTL_2, hctl2);
1115        I915_WRITE(TV_H_CTL_3, hctl3);
1116        I915_WRITE(TV_V_CTL_1, vctl1);
1117        I915_WRITE(TV_V_CTL_2, vctl2);
1118        I915_WRITE(TV_V_CTL_3, vctl3);
1119        I915_WRITE(TV_V_CTL_4, vctl4);
1120        I915_WRITE(TV_V_CTL_5, vctl5);
1121        I915_WRITE(TV_V_CTL_6, vctl6);
1122        I915_WRITE(TV_V_CTL_7, vctl7);
1123        I915_WRITE(TV_SC_CTL_1, scctl1);
1124        I915_WRITE(TV_SC_CTL_2, scctl2);
1125        I915_WRITE(TV_SC_CTL_3, scctl3);
1126
1127        if (color_conversion) {
1128                I915_WRITE(TV_CSC_Y, (color_conversion->ry << 16) |
1129                           color_conversion->gy);
1130                I915_WRITE(TV_CSC_Y2,(color_conversion->by << 16) |
1131                           color_conversion->ay);
1132                I915_WRITE(TV_CSC_U, (color_conversion->ru << 16) |
1133                           color_conversion->gu);
1134                I915_WRITE(TV_CSC_U2, (color_conversion->bu << 16) |
1135                           color_conversion->au);
1136                I915_WRITE(TV_CSC_V, (color_conversion->rv << 16) |
1137                           color_conversion->gv);
1138                I915_WRITE(TV_CSC_V2, (color_conversion->bv << 16) |
1139                           color_conversion->av);
1140        }
1141
1142        if (INTEL_INFO(dev)->gen >= 4)
1143                I915_WRITE(TV_CLR_KNOBS, 0x00404000);
1144        else
1145                I915_WRITE(TV_CLR_KNOBS, 0x00606000);
1146
1147        if (video_levels)
1148                I915_WRITE(TV_CLR_LEVEL,
1149                           ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
1150                            (video_levels->blank << TV_BLANK_LEVEL_SHIFT)));
1151        {
1152                int pipeconf_reg = (intel_crtc->pipe == 0) ?
1153                        PIPEACONF : PIPEBCONF;
1154                int dspcntr_reg = (intel_crtc->plane == 0) ?
1155                        DSPACNTR : DSPBCNTR;
1156                int pipeconf = I915_READ(pipeconf_reg);
1157                int dspcntr = I915_READ(dspcntr_reg);
1158                int dspbase_reg = (intel_crtc->plane == 0) ?
1159                        DSPAADDR : DSPBADDR;
1160                int xpos = 0x0, ypos = 0x0;
1161                unsigned int xsize, ysize;
1162                /* Pipe must be off here */
1163                I915_WRITE(dspcntr_reg, dspcntr & ~DISPLAY_PLANE_ENABLE);
1164                /* Flush the plane changes */
1165                I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
1166
1167                /* Wait for vblank for the disable to take effect */
1168                if (IS_GEN2(dev))
1169                        intel_wait_for_vblank(dev, intel_crtc->pipe);
1170
1171                I915_WRITE(pipeconf_reg, pipeconf & ~PIPECONF_ENABLE);
1172                /* Wait for vblank for the disable to take effect. */
1173                intel_wait_for_pipe_off(dev, intel_crtc->pipe);
1174
1175                /* Filter ctl must be set before TV_WIN_SIZE */
1176                I915_WRITE(TV_FILTER_CTL_1, TV_AUTO_SCALE);
1177                xsize = tv_mode->hblank_start - tv_mode->hblank_end;
1178                if (tv_mode->progressive)
1179                        ysize = tv_mode->nbr_end + 1;
1180                else
1181                        ysize = 2*tv_mode->nbr_end + 1;
1182
1183                xpos += intel_tv->margin[TV_MARGIN_LEFT];
1184                ypos += intel_tv->margin[TV_MARGIN_TOP];
1185                xsize -= (intel_tv->margin[TV_MARGIN_LEFT] +
1186                          intel_tv->margin[TV_MARGIN_RIGHT]);
1187                ysize -= (intel_tv->margin[TV_MARGIN_TOP] +
1188                          intel_tv->margin[TV_MARGIN_BOTTOM]);
1189                I915_WRITE(TV_WIN_POS, (xpos<<16)|ypos);
1190                I915_WRITE(TV_WIN_SIZE, (xsize<<16)|ysize);
1191
1192                I915_WRITE(pipeconf_reg, pipeconf);
1193                I915_WRITE(dspcntr_reg, dspcntr);
1194                /* Flush the plane changes */
1195                I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
1196        }
1197
1198        j = 0;
1199        for (i = 0; i < 60; i++)
1200                I915_WRITE(TV_H_LUMA_0 + (i<<2), tv_mode->filter_table[j++]);
1201        for (i = 0; i < 60; i++)
1202                I915_WRITE(TV_H_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]);
1203        for (i = 0; i < 43; i++)
1204                I915_WRITE(TV_V_LUMA_0 + (i<<2), tv_mode->filter_table[j++]);
1205        for (i = 0; i < 43; i++)
1206                I915_WRITE(TV_V_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]);
1207        I915_WRITE(TV_DAC, I915_READ(TV_DAC) & TV_DAC_SAVE);
1208        I915_WRITE(TV_CTL, tv_ctl);
1209}
1210
1211static const struct drm_display_mode reported_modes[] = {
1212        {
1213                .name = "NTSC 480i",
1214                .clock = 107520,
1215                .hdisplay = 1280,
1216                .hsync_start = 1368,
1217                .hsync_end = 1496,
1218                .htotal = 1712,
1219
1220                .vdisplay = 1024,
1221                .vsync_start = 1027,
1222                .vsync_end = 1034,
1223                .vtotal = 1104,
1224                .type = DRM_MODE_TYPE_DRIVER,
1225        },
1226};
1227
1228/**
1229 * Detects TV presence by checking for load.
1230 *
1231 * Requires that the current pipe's DPLL is active.
1232
1233 * \return true if TV is connected.
1234 * \return false if TV is disconnected.
1235 */
1236static int
1237intel_tv_detect_type (struct intel_tv *intel_tv,
1238                      struct drm_connector *connector)
1239{
1240        struct drm_encoder *encoder = &intel_tv->base.base;
1241        struct drm_device *dev = encoder->dev;
1242        struct drm_i915_private *dev_priv = dev->dev_private;
1243        unsigned long irqflags;
1244        u32 tv_ctl, save_tv_ctl;
1245        u32 tv_dac, save_tv_dac;
1246        int type;
1247
1248        /* Disable TV interrupts around load detect or we'll recurse */
1249        if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
1250                spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
1251                i915_disable_pipestat(dev_priv, 0,
1252                                      PIPE_HOTPLUG_INTERRUPT_ENABLE |
1253                                      PIPE_HOTPLUG_TV_INTERRUPT_ENABLE);
1254                spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
1255        }
1256
1257        save_tv_dac = tv_dac = I915_READ(TV_DAC);
1258        save_tv_ctl = tv_ctl = I915_READ(TV_CTL);
1259
1260        /* Poll for TV detection */
1261        tv_ctl &= ~(TV_ENC_ENABLE | TV_TEST_MODE_MASK);
1262        tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
1263
1264        tv_dac &= ~(TVDAC_SENSE_MASK | DAC_A_MASK | DAC_B_MASK | DAC_C_MASK);
1265        tv_dac |= (TVDAC_STATE_CHG_EN |
1266                   TVDAC_A_SENSE_CTL |
1267                   TVDAC_B_SENSE_CTL |
1268                   TVDAC_C_SENSE_CTL |
1269                   DAC_CTL_OVERRIDE |
1270                   DAC_A_0_7_V |
1271                   DAC_B_0_7_V |
1272                   DAC_C_0_7_V);
1273
1274        I915_WRITE(TV_CTL, tv_ctl);
1275        I915_WRITE(TV_DAC, tv_dac);
1276        POSTING_READ(TV_DAC);
1277
1278        intel_wait_for_vblank(intel_tv->base.base.dev,
1279                              to_intel_crtc(intel_tv->base.base.crtc)->pipe);
1280
1281        type = -1;
1282        if (wait_for((tv_dac = I915_READ(TV_DAC)) & TVDAC_STATE_CHG, 20) == 0) {
1283                DRM_DEBUG_KMS("TV detected: %x, %x\n", tv_ctl, tv_dac);
1284                /*
1285                 *  A B C
1286                 *  0 1 1 Composite
1287                 *  1 0 X svideo
1288                 *  0 0 0 Component
1289                 */
1290                if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
1291                        DRM_DEBUG_KMS("Detected Composite TV connection\n");
1292                        type = DRM_MODE_CONNECTOR_Composite;
1293                } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
1294                        DRM_DEBUG_KMS("Detected S-Video TV connection\n");
1295                        type = DRM_MODE_CONNECTOR_SVIDEO;
1296                } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
1297                        DRM_DEBUG_KMS("Detected Component TV connection\n");
1298                        type = DRM_MODE_CONNECTOR_Component;
1299                } else {
1300                        DRM_DEBUG_KMS("Unrecognised TV connection\n");
1301                }
1302        }
1303
1304        I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
1305        I915_WRITE(TV_CTL, save_tv_ctl);
1306
1307        /* Restore interrupt config */
1308        if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
1309                spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
1310                i915_enable_pipestat(dev_priv, 0,
1311                                     PIPE_HOTPLUG_INTERRUPT_ENABLE |
1312                                     PIPE_HOTPLUG_TV_INTERRUPT_ENABLE);
1313                spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
1314        }
1315
1316        return type;
1317}
1318
1319/*
1320 * Here we set accurate tv format according to connector type
1321 * i.e Component TV should not be assigned by NTSC or PAL
1322 */
1323static void intel_tv_find_better_format(struct drm_connector *connector)
1324{
1325        struct intel_tv *intel_tv = intel_attached_tv(connector);
1326        const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
1327        int i;
1328
1329        if ((intel_tv->type == DRM_MODE_CONNECTOR_Component) ==
1330                tv_mode->component_only)
1331                return;
1332
1333
1334        for (i = 0; i < sizeof(tv_modes) / sizeof(*tv_modes); i++) {
1335                tv_mode = tv_modes + i;
1336
1337                if ((intel_tv->type == DRM_MODE_CONNECTOR_Component) ==
1338                        tv_mode->component_only)
1339                        break;
1340        }
1341
1342        intel_tv->tv_format = tv_mode->name;
1343        drm_connector_property_set_value(connector,
1344                connector->dev->mode_config.tv_mode_property, i);
1345}
1346
1347/**
1348 * Detect the TV connection.
1349 *
1350 * Currently this always returns CONNECTOR_STATUS_UNKNOWN, as we need to be sure
1351 * we have a pipe programmed in order to probe the TV.
1352 */
1353static enum drm_connector_status
1354intel_tv_detect(struct drm_connector *connector, bool force)
1355{
1356        struct drm_display_mode mode;
1357        struct intel_tv *intel_tv = intel_attached_tv(connector);
1358        int type;
1359
1360        mode = reported_modes[0];
1361        drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V);
1362
1363        if (intel_tv->base.base.crtc && intel_tv->base.base.crtc->enabled) {
1364                type = intel_tv_detect_type(intel_tv, connector);
1365        } else if (force) {
1366                struct drm_crtc *crtc;
1367                int dpms_mode;
1368
1369                crtc = intel_get_load_detect_pipe(&intel_tv->base, connector,
1370                                                  &mode, &dpms_mode);
1371                if (crtc) {
1372                        type = intel_tv_detect_type(intel_tv, connector);
1373                        intel_release_load_detect_pipe(&intel_tv->base, connector,
1374                                                       dpms_mode);
1375                } else
1376                        return connector_status_unknown;
1377        } else
1378                return connector->status;
1379
1380        if (type < 0)
1381                return connector_status_disconnected;
1382
1383        intel_tv_find_better_format(connector);
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 =
1676                DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
1677
1678        drm_connector_init(dev, connector, &intel_tv_connector_funcs,
1679                           DRM_MODE_CONNECTOR_SVIDEO);
1680
1681        drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs,
1682                         DRM_MODE_ENCODER_TVDAC);
1683
1684        intel_connector_attach_encoder(intel_connector, intel_encoder);
1685        intel_encoder->type = INTEL_OUTPUT_TVOUT;
1686        intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
1687        intel_encoder->clone_mask = (1 << INTEL_TV_CLONE_BIT);
1688        intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1));
1689        intel_encoder->base.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
1690        intel_tv->type = DRM_MODE_CONNECTOR_Unknown;
1691
1692        /* BIOS margin values */
1693        intel_tv->margin[TV_MARGIN_LEFT] = 54;
1694        intel_tv->margin[TV_MARGIN_TOP] = 36;
1695        intel_tv->margin[TV_MARGIN_RIGHT] = 46;
1696        intel_tv->margin[TV_MARGIN_BOTTOM] = 37;
1697
1698        intel_tv->tv_format = tv_modes[initial_mode].name;
1699
1700        drm_encoder_helper_add(&intel_encoder->base, &intel_tv_helper_funcs);
1701        drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs);
1702        connector->interlace_allowed = false;
1703        connector->doublescan_allowed = false;
1704
1705        /* Create TV properties then attach current values */
1706        for (i = 0; i < ARRAY_SIZE(tv_modes); i++)
1707                tv_format_names[i] = (char *)tv_modes[i].name;
1708        drm_mode_create_tv_properties(dev,
1709                                      ARRAY_SIZE(tv_modes),
1710                                      tv_format_names);
1711
1712        drm_connector_attach_property(connector, dev->mode_config.tv_mode_property,
1713                                   initial_mode);
1714        drm_connector_attach_property(connector,
1715                                   dev->mode_config.tv_left_margin_property,
1716                                   intel_tv->margin[TV_MARGIN_LEFT]);
1717        drm_connector_attach_property(connector,
1718                                   dev->mode_config.tv_top_margin_property,
1719                                   intel_tv->margin[TV_MARGIN_TOP]);
1720        drm_connector_attach_property(connector,
1721                                   dev->mode_config.tv_right_margin_property,
1722                                   intel_tv->margin[TV_MARGIN_RIGHT]);
1723        drm_connector_attach_property(connector,
1724                                   dev->mode_config.tv_bottom_margin_property,
1725                                   intel_tv->margin[TV_MARGIN_BOTTOM]);
1726        drm_sysfs_connector_add(connector);
1727}
1728