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