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