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