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