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