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