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