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