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