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