intel_tv.c revision 235783
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: head/sys/dev/drm2/i915/intel_tv.c 235783 2012-05-22 11:07:44Z kib $");
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
44enum 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 */
50struct 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
91struct video_levels {
92	int blank, black, burst;
93};
94
95struct color_conversion {
96	u16 ry, gy, by, ay;
97	u16 ru, gu, bu, au;
98	u16 rv, gv, bv, av;
99};
100
101static 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 */
223static 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
229static const struct video_levels ntsc_m_levels_composite = {
230	.blank = 225, .black = 267, .burst = 113,
231};
232
233static 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
239static const struct video_levels ntsc_m_levels_svideo = {
240	.blank = 266, .black = 316, .burst = 133,
241};
242
243static 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
249static const struct video_levels ntsc_j_levels_composite = {
250	.blank = 225, .black = 225, .burst = 113,
251};
252
253static 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
259static const struct video_levels ntsc_j_levels_svideo = {
260	.blank = 266, .black = 266, .burst = 133,
261};
262
263static 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
269static const struct video_levels pal_levels_composite = {
270	.blank = 237, .black = 237, .burst = 118,
271};
272
273static 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
279static const struct video_levels pal_levels_svideo = {
280	.blank = 280, .black = 280, .burst = 139,
281};
282
283static 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
289static const struct video_levels pal_m_levels_composite = {
290	.blank = 225, .black = 267, .burst = 113,
291};
292
293static 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
299static const struct video_levels pal_m_levels_svideo = {
300	.blank = 266, .black = 316, .burst = 133,
301};
302
303static 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
309static const struct video_levels pal_n_levels_composite = {
310	.blank = 225, .black = 267, .burst = 118,
311};
312
313static 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
319static const struct video_levels pal_n_levels_svideo = {
320	.blank = 266, .black = 316, .burst = 139,
321};
322
323/*
324 * Component connections
325 */
326static 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
332static 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
338static 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
344static 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
350static const struct video_levels component_levels = {
351	.blank = 279, .black = 279, .burst = 0,
352};
353
354
355struct 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
419static 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
782static struct intel_tv *enc_to_intel_tv(struct drm_encoder *encoder)
783{
784	return container_of(encoder, struct intel_tv, base.base);
785}
786
787static 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
794static void
795intel_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
812static const struct tv_mode *
813intel_tv_mode_lookup(const char *tv_format)
814{
815	int i;
816
817	for (i = 0; i < sizeof(tv_modes) / sizeof(tv_modes[0]); 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
826static const struct tv_mode *
827intel_tv_mode_find(struct intel_tv *intel_tv)
828{
829	return intel_tv_mode_lookup(intel_tv->tv_format);
830}
831
832static enum drm_mode_status
833intel_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
848static bool
849intel_tv_mode_fixup(struct drm_encoder *encoder, 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
872static void
873intel_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
1090static 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 */
1115static int
1116intel_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	I915_WRITE(TV_CTL, tv_ctl);
1159	I915_WRITE(TV_DAC, tv_dac);
1160	POSTING_READ(TV_DAC);
1161
1162	intel_wait_for_vblank(intel_tv->base.base.dev,
1163			      to_intel_crtc(intel_tv->base.base.crtc)->pipe);
1164
1165	type = -1;
1166	tv_dac = I915_READ(TV_DAC);
1167	DRM_DEBUG_KMS("TV detected: %x, %x\n", tv_ctl, tv_dac);
1168	/*
1169	 *  A B C
1170	 *  0 1 1 Composite
1171	 *  1 0 X svideo
1172	 *  0 0 0 Component
1173	 */
1174	if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
1175		DRM_DEBUG_KMS("Detected Composite TV connection\n");
1176		type = DRM_MODE_CONNECTOR_Composite;
1177	} else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
1178		DRM_DEBUG_KMS("Detected S-Video TV connection\n");
1179		type = DRM_MODE_CONNECTOR_SVIDEO;
1180	} else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
1181		DRM_DEBUG_KMS("Detected Component TV connection\n");
1182		type = DRM_MODE_CONNECTOR_Component;
1183	} else {
1184		DRM_DEBUG_KMS("Unrecognised TV connection\n");
1185		type = -1;
1186	}
1187
1188	I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
1189	I915_WRITE(TV_CTL, save_tv_ctl);
1190
1191	/* Restore interrupt config */
1192	if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
1193		mtx_lock(&dev_priv->irq_lock);
1194		i915_enable_pipestat(dev_priv, 0,
1195				     PIPE_HOTPLUG_INTERRUPT_ENABLE |
1196				     PIPE_HOTPLUG_TV_INTERRUPT_ENABLE);
1197		mtx_unlock(&dev_priv->irq_lock);
1198	}
1199
1200	return type;
1201}
1202
1203/*
1204 * Here we set accurate tv format according to connector type
1205 * i.e Component TV should not be assigned by NTSC or PAL
1206 */
1207static void intel_tv_find_better_format(struct drm_connector *connector)
1208{
1209	struct intel_tv *intel_tv = intel_attached_tv(connector);
1210	const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
1211	int i;
1212
1213	if ((intel_tv->type == DRM_MODE_CONNECTOR_Component) ==
1214		tv_mode->component_only)
1215		return;
1216
1217
1218	for (i = 0; i < sizeof(tv_modes) / sizeof(*tv_modes); i++) {
1219		tv_mode = tv_modes + i;
1220
1221		if ((intel_tv->type == DRM_MODE_CONNECTOR_Component) ==
1222			tv_mode->component_only)
1223			break;
1224	}
1225
1226	intel_tv->tv_format = tv_mode->name;
1227	drm_connector_property_set_value(connector,
1228		connector->dev->mode_config.tv_mode_property, i);
1229}
1230
1231/**
1232 * Detect the TV connection.
1233 *
1234 * Currently this always returns CONNECTOR_STATUS_UNKNOWN, as we need to be sure
1235 * we have a pipe programmed in order to probe the TV.
1236 */
1237static enum drm_connector_status
1238intel_tv_detect(struct drm_connector *connector, bool force)
1239{
1240	struct drm_display_mode mode;
1241	struct intel_tv *intel_tv = intel_attached_tv(connector);
1242	int type;
1243
1244	mode = reported_modes[0];
1245	drm_mode_set_crtcinfo(&mode, 0);
1246
1247	if (intel_tv->base.base.crtc && intel_tv->base.base.crtc->enabled) {
1248		type = intel_tv_detect_type(intel_tv, connector);
1249	} else if (force) {
1250		struct intel_load_detect_pipe tmp;
1251
1252		if (intel_get_load_detect_pipe(&intel_tv->base, connector,
1253					       &mode, &tmp)) {
1254			type = intel_tv_detect_type(intel_tv, connector);
1255			intel_release_load_detect_pipe(&intel_tv->base,
1256						       connector,
1257						       &tmp);
1258		} else
1259			return connector_status_unknown;
1260	} else
1261		return connector->status;
1262
1263	if (type < 0)
1264		return connector_status_disconnected;
1265
1266	intel_tv->type = type;
1267	intel_tv_find_better_format(connector);
1268
1269	return connector_status_connected;
1270}
1271
1272static const struct input_res {
1273	const char *name;
1274	int w, h;
1275} input_res_table[] = {
1276	{"640x480", 640, 480},
1277	{"800x600", 800, 600},
1278	{"1024x768", 1024, 768},
1279	{"1280x1024", 1280, 1024},
1280	{"848x480", 848, 480},
1281	{"1280x720", 1280, 720},
1282	{"1920x1080", 1920, 1080},
1283};
1284
1285/*
1286 * Chose preferred mode  according to line number of TV format
1287 */
1288static void
1289intel_tv_chose_preferred_modes(struct drm_connector *connector,
1290			       struct drm_display_mode *mode_ptr)
1291{
1292	struct intel_tv *intel_tv = intel_attached_tv(connector);
1293	const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
1294
1295	if (tv_mode->nbr_end < 480 && mode_ptr->vdisplay == 480)
1296		mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
1297	else if (tv_mode->nbr_end > 480) {
1298		if (tv_mode->progressive == true && tv_mode->nbr_end < 720) {
1299			if (mode_ptr->vdisplay == 720)
1300				mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
1301		} else if (mode_ptr->vdisplay == 1080)
1302				mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
1303	}
1304}
1305
1306/**
1307 * Stub get_modes function.
1308 *
1309 * This should probably return a set of fixed modes, unless we can figure out
1310 * how to probe modes off of TV connections.
1311 */
1312
1313static int
1314intel_tv_get_modes(struct drm_connector *connector)
1315{
1316	struct drm_display_mode *mode_ptr;
1317	struct intel_tv *intel_tv = intel_attached_tv(connector);
1318	const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
1319	int j, count = 0;
1320	u64 tmp;
1321
1322	for (j = 0; j < DRM_ARRAY_SIZE(input_res_table);
1323	     j++) {
1324		const struct input_res *input = &input_res_table[j];
1325		unsigned int hactive_s = input->w;
1326		unsigned int vactive_s = input->h;
1327
1328		if (tv_mode->max_srcw && input->w > tv_mode->max_srcw)
1329			continue;
1330
1331		if (input->w > 1024 && (!tv_mode->progressive
1332					&& !tv_mode->component_only))
1333			continue;
1334
1335		mode_ptr = drm_mode_create(connector->dev);
1336		if (!mode_ptr)
1337			continue;
1338		strncpy(mode_ptr->name, input->name, DRM_DISPLAY_MODE_LEN);
1339
1340		mode_ptr->hdisplay = hactive_s;
1341		mode_ptr->hsync_start = hactive_s + 1;
1342		mode_ptr->hsync_end = hactive_s + 64;
1343		if (mode_ptr->hsync_end <= mode_ptr->hsync_start)
1344			mode_ptr->hsync_end = mode_ptr->hsync_start + 1;
1345		mode_ptr->htotal = hactive_s + 96;
1346
1347		mode_ptr->vdisplay = vactive_s;
1348		mode_ptr->vsync_start = vactive_s + 1;
1349		mode_ptr->vsync_end = vactive_s + 32;
1350		if (mode_ptr->vsync_end <= mode_ptr->vsync_start)
1351			mode_ptr->vsync_end = mode_ptr->vsync_start  + 1;
1352		mode_ptr->vtotal = vactive_s + 33;
1353
1354		tmp = (u64) tv_mode->refresh * mode_ptr->vtotal;
1355		tmp *= mode_ptr->htotal;
1356		tmp = tmp / 1000000;
1357		mode_ptr->clock = (int) tmp;
1358
1359		mode_ptr->type = DRM_MODE_TYPE_DRIVER;
1360		intel_tv_chose_preferred_modes(connector, mode_ptr);
1361		drm_mode_probed_add(connector, mode_ptr);
1362		count++;
1363	}
1364
1365	return count;
1366}
1367
1368static void
1369intel_tv_destroy(struct drm_connector *connector)
1370{
1371#if 0
1372	drm_sysfs_connector_remove(connector);
1373#endif
1374	drm_connector_cleanup(connector);
1375	free(connector, DRM_MEM_KMS);
1376}
1377
1378
1379static int
1380intel_tv_set_property(struct drm_connector *connector, struct drm_property *property,
1381		      uint64_t val)
1382{
1383	struct drm_device *dev = connector->dev;
1384	struct intel_tv *intel_tv = intel_attached_tv(connector);
1385	struct drm_crtc *crtc = intel_tv->base.base.crtc;
1386	int ret = 0;
1387	bool changed = false;
1388
1389	ret = drm_connector_property_set_value(connector, property, val);
1390	if (ret < 0)
1391		goto out;
1392
1393	if (property == dev->mode_config.tv_left_margin_property &&
1394		intel_tv->margin[TV_MARGIN_LEFT] != val) {
1395		intel_tv->margin[TV_MARGIN_LEFT] = val;
1396		changed = true;
1397	} else if (property == dev->mode_config.tv_right_margin_property &&
1398		intel_tv->margin[TV_MARGIN_RIGHT] != val) {
1399		intel_tv->margin[TV_MARGIN_RIGHT] = val;
1400		changed = true;
1401	} else if (property == dev->mode_config.tv_top_margin_property &&
1402		intel_tv->margin[TV_MARGIN_TOP] != val) {
1403		intel_tv->margin[TV_MARGIN_TOP] = val;
1404		changed = true;
1405	} else if (property == dev->mode_config.tv_bottom_margin_property &&
1406		intel_tv->margin[TV_MARGIN_BOTTOM] != val) {
1407		intel_tv->margin[TV_MARGIN_BOTTOM] = val;
1408		changed = true;
1409	} else if (property == dev->mode_config.tv_mode_property) {
1410		if (val >= DRM_ARRAY_SIZE(tv_modes)) {
1411			ret = -EINVAL;
1412			goto out;
1413		}
1414		if (!strcmp(intel_tv->tv_format, tv_modes[val].name))
1415			goto out;
1416
1417		intel_tv->tv_format = tv_modes[val].name;
1418		changed = true;
1419	} else {
1420		ret = -EINVAL;
1421		goto out;
1422	}
1423
1424	if (changed && crtc)
1425		drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
1426				crtc->y, crtc->fb);
1427out:
1428	return ret;
1429}
1430
1431static const struct drm_encoder_helper_funcs intel_tv_helper_funcs = {
1432	.dpms = intel_tv_dpms,
1433	.mode_fixup = intel_tv_mode_fixup,
1434	.prepare = intel_encoder_prepare,
1435	.mode_set = intel_tv_mode_set,
1436	.commit = intel_encoder_commit,
1437};
1438
1439static const struct drm_connector_funcs intel_tv_connector_funcs = {
1440	.dpms = drm_helper_connector_dpms,
1441	.detect = intel_tv_detect,
1442	.destroy = intel_tv_destroy,
1443	.set_property = intel_tv_set_property,
1444	.fill_modes = drm_helper_probe_single_connector_modes,
1445};
1446
1447static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = {
1448	.mode_valid = intel_tv_mode_valid,
1449	.get_modes = intel_tv_get_modes,
1450	.best_encoder = intel_best_encoder,
1451};
1452
1453static const struct drm_encoder_funcs intel_tv_enc_funcs = {
1454	.destroy = intel_encoder_destroy,
1455};
1456
1457/*
1458 * Enumerate the child dev array parsed from VBT to check whether
1459 * the integrated TV is present.
1460 * If it is present, return 1.
1461 * If it is not present, return false.
1462 * If no child dev is parsed from VBT, it assumes that the TV is present.
1463 */
1464static int tv_is_present_in_vbt(struct drm_device *dev)
1465{
1466	struct drm_i915_private *dev_priv = dev->dev_private;
1467	struct child_device_config *p_child;
1468	int i, ret;
1469
1470	if (!dev_priv->child_dev_num)
1471		return 1;
1472
1473	ret = 0;
1474	for (i = 0; i < dev_priv->child_dev_num; i++) {
1475		p_child = dev_priv->child_dev + i;
1476		/*
1477		 * If the device type is not TV, continue.
1478		 */
1479		if (p_child->device_type != DEVICE_TYPE_INT_TV &&
1480			p_child->device_type != DEVICE_TYPE_TV)
1481			continue;
1482		/* Only when the addin_offset is non-zero, it is regarded
1483		 * as present.
1484		 */
1485		if (p_child->addin_offset) {
1486			ret = 1;
1487			break;
1488		}
1489	}
1490	return ret;
1491}
1492
1493void
1494intel_tv_init(struct drm_device *dev)
1495{
1496	struct drm_i915_private *dev_priv = dev->dev_private;
1497	struct drm_connector *connector;
1498	struct intel_tv *intel_tv;
1499	struct intel_encoder *intel_encoder;
1500	struct intel_connector *intel_connector;
1501	u32 tv_dac_on, tv_dac_off, save_tv_dac;
1502	char *tv_format_names[DRM_ARRAY_SIZE(tv_modes)];
1503	int i, initial_mode = 0;
1504
1505	if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
1506		return;
1507
1508	if (!tv_is_present_in_vbt(dev)) {
1509		DRM_DEBUG_KMS("Integrated TV is not present.\n");
1510		return;
1511	}
1512	/* Even if we have an encoder we may not have a connector */
1513	if (!dev_priv->int_tv_support)
1514		return;
1515
1516	/*
1517	 * Sanity check the TV output by checking to see if the
1518	 * DAC register holds a value
1519	 */
1520	save_tv_dac = I915_READ(TV_DAC);
1521
1522	I915_WRITE(TV_DAC, save_tv_dac | TVDAC_STATE_CHG_EN);
1523	tv_dac_on = I915_READ(TV_DAC);
1524
1525	I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
1526	tv_dac_off = I915_READ(TV_DAC);
1527
1528	I915_WRITE(TV_DAC, save_tv_dac);
1529
1530	/*
1531	 * If the register does not hold the state change enable
1532	 * bit, (either as a 0 or a 1), assume it doesn't really
1533	 * exist
1534	 */
1535	if ((tv_dac_on & TVDAC_STATE_CHG_EN) == 0 ||
1536	    (tv_dac_off & TVDAC_STATE_CHG_EN) != 0)
1537		return;
1538
1539	intel_tv = malloc(sizeof(struct intel_tv), DRM_MEM_KMS,
1540	    M_WAITOK | M_ZERO);
1541	intel_connector = malloc(sizeof(struct intel_connector), DRM_MEM_KMS,
1542	    M_WAITOK | M_ZERO);
1543
1544	intel_encoder = &intel_tv->base;
1545	connector = &intel_connector->base;
1546
1547	/* The documentation, for the older chipsets at least, recommend
1548	 * using a polling method rather than hotplug detection for TVs.
1549	 * This is because in order to perform the hotplug detection, the PLLs
1550	 * for the TV must be kept alive increasing power drain and starving
1551	 * bandwidth from other encoders. Notably for instance, it causes
1552	 * pipe underruns on Crestline when this encoder is supposedly idle.
1553	 *
1554	 * More recent chipsets favour HDMI rather than integrated S-Video.
1555	 */
1556	connector->polled = DRM_CONNECTOR_POLL_CONNECT;
1557
1558	drm_connector_init(dev, connector, &intel_tv_connector_funcs,
1559			   DRM_MODE_CONNECTOR_SVIDEO);
1560
1561	drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs,
1562			 DRM_MODE_ENCODER_TVDAC);
1563
1564	intel_connector_attach_encoder(intel_connector, intel_encoder);
1565	intel_encoder->type = INTEL_OUTPUT_TVOUT;
1566	intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
1567	intel_encoder->clone_mask = (1 << INTEL_TV_CLONE_BIT);
1568	intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1));
1569	intel_encoder->base.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
1570	intel_tv->type = DRM_MODE_CONNECTOR_Unknown;
1571
1572	/* BIOS margin values */
1573	intel_tv->margin[TV_MARGIN_LEFT] = 54;
1574	intel_tv->margin[TV_MARGIN_TOP] = 36;
1575	intel_tv->margin[TV_MARGIN_RIGHT] = 46;
1576	intel_tv->margin[TV_MARGIN_BOTTOM] = 37;
1577
1578	intel_tv->tv_format = tv_modes[initial_mode].name;
1579
1580	drm_encoder_helper_add(&intel_encoder->base, &intel_tv_helper_funcs);
1581	drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs);
1582	connector->interlace_allowed = false;
1583	connector->doublescan_allowed = false;
1584
1585	/* Create TV properties then attach current values */
1586	for (i = 0; i < DRM_ARRAY_SIZE(tv_modes); i++)
1587		tv_format_names[i] = __DECONST(char *, tv_modes[i].name);
1588	drm_mode_create_tv_properties(dev,
1589				      DRM_ARRAY_SIZE(tv_modes),
1590				      tv_format_names);
1591
1592	drm_connector_attach_property(connector, dev->mode_config.tv_mode_property,
1593				   initial_mode);
1594	drm_connector_attach_property(connector,
1595				   dev->mode_config.tv_left_margin_property,
1596				   intel_tv->margin[TV_MARGIN_LEFT]);
1597	drm_connector_attach_property(connector,
1598				   dev->mode_config.tv_top_margin_property,
1599				   intel_tv->margin[TV_MARGIN_TOP]);
1600	drm_connector_attach_property(connector,
1601				   dev->mode_config.tv_right_margin_property,
1602				   intel_tv->margin[TV_MARGIN_RIGHT]);
1603	drm_connector_attach_property(connector,
1604				   dev->mode_config.tv_bottom_margin_property,
1605				   intel_tv->margin[TV_MARGIN_BOTTOM]);
1606#if 0
1607	drm_sysfs_connector_add(connector);
1608#endif
1609}
1610