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