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