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