2 * Copyright © 2006-2008 Intel Corporation
3 * Jesse Barnes <jesse.barnes@intel.com>
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:
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
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.
25 * Eric Anholt <eric@anholt.net>
30 * Integrated TV-out support for the 915GM and 945GM.
34 #include <drm/drm_atomic_helper.h>
35 #include <drm/drm_crtc.h>
36 #include <drm/drm_edid.h>
37 #include "intel_drv.h"
38 #include <drm/i915_drm.h>
42 TV_MARGIN_LEFT
, TV_MARGIN_TOP
,
43 TV_MARGIN_RIGHT
, TV_MARGIN_BOTTOM
47 struct intel_encoder base
;
57 struct color_conversion
{
63 static const u32 filter_table
[] = {
64 0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
65 0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
66 0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,
67 0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,
68 0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,
69 0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,
70 0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,
71 0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,
72 0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,
73 0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,
74 0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,
75 0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,
76 0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,
77 0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,
78 0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,
79 0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
80 0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
81 0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,
82 0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,
83 0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,
84 0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,
85 0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,
86 0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,
87 0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,
88 0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,
89 0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,
90 0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,
91 0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,
92 0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,
93 0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,
94 0x36403000, 0x2D002CC0, 0x30003640, 0x2D0036C0,
95 0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,
96 0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,
97 0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,
98 0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,
99 0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,
100 0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,
101 0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,
102 0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,
103 0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,
104 0x28003100, 0x28002F00, 0x00003100, 0x36403000,
105 0x2D002CC0, 0x30003640, 0x2D0036C0,
106 0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,
107 0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,
108 0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,
109 0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,
110 0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,
111 0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,
112 0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,
113 0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,
114 0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,
115 0x28003100, 0x28002F00, 0x00003100,
119 * Color conversion values have 3 separate fixed point formats:
121 * 10 bit fields (ay, au)
122 * 1.9 fixed point (b.bbbbbbbbb)
123 * 11 bit fields (ry, by, ru, gu, gv)
124 * exp.mantissa (ee.mmmmmmmmm)
125 * ee = 00 = 10^-1 (0.mmmmmmmmm)
126 * ee = 01 = 10^-2 (0.0mmmmmmmmm)
127 * ee = 10 = 10^-3 (0.00mmmmmmmmm)
128 * ee = 11 = 10^-4 (0.000mmmmmmmmm)
129 * 12 bit fields (gy, rv, bu)
130 * exp.mantissa (eee.mmmmmmmmm)
131 * eee = 000 = 10^-1 (0.mmmmmmmmm)
132 * eee = 001 = 10^-2 (0.0mmmmmmmmm)
133 * eee = 010 = 10^-3 (0.00mmmmmmmmm)
134 * eee = 011 = 10^-4 (0.000mmmmmmmmm)
135 * eee = 100 = reserved
136 * eee = 101 = reserved
137 * eee = 110 = reserved
138 * eee = 111 = 10^0 (m.mmmmmmmm) (only usable for 1.0 representation)
140 * Saturation and contrast are 8 bits, with their own representation:
141 * 8 bit field (saturation, contrast)
142 * exp.mantissa (ee.mmmmmm)
143 * ee = 00 = 10^-1 (0.mmmmmm)
144 * ee = 01 = 10^0 (m.mmmmm)
145 * ee = 10 = 10^1 (mm.mmmm)
146 * ee = 11 = 10^2 (mmm.mmm)
148 * Simple conversion function:
151 * float_to_csc_11(float f)
164 * for (exp = 0; exp < 3 && f < 0.5; exp++)
166 * mant = (f * (1 << 9) + 0.5);
167 * if (mant >= (1 << 9))
168 * mant = (1 << 9) - 1;
170 * ret = (exp << 9) | mant;
176 * Behold, magic numbers! If we plant them they might grow a big
177 * s-video cable to the sky... or something.
179 * Pre-converted to appropriate hex value.
183 * PAL & NTSC values for composite & s-video connections
185 static const struct color_conversion ntsc_m_csc_composite
= {
186 .ry
= 0x0332, .gy
= 0x012d, .by
= 0x07d3, .ay
= 0x0104,
187 .ru
= 0x0733, .gu
= 0x052d, .bu
= 0x05c7, .au
= 0x0200,
188 .rv
= 0x0340, .gv
= 0x030c, .bv
= 0x06d0, .av
= 0x0200,
191 static const struct video_levels ntsc_m_levels_composite
= {
192 .blank
= 225, .black
= 267, .burst
= 113,
195 static const struct color_conversion ntsc_m_csc_svideo
= {
196 .ry
= 0x0332, .gy
= 0x012d, .by
= 0x07d3, .ay
= 0x0133,
197 .ru
= 0x076a, .gu
= 0x0564, .bu
= 0x030d, .au
= 0x0200,
198 .rv
= 0x037a, .gv
= 0x033d, .bv
= 0x06f6, .av
= 0x0200,
201 static const struct video_levels ntsc_m_levels_svideo
= {
202 .blank
= 266, .black
= 316, .burst
= 133,
205 static const struct color_conversion ntsc_j_csc_composite
= {
206 .ry
= 0x0332, .gy
= 0x012d, .by
= 0x07d3, .ay
= 0x0119,
207 .ru
= 0x074c, .gu
= 0x0546, .bu
= 0x05ec, .au
= 0x0200,
208 .rv
= 0x035a, .gv
= 0x0322, .bv
= 0x06e1, .av
= 0x0200,
211 static const struct video_levels ntsc_j_levels_composite
= {
212 .blank
= 225, .black
= 225, .burst
= 113,
215 static const struct color_conversion ntsc_j_csc_svideo
= {
216 .ry
= 0x0332, .gy
= 0x012d, .by
= 0x07d3, .ay
= 0x014c,
217 .ru
= 0x0788, .gu
= 0x0581, .bu
= 0x0322, .au
= 0x0200,
218 .rv
= 0x0399, .gv
= 0x0356, .bv
= 0x070a, .av
= 0x0200,
221 static const struct video_levels ntsc_j_levels_svideo
= {
222 .blank
= 266, .black
= 266, .burst
= 133,
225 static const struct color_conversion pal_csc_composite
= {
226 .ry
= 0x0332, .gy
= 0x012d, .by
= 0x07d3, .ay
= 0x0113,
227 .ru
= 0x0745, .gu
= 0x053f, .bu
= 0x05e1, .au
= 0x0200,
228 .rv
= 0x0353, .gv
= 0x031c, .bv
= 0x06dc, .av
= 0x0200,
231 static const struct video_levels pal_levels_composite
= {
232 .blank
= 237, .black
= 237, .burst
= 118,
235 static const struct color_conversion pal_csc_svideo
= {
236 .ry
= 0x0332, .gy
= 0x012d, .by
= 0x07d3, .ay
= 0x0145,
237 .ru
= 0x0780, .gu
= 0x0579, .bu
= 0x031c, .au
= 0x0200,
238 .rv
= 0x0390, .gv
= 0x034f, .bv
= 0x0705, .av
= 0x0200,
241 static const struct video_levels pal_levels_svideo
= {
242 .blank
= 280, .black
= 280, .burst
= 139,
245 static const struct color_conversion pal_m_csc_composite
= {
246 .ry
= 0x0332, .gy
= 0x012d, .by
= 0x07d3, .ay
= 0x0104,
247 .ru
= 0x0733, .gu
= 0x052d, .bu
= 0x05c7, .au
= 0x0200,
248 .rv
= 0x0340, .gv
= 0x030c, .bv
= 0x06d0, .av
= 0x0200,
251 static const struct video_levels pal_m_levels_composite
= {
252 .blank
= 225, .black
= 267, .burst
= 113,
255 static const struct color_conversion pal_m_csc_svideo
= {
256 .ry
= 0x0332, .gy
= 0x012d, .by
= 0x07d3, .ay
= 0x0133,
257 .ru
= 0x076a, .gu
= 0x0564, .bu
= 0x030d, .au
= 0x0200,
258 .rv
= 0x037a, .gv
= 0x033d, .bv
= 0x06f6, .av
= 0x0200,
261 static const struct video_levels pal_m_levels_svideo
= {
262 .blank
= 266, .black
= 316, .burst
= 133,
265 static const struct color_conversion pal_n_csc_composite
= {
266 .ry
= 0x0332, .gy
= 0x012d, .by
= 0x07d3, .ay
= 0x0104,
267 .ru
= 0x0733, .gu
= 0x052d, .bu
= 0x05c7, .au
= 0x0200,
268 .rv
= 0x0340, .gv
= 0x030c, .bv
= 0x06d0, .av
= 0x0200,
271 static const struct video_levels pal_n_levels_composite
= {
272 .blank
= 225, .black
= 267, .burst
= 118,
275 static const struct color_conversion pal_n_csc_svideo
= {
276 .ry
= 0x0332, .gy
= 0x012d, .by
= 0x07d3, .ay
= 0x0133,
277 .ru
= 0x076a, .gu
= 0x0564, .bu
= 0x030d, .au
= 0x0200,
278 .rv
= 0x037a, .gv
= 0x033d, .bv
= 0x06f6, .av
= 0x0200,
281 static const struct video_levels pal_n_levels_svideo
= {
282 .blank
= 266, .black
= 316, .burst
= 139,
286 * Component connections
288 static const struct color_conversion sdtv_csc_yprpb
= {
289 .ry
= 0x0332, .gy
= 0x012d, .by
= 0x07d3, .ay
= 0x0145,
290 .ru
= 0x0559, .gu
= 0x0353, .bu
= 0x0100, .au
= 0x0200,
291 .rv
= 0x0100, .gv
= 0x03ad, .bv
= 0x074d, .av
= 0x0200,
294 static const struct color_conversion hdtv_csc_yprpb
= {
295 .ry
= 0x05b3, .gy
= 0x016e, .by
= 0x0728, .ay
= 0x0145,
296 .ru
= 0x07d5, .gu
= 0x038b, .bu
= 0x0100, .au
= 0x0200,
297 .rv
= 0x0100, .gv
= 0x03d1, .bv
= 0x06bc, .av
= 0x0200,
300 static const struct video_levels component_levels
= {
301 .blank
= 279, .black
= 279, .burst
= 0,
309 u16 refresh
; /* in millihertz (for precision) */
312 u16 hblank_start
, hblank_end
, htotal
;
313 bool progressive
: 1, trilevel_sync
: 1, component_only
: 1;
314 u8 vsync_start_f1
, vsync_start_f2
, vsync_len
;
316 u8 veq_start_f1
, veq_start_f2
, veq_len
;
317 u8 vi_end_f1
, vi_end_f2
;
320 u8 hburst_start
, hburst_len
;
330 * subcarrier programming
332 u16 dda2_size
, dda3_size
;
334 u16 dda2_inc
, dda3_inc
;
340 const struct video_levels
*composite_levels
, *svideo_levels
;
341 const struct color_conversion
*composite_color
, *svideo_color
;
342 const u32
*filter_table
;
350 * I think this works as follows:
352 * subcarrier freq = pixel_clock * (dda1_inc + dda2_inc / dda2_size) / 4096
354 * Presumably, when dda3 is added in, it gets to adjust the dda2_inc value
357 * dda1_ideal = subcarrier/pixel * 4096
358 * dda1_inc = floor (dda1_ideal)
359 * dda2 = dda1_ideal - dda1_inc
361 * then pick a ratio for dda2 that gives the closest approximation. If
362 * you can't get close enough, you can play with dda3 as well. This
363 * seems likely to happen when dda2 is small as the jumps would be larger
367 * pixel_clock = subcarrier * 4096 / (dda1_inc + dda2_inc / dda2_size)
369 * The constants below were all computed using a 107.520MHz clock
373 * Register programming values for TV modes.
375 * These values account for -1s required.
377 static const struct tv_mode tv_modes
[] = {
382 .oversample
= TV_OVERSAMPLE_8X
,
384 /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
386 .hsync_end
= 64, .hblank_end
= 124,
387 .hblank_start
= 836, .htotal
= 857,
389 .progressive
= false, .trilevel_sync
= false,
391 .vsync_start_f1
= 6, .vsync_start_f2
= 7,
394 .veq_ena
= true, .veq_start_f1
= 0,
395 .veq_start_f2
= 1, .veq_len
= 18,
397 .vi_end_f1
= 20, .vi_end_f2
= 21,
401 .hburst_start
= 72, .hburst_len
= 34,
402 .vburst_start_f1
= 9, .vburst_end_f1
= 240,
403 .vburst_start_f2
= 10, .vburst_end_f2
= 240,
404 .vburst_start_f3
= 9, .vburst_end_f3
= 240,
405 .vburst_start_f4
= 10, .vburst_end_f4
= 240,
407 /* desired 3.5800000 actual 3.5800000 clock 107.52 */
409 .dda2_inc
= 20800, .dda2_size
= 27456,
410 .dda3_inc
= 0, .dda3_size
= 0,
411 .sc_reset
= TV_SC_RESET_EVERY_4
,
414 .composite_levels
= &ntsc_m_levels_composite
,
415 .composite_color
= &ntsc_m_csc_composite
,
416 .svideo_levels
= &ntsc_m_levels_svideo
,
417 .svideo_color
= &ntsc_m_csc_svideo
,
419 .filter_table
= filter_table
,
425 .oversample
= TV_OVERSAMPLE_8X
,
427 /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 4.43MHz */
428 .hsync_end
= 64, .hblank_end
= 124,
429 .hblank_start
= 836, .htotal
= 857,
431 .progressive
= false, .trilevel_sync
= false,
433 .vsync_start_f1
= 6, .vsync_start_f2
= 7,
436 .veq_ena
= true, .veq_start_f1
= 0,
437 .veq_start_f2
= 1, .veq_len
= 18,
439 .vi_end_f1
= 20, .vi_end_f2
= 21,
443 .hburst_start
= 72, .hburst_len
= 34,
444 .vburst_start_f1
= 9, .vburst_end_f1
= 240,
445 .vburst_start_f2
= 10, .vburst_end_f2
= 240,
446 .vburst_start_f3
= 9, .vburst_end_f3
= 240,
447 .vburst_start_f4
= 10, .vburst_end_f4
= 240,
449 /* desired 4.4336180 actual 4.4336180 clock 107.52 */
451 .dda2_inc
= 4093, .dda2_size
= 27456,
452 .dda3_inc
= 310, .dda3_size
= 525,
453 .sc_reset
= TV_SC_RESET_NEVER
,
456 .composite_levels
= &ntsc_m_levels_composite
,
457 .composite_color
= &ntsc_m_csc_composite
,
458 .svideo_levels
= &ntsc_m_levels_svideo
,
459 .svideo_color
= &ntsc_m_csc_svideo
,
461 .filter_table
= filter_table
,
467 .oversample
= TV_OVERSAMPLE_8X
,
470 /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
471 .hsync_end
= 64, .hblank_end
= 124,
472 .hblank_start
= 836, .htotal
= 857,
474 .progressive
= false, .trilevel_sync
= false,
476 .vsync_start_f1
= 6, .vsync_start_f2
= 7,
479 .veq_ena
= true, .veq_start_f1
= 0,
480 .veq_start_f2
= 1, .veq_len
= 18,
482 .vi_end_f1
= 20, .vi_end_f2
= 21,
486 .hburst_start
= 72, .hburst_len
= 34,
487 .vburst_start_f1
= 9, .vburst_end_f1
= 240,
488 .vburst_start_f2
= 10, .vburst_end_f2
= 240,
489 .vburst_start_f3
= 9, .vburst_end_f3
= 240,
490 .vburst_start_f4
= 10, .vburst_end_f4
= 240,
492 /* desired 3.5800000 actual 3.5800000 clock 107.52 */
494 .dda2_inc
= 20800, .dda2_size
= 27456,
495 .dda3_inc
= 0, .dda3_size
= 0,
496 .sc_reset
= TV_SC_RESET_EVERY_4
,
499 .composite_levels
= &ntsc_j_levels_composite
,
500 .composite_color
= &ntsc_j_csc_composite
,
501 .svideo_levels
= &ntsc_j_levels_svideo
,
502 .svideo_color
= &ntsc_j_csc_svideo
,
504 .filter_table
= filter_table
,
510 .oversample
= TV_OVERSAMPLE_8X
,
513 /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
514 .hsync_end
= 64, .hblank_end
= 124,
515 .hblank_start
= 836, .htotal
= 857,
517 .progressive
= false, .trilevel_sync
= false,
519 .vsync_start_f1
= 6, .vsync_start_f2
= 7,
522 .veq_ena
= true, .veq_start_f1
= 0,
523 .veq_start_f2
= 1, .veq_len
= 18,
525 .vi_end_f1
= 20, .vi_end_f2
= 21,
529 .hburst_start
= 72, .hburst_len
= 34,
530 .vburst_start_f1
= 9, .vburst_end_f1
= 240,
531 .vburst_start_f2
= 10, .vburst_end_f2
= 240,
532 .vburst_start_f3
= 9, .vburst_end_f3
= 240,
533 .vburst_start_f4
= 10, .vburst_end_f4
= 240,
535 /* desired 3.5800000 actual 3.5800000 clock 107.52 */
537 .dda2_inc
= 16704, .dda2_size
= 27456,
538 .dda3_inc
= 0, .dda3_size
= 0,
539 .sc_reset
= TV_SC_RESET_EVERY_8
,
542 .composite_levels
= &pal_m_levels_composite
,
543 .composite_color
= &pal_m_csc_composite
,
544 .svideo_levels
= &pal_m_levels_svideo
,
545 .svideo_color
= &pal_m_csc_svideo
,
547 .filter_table
= filter_table
,
550 /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
554 .oversample
= TV_OVERSAMPLE_8X
,
557 .hsync_end
= 64, .hblank_end
= 128,
558 .hblank_start
= 844, .htotal
= 863,
560 .progressive
= false, .trilevel_sync
= false,
563 .vsync_start_f1
= 6, .vsync_start_f2
= 7,
566 .veq_ena
= true, .veq_start_f1
= 0,
567 .veq_start_f2
= 1, .veq_len
= 18,
569 .vi_end_f1
= 24, .vi_end_f2
= 25,
573 .hburst_start
= 73, .hburst_len
= 34,
574 .vburst_start_f1
= 8, .vburst_end_f1
= 285,
575 .vburst_start_f2
= 8, .vburst_end_f2
= 286,
576 .vburst_start_f3
= 9, .vburst_end_f3
= 286,
577 .vburst_start_f4
= 9, .vburst_end_f4
= 285,
580 /* desired 4.4336180 actual 4.4336180 clock 107.52 */
582 .dda2_inc
= 23578, .dda2_size
= 27648,
583 .dda3_inc
= 134, .dda3_size
= 625,
584 .sc_reset
= TV_SC_RESET_EVERY_8
,
587 .composite_levels
= &pal_n_levels_composite
,
588 .composite_color
= &pal_n_csc_composite
,
589 .svideo_levels
= &pal_n_levels_svideo
,
590 .svideo_color
= &pal_n_csc_svideo
,
592 .filter_table
= filter_table
,
595 /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
599 .oversample
= TV_OVERSAMPLE_8X
,
602 .hsync_end
= 64, .hblank_end
= 142,
603 .hblank_start
= 844, .htotal
= 863,
605 .progressive
= false, .trilevel_sync
= false,
607 .vsync_start_f1
= 5, .vsync_start_f2
= 6,
610 .veq_ena
= true, .veq_start_f1
= 0,
611 .veq_start_f2
= 1, .veq_len
= 15,
613 .vi_end_f1
= 24, .vi_end_f2
= 25,
617 .hburst_start
= 73, .hburst_len
= 32,
618 .vburst_start_f1
= 8, .vburst_end_f1
= 285,
619 .vburst_start_f2
= 8, .vburst_end_f2
= 286,
620 .vburst_start_f3
= 9, .vburst_end_f3
= 286,
621 .vburst_start_f4
= 9, .vburst_end_f4
= 285,
623 /* desired 4.4336180 actual 4.4336180 clock 107.52 */
625 .dda2_inc
= 4122, .dda2_size
= 27648,
626 .dda3_inc
= 67, .dda3_size
= 625,
627 .sc_reset
= TV_SC_RESET_EVERY_8
,
630 .composite_levels
= &pal_levels_composite
,
631 .composite_color
= &pal_csc_composite
,
632 .svideo_levels
= &pal_levels_svideo
,
633 .svideo_color
= &pal_csc_svideo
,
635 .filter_table
= filter_table
,
641 .oversample
= TV_OVERSAMPLE_4X
,
644 .hsync_end
= 64, .hblank_end
= 122,
645 .hblank_start
= 842, .htotal
= 857,
647 .progressive
= true, .trilevel_sync
= false,
649 .vsync_start_f1
= 12, .vsync_start_f2
= 12,
654 .vi_end_f1
= 44, .vi_end_f2
= 44,
659 .filter_table
= filter_table
,
665 .oversample
= TV_OVERSAMPLE_4X
,
668 .hsync_end
= 64, .hblank_end
= 139,
669 .hblank_start
= 859, .htotal
= 863,
671 .progressive
= true, .trilevel_sync
= false,
673 .vsync_start_f1
= 10, .vsync_start_f2
= 10,
678 .vi_end_f1
= 48, .vi_end_f2
= 48,
683 .filter_table
= filter_table
,
689 .oversample
= TV_OVERSAMPLE_2X
,
692 .hsync_end
= 80, .hblank_end
= 300,
693 .hblank_start
= 1580, .htotal
= 1649,
695 .progressive
= true, .trilevel_sync
= true,
697 .vsync_start_f1
= 10, .vsync_start_f2
= 10,
702 .vi_end_f1
= 29, .vi_end_f2
= 29,
707 .filter_table
= filter_table
,
713 .oversample
= TV_OVERSAMPLE_2X
,
716 .hsync_end
= 80, .hblank_end
= 300,
717 .hblank_start
= 1580, .htotal
= 1979,
719 .progressive
= true, .trilevel_sync
= true,
721 .vsync_start_f1
= 10, .vsync_start_f2
= 10,
726 .vi_end_f1
= 29, .vi_end_f2
= 29,
731 .filter_table
= filter_table
,
735 .name
= "1080i@50Hz",
738 .oversample
= TV_OVERSAMPLE_2X
,
741 .hsync_end
= 88, .hblank_end
= 235,
742 .hblank_start
= 2155, .htotal
= 2639,
744 .progressive
= false, .trilevel_sync
= true,
746 .vsync_start_f1
= 4, .vsync_start_f2
= 5,
749 .veq_ena
= true, .veq_start_f1
= 4,
750 .veq_start_f2
= 4, .veq_len
= 10,
753 .vi_end_f1
= 21, .vi_end_f2
= 22,
758 .filter_table
= filter_table
,
761 .name
= "1080i@60Hz",
764 .oversample
= TV_OVERSAMPLE_2X
,
767 .hsync_end
= 88, .hblank_end
= 235,
768 .hblank_start
= 2155, .htotal
= 2199,
770 .progressive
= false, .trilevel_sync
= true,
772 .vsync_start_f1
= 4, .vsync_start_f2
= 5,
775 .veq_ena
= true, .veq_start_f1
= 4,
776 .veq_start_f2
= 4, .veq_len
= 10,
779 .vi_end_f1
= 21, .vi_end_f2
= 22,
784 .filter_table
= filter_table
,
788 static struct intel_tv
*enc_to_tv(struct intel_encoder
*encoder
)
790 return container_of(encoder
, struct intel_tv
, base
);
793 static struct intel_tv
*intel_attached_tv(struct drm_connector
*connector
)
795 return enc_to_tv(intel_attached_encoder(connector
));
799 intel_tv_get_hw_state(struct intel_encoder
*encoder
, enum pipe
*pipe
)
801 struct drm_i915_private
*dev_priv
= to_i915(encoder
->base
.dev
);
802 u32 tmp
= I915_READ(TV_CTL
);
804 *pipe
= (tmp
& TV_ENC_PIPE_SEL_MASK
) >> TV_ENC_PIPE_SEL_SHIFT
;
806 return tmp
& TV_ENC_ENABLE
;
810 intel_enable_tv(struct intel_encoder
*encoder
,
811 const struct intel_crtc_state
*pipe_config
,
812 const struct drm_connector_state
*conn_state
)
814 struct drm_device
*dev
= encoder
->base
.dev
;
815 struct drm_i915_private
*dev_priv
= to_i915(dev
);
817 /* Prevents vblank waits from timing out in intel_tv_detect_type() */
818 intel_wait_for_vblank(dev_priv
,
819 to_intel_crtc(pipe_config
->base
.crtc
)->pipe
);
821 I915_WRITE(TV_CTL
, I915_READ(TV_CTL
) | TV_ENC_ENABLE
);
825 intel_disable_tv(struct intel_encoder
*encoder
,
826 const struct intel_crtc_state
*old_crtc_state
,
827 const struct drm_connector_state
*old_conn_state
)
829 struct drm_device
*dev
= encoder
->base
.dev
;
830 struct drm_i915_private
*dev_priv
= to_i915(dev
);
832 I915_WRITE(TV_CTL
, I915_READ(TV_CTL
) & ~TV_ENC_ENABLE
);
835 static const struct tv_mode
*intel_tv_mode_find(const struct drm_connector_state
*conn_state
)
837 int format
= conn_state
->tv
.mode
;
839 return &tv_modes
[format
];
842 static enum drm_mode_status
843 intel_tv_mode_valid(struct drm_connector
*connector
,
844 struct drm_display_mode
*mode
)
846 const struct tv_mode
*tv_mode
= intel_tv_mode_find(connector
->state
);
847 int max_dotclk
= to_i915(connector
->dev
)->max_dotclk_freq
;
849 if (mode
->flags
& DRM_MODE_FLAG_DBLSCAN
)
850 return MODE_NO_DBLESCAN
;
852 if (mode
->clock
> max_dotclk
)
853 return MODE_CLOCK_HIGH
;
855 /* Ensure TV refresh is close to desired refresh */
856 if (tv_mode
&& abs(tv_mode
->refresh
- drm_mode_vrefresh(mode
) * 1000)
860 return MODE_CLOCK_RANGE
;
865 intel_tv_get_config(struct intel_encoder
*encoder
,
866 struct intel_crtc_state
*pipe_config
)
868 pipe_config
->output_types
|= BIT(INTEL_OUTPUT_TVOUT
);
870 pipe_config
->base
.adjusted_mode
.crtc_clock
= pipe_config
->port_clock
;
874 intel_tv_compute_config(struct intel_encoder
*encoder
,
875 struct intel_crtc_state
*pipe_config
,
876 struct drm_connector_state
*conn_state
)
878 const struct tv_mode
*tv_mode
= intel_tv_mode_find(conn_state
);
879 struct drm_display_mode
*adjusted_mode
=
880 &pipe_config
->base
.adjusted_mode
;
885 if (adjusted_mode
->flags
& DRM_MODE_FLAG_DBLSCAN
)
888 adjusted_mode
->crtc_clock
= tv_mode
->clock
;
889 DRM_DEBUG_KMS("forcing bpc to 8 for TV\n");
890 pipe_config
->pipe_bpp
= 8*3;
892 /* TV has it's own notion of sync and other mode flags, so clear them. */
893 adjusted_mode
->flags
= 0;
896 * FIXME: We don't check whether the input mode is actually what we want
897 * or whether userspace is doing something stupid.
904 set_tv_mode_timings(struct drm_i915_private
*dev_priv
,
905 const struct tv_mode
*tv_mode
,
908 u32 hctl1
, hctl2
, hctl3
;
909 u32 vctl1
, vctl2
, vctl3
, vctl4
, vctl5
, vctl6
, vctl7
;
911 hctl1
= (tv_mode
->hsync_end
<< TV_HSYNC_END_SHIFT
) |
912 (tv_mode
->htotal
<< TV_HTOTAL_SHIFT
);
914 hctl2
= (tv_mode
->hburst_start
<< 16) |
915 (tv_mode
->hburst_len
<< TV_HBURST_LEN_SHIFT
);
918 hctl2
|= TV_BURST_ENA
;
920 hctl3
= (tv_mode
->hblank_start
<< TV_HBLANK_START_SHIFT
) |
921 (tv_mode
->hblank_end
<< TV_HBLANK_END_SHIFT
);
923 vctl1
= (tv_mode
->nbr_end
<< TV_NBR_END_SHIFT
) |
924 (tv_mode
->vi_end_f1
<< TV_VI_END_F1_SHIFT
) |
925 (tv_mode
->vi_end_f2
<< TV_VI_END_F2_SHIFT
);
927 vctl2
= (tv_mode
->vsync_len
<< TV_VSYNC_LEN_SHIFT
) |
928 (tv_mode
->vsync_start_f1
<< TV_VSYNC_START_F1_SHIFT
) |
929 (tv_mode
->vsync_start_f2
<< TV_VSYNC_START_F2_SHIFT
);
931 vctl3
= (tv_mode
->veq_len
<< TV_VEQ_LEN_SHIFT
) |
932 (tv_mode
->veq_start_f1
<< TV_VEQ_START_F1_SHIFT
) |
933 (tv_mode
->veq_start_f2
<< TV_VEQ_START_F2_SHIFT
);
935 if (tv_mode
->veq_ena
)
936 vctl3
|= TV_EQUAL_ENA
;
938 vctl4
= (tv_mode
->vburst_start_f1
<< TV_VBURST_START_F1_SHIFT
) |
939 (tv_mode
->vburst_end_f1
<< TV_VBURST_END_F1_SHIFT
);
941 vctl5
= (tv_mode
->vburst_start_f2
<< TV_VBURST_START_F2_SHIFT
) |
942 (tv_mode
->vburst_end_f2
<< TV_VBURST_END_F2_SHIFT
);
944 vctl6
= (tv_mode
->vburst_start_f3
<< TV_VBURST_START_F3_SHIFT
) |
945 (tv_mode
->vburst_end_f3
<< TV_VBURST_END_F3_SHIFT
);
947 vctl7
= (tv_mode
->vburst_start_f4
<< TV_VBURST_START_F4_SHIFT
) |
948 (tv_mode
->vburst_end_f4
<< TV_VBURST_END_F4_SHIFT
);
950 I915_WRITE(TV_H_CTL_1
, hctl1
);
951 I915_WRITE(TV_H_CTL_2
, hctl2
);
952 I915_WRITE(TV_H_CTL_3
, hctl3
);
953 I915_WRITE(TV_V_CTL_1
, vctl1
);
954 I915_WRITE(TV_V_CTL_2
, vctl2
);
955 I915_WRITE(TV_V_CTL_3
, vctl3
);
956 I915_WRITE(TV_V_CTL_4
, vctl4
);
957 I915_WRITE(TV_V_CTL_5
, vctl5
);
958 I915_WRITE(TV_V_CTL_6
, vctl6
);
959 I915_WRITE(TV_V_CTL_7
, vctl7
);
962 static void set_color_conversion(struct drm_i915_private
*dev_priv
,
963 const struct color_conversion
*color_conversion
)
965 if (!color_conversion
)
968 I915_WRITE(TV_CSC_Y
, (color_conversion
->ry
<< 16) |
969 color_conversion
->gy
);
970 I915_WRITE(TV_CSC_Y2
, (color_conversion
->by
<< 16) |
971 color_conversion
->ay
);
972 I915_WRITE(TV_CSC_U
, (color_conversion
->ru
<< 16) |
973 color_conversion
->gu
);
974 I915_WRITE(TV_CSC_U2
, (color_conversion
->bu
<< 16) |
975 color_conversion
->au
);
976 I915_WRITE(TV_CSC_V
, (color_conversion
->rv
<< 16) |
977 color_conversion
->gv
);
978 I915_WRITE(TV_CSC_V2
, (color_conversion
->bv
<< 16) |
979 color_conversion
->av
);
982 static void intel_tv_pre_enable(struct intel_encoder
*encoder
,
983 const struct intel_crtc_state
*pipe_config
,
984 const struct drm_connector_state
*conn_state
)
986 struct drm_i915_private
*dev_priv
= to_i915(encoder
->base
.dev
);
987 struct intel_crtc
*intel_crtc
= to_intel_crtc(pipe_config
->base
.crtc
);
988 struct intel_tv
*intel_tv
= enc_to_tv(encoder
);
989 const struct tv_mode
*tv_mode
= intel_tv_mode_find(conn_state
);
991 u32 scctl1
, scctl2
, scctl3
;
993 const struct video_levels
*video_levels
;
994 const struct color_conversion
*color_conversion
;
996 int xpos
= 0x0, ypos
= 0x0;
997 unsigned int xsize
, ysize
;
1000 return; /* can't happen (mode_prepare prevents this) */
1002 tv_ctl
= I915_READ(TV_CTL
);
1003 tv_ctl
&= TV_CTL_SAVE
;
1005 switch (intel_tv
->type
) {
1007 case DRM_MODE_CONNECTOR_Unknown
:
1008 case DRM_MODE_CONNECTOR_Composite
:
1009 tv_ctl
|= TV_ENC_OUTPUT_COMPOSITE
;
1010 video_levels
= tv_mode
->composite_levels
;
1011 color_conversion
= tv_mode
->composite_color
;
1012 burst_ena
= tv_mode
->burst_ena
;
1014 case DRM_MODE_CONNECTOR_Component
:
1015 tv_ctl
|= TV_ENC_OUTPUT_COMPONENT
;
1016 video_levels
= &component_levels
;
1017 if (tv_mode
->burst_ena
)
1018 color_conversion
= &sdtv_csc_yprpb
;
1020 color_conversion
= &hdtv_csc_yprpb
;
1023 case DRM_MODE_CONNECTOR_SVIDEO
:
1024 tv_ctl
|= TV_ENC_OUTPUT_SVIDEO
;
1025 video_levels
= tv_mode
->svideo_levels
;
1026 color_conversion
= tv_mode
->svideo_color
;
1027 burst_ena
= tv_mode
->burst_ena
;
1031 tv_ctl
|= TV_ENC_PIPE_SEL(intel_crtc
->pipe
);
1032 tv_ctl
|= tv_mode
->oversample
;
1034 if (tv_mode
->progressive
)
1035 tv_ctl
|= TV_PROGRESSIVE
;
1036 if (tv_mode
->trilevel_sync
)
1037 tv_ctl
|= TV_TRILEVEL_SYNC
;
1038 if (tv_mode
->pal_burst
)
1039 tv_ctl
|= TV_PAL_BURST
;
1042 if (tv_mode
->dda1_inc
)
1043 scctl1
|= TV_SC_DDA1_EN
;
1044 if (tv_mode
->dda2_inc
)
1045 scctl1
|= TV_SC_DDA2_EN
;
1046 if (tv_mode
->dda3_inc
)
1047 scctl1
|= TV_SC_DDA3_EN
;
1048 scctl1
|= tv_mode
->sc_reset
;
1050 scctl1
|= video_levels
->burst
<< TV_BURST_LEVEL_SHIFT
;
1051 scctl1
|= tv_mode
->dda1_inc
<< TV_SCDDA1_INC_SHIFT
;
1053 scctl2
= tv_mode
->dda2_size
<< TV_SCDDA2_SIZE_SHIFT
|
1054 tv_mode
->dda2_inc
<< TV_SCDDA2_INC_SHIFT
;
1056 scctl3
= tv_mode
->dda3_size
<< TV_SCDDA3_SIZE_SHIFT
|
1057 tv_mode
->dda3_inc
<< TV_SCDDA3_INC_SHIFT
;
1059 /* Enable two fixes for the chips that need them. */
1060 if (IS_I915GM(dev_priv
))
1061 tv_ctl
|= TV_ENC_C0_FIX
| TV_ENC_SDP_FIX
;
1063 set_tv_mode_timings(dev_priv
, tv_mode
, burst_ena
);
1065 I915_WRITE(TV_SC_CTL_1
, scctl1
);
1066 I915_WRITE(TV_SC_CTL_2
, scctl2
);
1067 I915_WRITE(TV_SC_CTL_3
, scctl3
);
1069 set_color_conversion(dev_priv
, color_conversion
);
1071 if (INTEL_GEN(dev_priv
) >= 4)
1072 I915_WRITE(TV_CLR_KNOBS
, 0x00404000);
1074 I915_WRITE(TV_CLR_KNOBS
, 0x00606000);
1077 I915_WRITE(TV_CLR_LEVEL
,
1078 ((video_levels
->black
<< TV_BLACK_LEVEL_SHIFT
) |
1079 (video_levels
->blank
<< TV_BLANK_LEVEL_SHIFT
)));
1081 assert_pipe_disabled(dev_priv
, intel_crtc
->pipe
);
1083 /* Filter ctl must be set before TV_WIN_SIZE */
1084 I915_WRITE(TV_FILTER_CTL_1
, TV_AUTO_SCALE
);
1085 xsize
= tv_mode
->hblank_start
- tv_mode
->hblank_end
;
1086 if (tv_mode
->progressive
)
1087 ysize
= tv_mode
->nbr_end
+ 1;
1089 ysize
= 2*tv_mode
->nbr_end
+ 1;
1091 xpos
+= conn_state
->tv
.margins
.left
;
1092 ypos
+= conn_state
->tv
.margins
.top
;
1093 xsize
-= (conn_state
->tv
.margins
.left
+
1094 conn_state
->tv
.margins
.right
);
1095 ysize
-= (conn_state
->tv
.margins
.top
+
1096 conn_state
->tv
.margins
.bottom
);
1097 I915_WRITE(TV_WIN_POS
, (xpos
<<16)|ypos
);
1098 I915_WRITE(TV_WIN_SIZE
, (xsize
<<16)|ysize
);
1101 for (i
= 0; i
< 60; i
++)
1102 I915_WRITE(TV_H_LUMA(i
), tv_mode
->filter_table
[j
++]);
1103 for (i
= 0; i
< 60; i
++)
1104 I915_WRITE(TV_H_CHROMA(i
), tv_mode
->filter_table
[j
++]);
1105 for (i
= 0; i
< 43; i
++)
1106 I915_WRITE(TV_V_LUMA(i
), tv_mode
->filter_table
[j
++]);
1107 for (i
= 0; i
< 43; i
++)
1108 I915_WRITE(TV_V_CHROMA(i
), tv_mode
->filter_table
[j
++]);
1109 I915_WRITE(TV_DAC
, I915_READ(TV_DAC
) & TV_DAC_SAVE
);
1110 I915_WRITE(TV_CTL
, tv_ctl
);
1113 static const struct drm_display_mode reported_modes
[] = {
1115 .name
= "NTSC 480i",
1118 .hsync_start
= 1368,
1123 .vsync_start
= 1027,
1126 .type
= DRM_MODE_TYPE_DRIVER
,
1131 intel_tv_detect_type(struct intel_tv
*intel_tv
,
1132 struct drm_connector
*connector
)
1134 struct drm_crtc
*crtc
= connector
->state
->crtc
;
1135 struct intel_crtc
*intel_crtc
= to_intel_crtc(crtc
);
1136 struct drm_device
*dev
= connector
->dev
;
1137 struct drm_i915_private
*dev_priv
= to_i915(dev
);
1138 u32 tv_ctl
, save_tv_ctl
;
1139 u32 tv_dac
, save_tv_dac
;
1142 /* Disable TV interrupts around load detect or we'll recurse */
1143 if (connector
->polled
& DRM_CONNECTOR_POLL_HPD
) {
1144 spin_lock_irq(&dev_priv
->irq_lock
);
1145 i915_disable_pipestat(dev_priv
, 0,
1146 PIPE_HOTPLUG_INTERRUPT_STATUS
|
1147 PIPE_HOTPLUG_TV_INTERRUPT_STATUS
);
1148 spin_unlock_irq(&dev_priv
->irq_lock
);
1151 save_tv_dac
= tv_dac
= I915_READ(TV_DAC
);
1152 save_tv_ctl
= tv_ctl
= I915_READ(TV_CTL
);
1154 /* Poll for TV detection */
1155 tv_ctl
&= ~(TV_ENC_ENABLE
| TV_ENC_PIPE_SEL_MASK
| TV_TEST_MODE_MASK
);
1156 tv_ctl
|= TV_TEST_MODE_MONITOR_DETECT
;
1157 tv_ctl
|= TV_ENC_PIPE_SEL(intel_crtc
->pipe
);
1159 tv_dac
&= ~(TVDAC_SENSE_MASK
| DAC_A_MASK
| DAC_B_MASK
| DAC_C_MASK
);
1160 tv_dac
|= (TVDAC_STATE_CHG_EN
|
1171 * The TV sense state should be cleared to zero on cantiga platform. Otherwise
1172 * the TV is misdetected. This is hardware requirement.
1174 if (IS_GM45(dev_priv
))
1175 tv_dac
&= ~(TVDAC_STATE_CHG_EN
| TVDAC_A_SENSE_CTL
|
1176 TVDAC_B_SENSE_CTL
| TVDAC_C_SENSE_CTL
);
1178 I915_WRITE(TV_CTL
, tv_ctl
);
1179 I915_WRITE(TV_DAC
, tv_dac
);
1180 POSTING_READ(TV_DAC
);
1182 intel_wait_for_vblank(dev_priv
, intel_crtc
->pipe
);
1185 tv_dac
= I915_READ(TV_DAC
);
1186 DRM_DEBUG_KMS("TV detected: %x, %x\n", tv_ctl
, tv_dac
);
1193 if ((tv_dac
& TVDAC_SENSE_MASK
) == (TVDAC_B_SENSE
| TVDAC_C_SENSE
)) {
1194 DRM_DEBUG_KMS("Detected Composite TV connection\n");
1195 type
= DRM_MODE_CONNECTOR_Composite
;
1196 } else if ((tv_dac
& (TVDAC_A_SENSE
|TVDAC_B_SENSE
)) == TVDAC_A_SENSE
) {
1197 DRM_DEBUG_KMS("Detected S-Video TV connection\n");
1198 type
= DRM_MODE_CONNECTOR_SVIDEO
;
1199 } else if ((tv_dac
& TVDAC_SENSE_MASK
) == 0) {
1200 DRM_DEBUG_KMS("Detected Component TV connection\n");
1201 type
= DRM_MODE_CONNECTOR_Component
;
1203 DRM_DEBUG_KMS("Unrecognised TV connection\n");
1207 I915_WRITE(TV_DAC
, save_tv_dac
& ~TVDAC_STATE_CHG_EN
);
1208 I915_WRITE(TV_CTL
, save_tv_ctl
);
1209 POSTING_READ(TV_CTL
);
1211 /* For unknown reasons the hw barfs if we don't do this vblank wait. */
1212 intel_wait_for_vblank(dev_priv
, intel_crtc
->pipe
);
1214 /* Restore interrupt config */
1215 if (connector
->polled
& DRM_CONNECTOR_POLL_HPD
) {
1216 spin_lock_irq(&dev_priv
->irq_lock
);
1217 i915_enable_pipestat(dev_priv
, 0,
1218 PIPE_HOTPLUG_INTERRUPT_STATUS
|
1219 PIPE_HOTPLUG_TV_INTERRUPT_STATUS
);
1220 spin_unlock_irq(&dev_priv
->irq_lock
);
1227 * Here we set accurate tv format according to connector type
1228 * i.e Component TV should not be assigned by NTSC or PAL
1230 static void intel_tv_find_better_format(struct drm_connector
*connector
)
1232 struct intel_tv
*intel_tv
= intel_attached_tv(connector
);
1233 const struct tv_mode
*tv_mode
= intel_tv_mode_find(connector
->state
);
1236 if ((intel_tv
->type
== DRM_MODE_CONNECTOR_Component
) ==
1237 tv_mode
->component_only
)
1241 for (i
= 0; i
< ARRAY_SIZE(tv_modes
); i
++) {
1242 tv_mode
= tv_modes
+ i
;
1244 if ((intel_tv
->type
== DRM_MODE_CONNECTOR_Component
) ==
1245 tv_mode
->component_only
)
1249 connector
->state
->tv
.mode
= i
;
1253 intel_tv_detect(struct drm_connector
*connector
,
1254 struct drm_modeset_acquire_ctx
*ctx
,
1257 struct drm_display_mode mode
;
1258 struct intel_tv
*intel_tv
= intel_attached_tv(connector
);
1259 enum drm_connector_status status
;
1262 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n",
1263 connector
->base
.id
, connector
->name
,
1266 mode
= reported_modes
[0];
1269 struct intel_load_detect_pipe tmp
;
1272 ret
= intel_get_load_detect_pipe(connector
, &mode
, &tmp
, ctx
);
1277 type
= intel_tv_detect_type(intel_tv
, connector
);
1278 intel_release_load_detect_pipe(connector
, &tmp
, ctx
);
1280 connector_status_disconnected
:
1281 connector_status_connected
;
1283 status
= connector_status_unknown
;
1285 if (status
== connector_status_connected
) {
1286 intel_tv
->type
= type
;
1287 intel_tv_find_better_format(connector
);
1292 return connector
->status
;
1295 static const struct input_res
{
1298 } input_res_table
[] = {
1299 {"640x480", 640, 480},
1300 {"800x600", 800, 600},
1301 {"1024x768", 1024, 768},
1302 {"1280x1024", 1280, 1024},
1303 {"848x480", 848, 480},
1304 {"1280x720", 1280, 720},
1305 {"1920x1080", 1920, 1080},
1309 * Chose preferred mode according to line number of TV format
1312 intel_tv_choose_preferred_modes(const struct tv_mode
*tv_mode
,
1313 struct drm_display_mode
*mode_ptr
)
1315 if (tv_mode
->nbr_end
< 480 && mode_ptr
->vdisplay
== 480)
1316 mode_ptr
->type
|= DRM_MODE_TYPE_PREFERRED
;
1317 else if (tv_mode
->nbr_end
> 480) {
1318 if (tv_mode
->progressive
== true && tv_mode
->nbr_end
< 720) {
1319 if (mode_ptr
->vdisplay
== 720)
1320 mode_ptr
->type
|= DRM_MODE_TYPE_PREFERRED
;
1321 } else if (mode_ptr
->vdisplay
== 1080)
1322 mode_ptr
->type
|= DRM_MODE_TYPE_PREFERRED
;
1327 intel_tv_get_modes(struct drm_connector
*connector
)
1329 struct drm_display_mode
*mode_ptr
;
1330 const struct tv_mode
*tv_mode
= intel_tv_mode_find(connector
->state
);
1334 for (j
= 0; j
< ARRAY_SIZE(input_res_table
);
1336 const struct input_res
*input
= &input_res_table
[j
];
1337 unsigned int hactive_s
= input
->w
;
1338 unsigned int vactive_s
= input
->h
;
1340 if (tv_mode
->max_srcw
&& input
->w
> tv_mode
->max_srcw
)
1343 if (input
->w
> 1024 && (!tv_mode
->progressive
1344 && !tv_mode
->component_only
))
1347 mode_ptr
= drm_mode_create(connector
->dev
);
1350 strlcpy(mode_ptr
->name
, input
->name
, DRM_DISPLAY_MODE_LEN
);
1352 mode_ptr
->hdisplay
= hactive_s
;
1353 mode_ptr
->hsync_start
= hactive_s
+ 1;
1354 mode_ptr
->hsync_end
= hactive_s
+ 64;
1355 if (mode_ptr
->hsync_end
<= mode_ptr
->hsync_start
)
1356 mode_ptr
->hsync_end
= mode_ptr
->hsync_start
+ 1;
1357 mode_ptr
->htotal
= hactive_s
+ 96;
1359 mode_ptr
->vdisplay
= vactive_s
;
1360 mode_ptr
->vsync_start
= vactive_s
+ 1;
1361 mode_ptr
->vsync_end
= vactive_s
+ 32;
1362 if (mode_ptr
->vsync_end
<= mode_ptr
->vsync_start
)
1363 mode_ptr
->vsync_end
= mode_ptr
->vsync_start
+ 1;
1364 mode_ptr
->vtotal
= vactive_s
+ 33;
1366 tmp
= mul_u32_u32(tv_mode
->refresh
, mode_ptr
->vtotal
);
1367 tmp
*= mode_ptr
->htotal
;
1368 tmp
= div_u64(tmp
, 1000000);
1369 mode_ptr
->clock
= (int) tmp
;
1371 mode_ptr
->type
= DRM_MODE_TYPE_DRIVER
;
1372 intel_tv_choose_preferred_modes(tv_mode
, mode_ptr
);
1373 drm_mode_probed_add(connector
, mode_ptr
);
1381 intel_tv_destroy(struct drm_connector
*connector
)
1383 drm_connector_cleanup(connector
);
1387 static const struct drm_connector_funcs intel_tv_connector_funcs
= {
1388 .late_register
= intel_connector_register
,
1389 .early_unregister
= intel_connector_unregister
,
1390 .destroy
= intel_tv_destroy
,
1391 .fill_modes
= drm_helper_probe_single_connector_modes
,
1392 .atomic_destroy_state
= drm_atomic_helper_connector_destroy_state
,
1393 .atomic_duplicate_state
= drm_atomic_helper_connector_duplicate_state
,
1396 static int intel_tv_atomic_check(struct drm_connector
*connector
,
1397 struct drm_connector_state
*new_state
)
1399 struct drm_crtc_state
*new_crtc_state
;
1400 struct drm_connector_state
*old_state
;
1402 if (!new_state
->crtc
)
1405 old_state
= drm_atomic_get_old_connector_state(new_state
->state
, connector
);
1406 new_crtc_state
= drm_atomic_get_new_crtc_state(new_state
->state
, new_state
->crtc
);
1408 if (old_state
->tv
.mode
!= new_state
->tv
.mode
||
1409 old_state
->tv
.margins
.left
!= new_state
->tv
.margins
.left
||
1410 old_state
->tv
.margins
.right
!= new_state
->tv
.margins
.right
||
1411 old_state
->tv
.margins
.top
!= new_state
->tv
.margins
.top
||
1412 old_state
->tv
.margins
.bottom
!= new_state
->tv
.margins
.bottom
) {
1413 /* Force a modeset. */
1415 new_crtc_state
->connectors_changed
= true;
1421 static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs
= {
1422 .detect_ctx
= intel_tv_detect
,
1423 .mode_valid
= intel_tv_mode_valid
,
1424 .get_modes
= intel_tv_get_modes
,
1425 .atomic_check
= intel_tv_atomic_check
,
1428 static const struct drm_encoder_funcs intel_tv_enc_funcs
= {
1429 .destroy
= intel_encoder_destroy
,
1433 intel_tv_init(struct drm_i915_private
*dev_priv
)
1435 struct drm_device
*dev
= &dev_priv
->drm
;
1436 struct drm_connector
*connector
;
1437 struct intel_tv
*intel_tv
;
1438 struct intel_encoder
*intel_encoder
;
1439 struct intel_connector
*intel_connector
;
1440 u32 tv_dac_on
, tv_dac_off
, save_tv_dac
;
1441 const char *tv_format_names
[ARRAY_SIZE(tv_modes
)];
1442 int i
, initial_mode
= 0;
1443 struct drm_connector_state
*state
;
1445 if ((I915_READ(TV_CTL
) & TV_FUSE_STATE_MASK
) == TV_FUSE_STATE_DISABLED
)
1448 if (!intel_bios_is_tv_present(dev_priv
)) {
1449 DRM_DEBUG_KMS("Integrated TV is not present.\n");
1454 * Sanity check the TV output by checking to see if the
1455 * DAC register holds a value
1457 save_tv_dac
= I915_READ(TV_DAC
);
1459 I915_WRITE(TV_DAC
, save_tv_dac
| TVDAC_STATE_CHG_EN
);
1460 tv_dac_on
= I915_READ(TV_DAC
);
1462 I915_WRITE(TV_DAC
, save_tv_dac
& ~TVDAC_STATE_CHG_EN
);
1463 tv_dac_off
= I915_READ(TV_DAC
);
1465 I915_WRITE(TV_DAC
, save_tv_dac
);
1468 * If the register does not hold the state change enable
1469 * bit, (either as a 0 or a 1), assume it doesn't really
1472 if ((tv_dac_on
& TVDAC_STATE_CHG_EN
) == 0 ||
1473 (tv_dac_off
& TVDAC_STATE_CHG_EN
) != 0)
1476 intel_tv
= kzalloc(sizeof(*intel_tv
), GFP_KERNEL
);
1481 intel_connector
= intel_connector_alloc();
1482 if (!intel_connector
) {
1487 intel_encoder
= &intel_tv
->base
;
1488 connector
= &intel_connector
->base
;
1489 state
= connector
->state
;
1492 * The documentation, for the older chipsets at least, recommend
1493 * using a polling method rather than hotplug detection for TVs.
1494 * This is because in order to perform the hotplug detection, the PLLs
1495 * for the TV must be kept alive increasing power drain and starving
1496 * bandwidth from other encoders. Notably for instance, it causes
1497 * pipe underruns on Crestline when this encoder is supposedly idle.
1499 * More recent chipsets favour HDMI rather than integrated S-Video.
1501 intel_connector
->polled
= DRM_CONNECTOR_POLL_CONNECT
;
1503 drm_connector_init(dev
, connector
, &intel_tv_connector_funcs
,
1504 DRM_MODE_CONNECTOR_SVIDEO
);
1506 drm_encoder_init(dev
, &intel_encoder
->base
, &intel_tv_enc_funcs
,
1507 DRM_MODE_ENCODER_TVDAC
, "TV");
1509 intel_encoder
->compute_config
= intel_tv_compute_config
;
1510 intel_encoder
->get_config
= intel_tv_get_config
;
1511 intel_encoder
->pre_enable
= intel_tv_pre_enable
;
1512 intel_encoder
->enable
= intel_enable_tv
;
1513 intel_encoder
->disable
= intel_disable_tv
;
1514 intel_encoder
->get_hw_state
= intel_tv_get_hw_state
;
1515 intel_connector
->get_hw_state
= intel_connector_get_hw_state
;
1517 intel_connector_attach_encoder(intel_connector
, intel_encoder
);
1519 intel_encoder
->type
= INTEL_OUTPUT_TVOUT
;
1520 intel_encoder
->power_domain
= POWER_DOMAIN_PORT_OTHER
;
1521 intel_encoder
->port
= PORT_NONE
;
1522 intel_encoder
->crtc_mask
= (1 << 0) | (1 << 1);
1523 intel_encoder
->cloneable
= 0;
1524 intel_encoder
->base
.possible_crtcs
= ((1 << 0) | (1 << 1));
1525 intel_tv
->type
= DRM_MODE_CONNECTOR_Unknown
;
1527 /* BIOS margin values */
1528 state
->tv
.margins
.left
= 54;
1529 state
->tv
.margins
.top
= 36;
1530 state
->tv
.margins
.right
= 46;
1531 state
->tv
.margins
.bottom
= 37;
1533 state
->tv
.mode
= initial_mode
;
1535 drm_connector_helper_add(connector
, &intel_tv_connector_helper_funcs
);
1536 connector
->interlace_allowed
= false;
1537 connector
->doublescan_allowed
= false;
1539 /* Create TV properties then attach current values */
1540 for (i
= 0; i
< ARRAY_SIZE(tv_modes
); i
++)
1541 tv_format_names
[i
] = tv_modes
[i
].name
;
1542 drm_mode_create_tv_properties(dev
,
1543 ARRAY_SIZE(tv_modes
),
1546 drm_object_attach_property(&connector
->base
, dev
->mode_config
.tv_mode_property
,
1548 drm_object_attach_property(&connector
->base
,
1549 dev
->mode_config
.tv_left_margin_property
,
1550 state
->tv
.margins
.left
);
1551 drm_object_attach_property(&connector
->base
,
1552 dev
->mode_config
.tv_top_margin_property
,
1553 state
->tv
.margins
.top
);
1554 drm_object_attach_property(&connector
->base
,
1555 dev
->mode_config
.tv_right_margin_property
,
1556 state
->tv
.margins
.right
);
1557 drm_object_attach_property(&connector
->base
,
1558 dev
->mode_config
.tv_bottom_margin_property
,
1559 state
->tv
.margins
.bottom
);