This source file includes following definitions.
- intel_tv_connector_duplicate_state
- enc_to_tv
- intel_attached_tv
- intel_tv_get_hw_state
- intel_enable_tv
- intel_disable_tv
- intel_tv_mode_find
- intel_tv_mode_valid
- intel_tv_mode_vdisplay
- intel_tv_mode_to_mode
- intel_tv_scale_mode_horiz
- intel_tv_scale_mode_vert
- intel_tv_get_config
- intel_tv_source_too_wide
- intel_tv_vert_scaling
- intel_tv_compute_config
- set_tv_mode_timings
- set_color_conversion
- intel_tv_pre_enable
- intel_tv_detect_type
- intel_tv_find_better_format
- intel_tv_detect
- intel_tv_is_preferred_mode
- intel_tv_set_mode_type
- intel_tv_get_modes
- intel_tv_atomic_check
- intel_tv_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 #include <drm/drm_atomic_helper.h>
34 #include <drm/drm_crtc.h>
35 #include <drm/drm_edid.h>
36 #include <drm/i915_drm.h>
37
38 #include "i915_drv.h"
39 #include "intel_connector.h"
40 #include "intel_display_types.h"
41 #include "intel_hotplug.h"
42 #include "intel_tv.h"
43
44 enum tv_margin {
45 TV_MARGIN_LEFT, TV_MARGIN_TOP,
46 TV_MARGIN_RIGHT, TV_MARGIN_BOTTOM
47 };
48
49 struct intel_tv {
50 struct intel_encoder base;
51
52 int type;
53 };
54
55 struct video_levels {
56 u16 blank, black;
57 u8 burst;
58 };
59
60 struct color_conversion {
61 u16 ry, gy, by, ay;
62 u16 ru, gu, bu, au;
63 u16 rv, gv, bv, av;
64 };
65
66 static const u32 filter_table[] = {
67 0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
68 0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
69 0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,
70 0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,
71 0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,
72 0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,
73 0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,
74 0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,
75 0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,
76 0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,
77 0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,
78 0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,
79 0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,
80 0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,
81 0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,
82 0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
83 0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
84 0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,
85 0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,
86 0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,
87 0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,
88 0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,
89 0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,
90 0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,
91 0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,
92 0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,
93 0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,
94 0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,
95 0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,
96 0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,
97 0x36403000, 0x2D002CC0, 0x30003640, 0x2D0036C0,
98 0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,
99 0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,
100 0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,
101 0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,
102 0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,
103 0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,
104 0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,
105 0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,
106 0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,
107 0x28003100, 0x28002F00, 0x00003100, 0x36403000,
108 0x2D002CC0, 0x30003640, 0x2D0036C0,
109 0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,
110 0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,
111 0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,
112 0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,
113 0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,
114 0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,
115 0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,
116 0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,
117 0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,
118 0x28003100, 0x28002F00, 0x00003100,
119 };
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 static const struct color_conversion ntsc_m_csc_composite = {
189 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104,
190 .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200,
191 .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200,
192 };
193
194 static const struct video_levels ntsc_m_levels_composite = {
195 .blank = 225, .black = 267, .burst = 113,
196 };
197
198 static const struct color_conversion ntsc_m_csc_svideo = {
199 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133,
200 .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200,
201 .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200,
202 };
203
204 static const struct video_levels ntsc_m_levels_svideo = {
205 .blank = 266, .black = 316, .burst = 133,
206 };
207
208 static const struct color_conversion ntsc_j_csc_composite = {
209 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0119,
210 .ru = 0x074c, .gu = 0x0546, .bu = 0x05ec, .au = 0x0200,
211 .rv = 0x035a, .gv = 0x0322, .bv = 0x06e1, .av = 0x0200,
212 };
213
214 static const struct video_levels ntsc_j_levels_composite = {
215 .blank = 225, .black = 225, .burst = 113,
216 };
217
218 static const struct color_conversion ntsc_j_csc_svideo = {
219 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x014c,
220 .ru = 0x0788, .gu = 0x0581, .bu = 0x0322, .au = 0x0200,
221 .rv = 0x0399, .gv = 0x0356, .bv = 0x070a, .av = 0x0200,
222 };
223
224 static const struct video_levels ntsc_j_levels_svideo = {
225 .blank = 266, .black = 266, .burst = 133,
226 };
227
228 static const struct color_conversion pal_csc_composite = {
229 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0113,
230 .ru = 0x0745, .gu = 0x053f, .bu = 0x05e1, .au = 0x0200,
231 .rv = 0x0353, .gv = 0x031c, .bv = 0x06dc, .av = 0x0200,
232 };
233
234 static const struct video_levels pal_levels_composite = {
235 .blank = 237, .black = 237, .burst = 118,
236 };
237
238 static const struct color_conversion pal_csc_svideo = {
239 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0145,
240 .ru = 0x0780, .gu = 0x0579, .bu = 0x031c, .au = 0x0200,
241 .rv = 0x0390, .gv = 0x034f, .bv = 0x0705, .av = 0x0200,
242 };
243
244 static const struct video_levels pal_levels_svideo = {
245 .blank = 280, .black = 280, .burst = 139,
246 };
247
248 static const struct color_conversion pal_m_csc_composite = {
249 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104,
250 .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200,
251 .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200,
252 };
253
254 static const struct video_levels pal_m_levels_composite = {
255 .blank = 225, .black = 267, .burst = 113,
256 };
257
258 static const struct color_conversion pal_m_csc_svideo = {
259 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133,
260 .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200,
261 .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200,
262 };
263
264 static const struct video_levels pal_m_levels_svideo = {
265 .blank = 266, .black = 316, .burst = 133,
266 };
267
268 static const struct color_conversion pal_n_csc_composite = {
269 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104,
270 .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200,
271 .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200,
272 };
273
274 static const struct video_levels pal_n_levels_composite = {
275 .blank = 225, .black = 267, .burst = 118,
276 };
277
278 static const struct color_conversion pal_n_csc_svideo = {
279 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133,
280 .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200,
281 .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200,
282 };
283
284 static const struct video_levels pal_n_levels_svideo = {
285 .blank = 266, .black = 316, .burst = 139,
286 };
287
288
289
290
291 static const struct color_conversion sdtv_csc_yprpb = {
292 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0145,
293 .ru = 0x0559, .gu = 0x0353, .bu = 0x0100, .au = 0x0200,
294 .rv = 0x0100, .gv = 0x03ad, .bv = 0x074d, .av = 0x0200,
295 };
296
297 static const struct color_conversion hdtv_csc_yprpb = {
298 .ry = 0x05b3, .gy = 0x016e, .by = 0x0728, .ay = 0x0145,
299 .ru = 0x07d5, .gu = 0x038b, .bu = 0x0100, .au = 0x0200,
300 .rv = 0x0100, .gv = 0x03d1, .bv = 0x06bc, .av = 0x0200,
301 };
302
303 static const struct video_levels component_levels = {
304 .blank = 279, .black = 279, .burst = 0,
305 };
306
307
308 struct tv_mode {
309 const char *name;
310
311 u32 clock;
312 u16 refresh;
313 u8 oversample;
314 u8 hsync_end;
315 u16 hblank_start, hblank_end, htotal;
316 bool progressive : 1, trilevel_sync : 1, component_only : 1;
317 u8 vsync_start_f1, vsync_start_f2, vsync_len;
318 bool veq_ena : 1;
319 u8 veq_start_f1, veq_start_f2, veq_len;
320 u8 vi_end_f1, vi_end_f2;
321 u16 nbr_end;
322 bool burst_ena : 1;
323 u8 hburst_start, hburst_len;
324 u8 vburst_start_f1;
325 u16 vburst_end_f1;
326 u8 vburst_start_f2;
327 u16 vburst_end_f2;
328 u8 vburst_start_f3;
329 u16 vburst_end_f3;
330 u8 vburst_start_f4;
331 u16 vburst_end_f4;
332
333
334
335 u16 dda2_size, dda3_size;
336 u8 dda1_inc;
337 u16 dda2_inc, dda3_inc;
338 u32 sc_reset;
339 bool pal_burst : 1;
340
341
342
343 const struct video_levels *composite_levels, *svideo_levels;
344 const struct color_conversion *composite_color, *svideo_color;
345 const u32 *filter_table;
346 };
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379 static const struct tv_mode tv_modes[] = {
380 {
381 .name = "NTSC-M",
382 .clock = 108000,
383 .refresh = 59940,
384 .oversample = 8,
385 .component_only = false,
386
387
388 .hsync_end = 64, .hblank_end = 124,
389 .hblank_start = 836, .htotal = 857,
390
391 .progressive = false, .trilevel_sync = false,
392
393 .vsync_start_f1 = 6, .vsync_start_f2 = 7,
394 .vsync_len = 6,
395
396 .veq_ena = true, .veq_start_f1 = 0,
397 .veq_start_f2 = 1, .veq_len = 18,
398
399 .vi_end_f1 = 20, .vi_end_f2 = 21,
400 .nbr_end = 240,
401
402 .burst_ena = true,
403 .hburst_start = 72, .hburst_len = 34,
404 .vburst_start_f1 = 9, .vburst_end_f1 = 240,
405 .vburst_start_f2 = 10, .vburst_end_f2 = 240,
406 .vburst_start_f3 = 9, .vburst_end_f3 = 240,
407 .vburst_start_f4 = 10, .vburst_end_f4 = 240,
408
409
410 .dda1_inc = 135,
411 .dda2_inc = 20800, .dda2_size = 27456,
412 .dda3_inc = 0, .dda3_size = 0,
413 .sc_reset = TV_SC_RESET_EVERY_4,
414 .pal_burst = false,
415
416 .composite_levels = &ntsc_m_levels_composite,
417 .composite_color = &ntsc_m_csc_composite,
418 .svideo_levels = &ntsc_m_levels_svideo,
419 .svideo_color = &ntsc_m_csc_svideo,
420
421 .filter_table = filter_table,
422 },
423 {
424 .name = "NTSC-443",
425 .clock = 108000,
426 .refresh = 59940,
427 .oversample = 8,
428 .component_only = false,
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
452 .dda1_inc = 168,
453 .dda2_inc = 4093, .dda2_size = 27456,
454 .dda3_inc = 310, .dda3_size = 525,
455 .sc_reset = TV_SC_RESET_NEVER,
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-J",
467 .clock = 108000,
468 .refresh = 59940,
469 .oversample = 8,
470 .component_only = false,
471
472
473 .hsync_end = 64, .hblank_end = 124,
474 .hblank_start = 836, .htotal = 857,
475
476 .progressive = false, .trilevel_sync = false,
477
478 .vsync_start_f1 = 6, .vsync_start_f2 = 7,
479 .vsync_len = 6,
480
481 .veq_ena = true, .veq_start_f1 = 0,
482 .veq_start_f2 = 1, .veq_len = 18,
483
484 .vi_end_f1 = 20, .vi_end_f2 = 21,
485 .nbr_end = 240,
486
487 .burst_ena = true,
488 .hburst_start = 72, .hburst_len = 34,
489 .vburst_start_f1 = 9, .vburst_end_f1 = 240,
490 .vburst_start_f2 = 10, .vburst_end_f2 = 240,
491 .vburst_start_f3 = 9, .vburst_end_f3 = 240,
492 .vburst_start_f4 = 10, .vburst_end_f4 = 240,
493
494
495 .dda1_inc = 135,
496 .dda2_inc = 20800, .dda2_size = 27456,
497 .dda3_inc = 0, .dda3_size = 0,
498 .sc_reset = TV_SC_RESET_EVERY_4,
499 .pal_burst = false,
500
501 .composite_levels = &ntsc_j_levels_composite,
502 .composite_color = &ntsc_j_csc_composite,
503 .svideo_levels = &ntsc_j_levels_svideo,
504 .svideo_color = &ntsc_j_csc_svideo,
505
506 .filter_table = filter_table,
507 },
508 {
509 .name = "PAL-M",
510 .clock = 108000,
511 .refresh = 59940,
512 .oversample = 8,
513 .component_only = false,
514
515
516 .hsync_end = 64, .hblank_end = 124,
517 .hblank_start = 836, .htotal = 857,
518
519 .progressive = false, .trilevel_sync = false,
520
521 .vsync_start_f1 = 6, .vsync_start_f2 = 7,
522 .vsync_len = 6,
523
524 .veq_ena = true, .veq_start_f1 = 0,
525 .veq_start_f2 = 1, .veq_len = 18,
526
527 .vi_end_f1 = 20, .vi_end_f2 = 21,
528 .nbr_end = 240,
529
530 .burst_ena = true,
531 .hburst_start = 72, .hburst_len = 34,
532 .vburst_start_f1 = 9, .vburst_end_f1 = 240,
533 .vburst_start_f2 = 10, .vburst_end_f2 = 240,
534 .vburst_start_f3 = 9, .vburst_end_f3 = 240,
535 .vburst_start_f4 = 10, .vburst_end_f4 = 240,
536
537
538 .dda1_inc = 135,
539 .dda2_inc = 16704, .dda2_size = 27456,
540 .dda3_inc = 0, .dda3_size = 0,
541 .sc_reset = TV_SC_RESET_EVERY_8,
542 .pal_burst = true,
543
544 .composite_levels = &pal_m_levels_composite,
545 .composite_color = &pal_m_csc_composite,
546 .svideo_levels = &pal_m_levels_svideo,
547 .svideo_color = &pal_m_csc_svideo,
548
549 .filter_table = filter_table,
550 },
551 {
552
553 .name = "PAL-N",
554 .clock = 108000,
555 .refresh = 50000,
556 .oversample = 8,
557 .component_only = false,
558
559 .hsync_end = 64, .hblank_end = 128,
560 .hblank_start = 844, .htotal = 863,
561
562 .progressive = false, .trilevel_sync = false,
563
564
565 .vsync_start_f1 = 6, .vsync_start_f2 = 7,
566 .vsync_len = 6,
567
568 .veq_ena = true, .veq_start_f1 = 0,
569 .veq_start_f2 = 1, .veq_len = 18,
570
571 .vi_end_f1 = 24, .vi_end_f2 = 25,
572 .nbr_end = 286,
573
574 .burst_ena = true,
575 .hburst_start = 73, .hburst_len = 34,
576 .vburst_start_f1 = 8, .vburst_end_f1 = 285,
577 .vburst_start_f2 = 8, .vburst_end_f2 = 286,
578 .vburst_start_f3 = 9, .vburst_end_f3 = 286,
579 .vburst_start_f4 = 9, .vburst_end_f4 = 285,
580
581
582
583 .dda1_inc = 135,
584 .dda2_inc = 23578, .dda2_size = 27648,
585 .dda3_inc = 134, .dda3_size = 625,
586 .sc_reset = TV_SC_RESET_EVERY_8,
587 .pal_burst = true,
588
589 .composite_levels = &pal_n_levels_composite,
590 .composite_color = &pal_n_csc_composite,
591 .svideo_levels = &pal_n_levels_svideo,
592 .svideo_color = &pal_n_csc_svideo,
593
594 .filter_table = filter_table,
595 },
596 {
597
598 .name = "PAL",
599 .clock = 108000,
600 .refresh = 50000,
601 .oversample = 8,
602 .component_only = false,
603
604 .hsync_end = 64, .hblank_end = 142,
605 .hblank_start = 844, .htotal = 863,
606
607 .progressive = false, .trilevel_sync = false,
608
609 .vsync_start_f1 = 5, .vsync_start_f2 = 6,
610 .vsync_len = 5,
611
612 .veq_ena = true, .veq_start_f1 = 0,
613 .veq_start_f2 = 1, .veq_len = 15,
614
615 .vi_end_f1 = 24, .vi_end_f2 = 25,
616 .nbr_end = 286,
617
618 .burst_ena = true,
619 .hburst_start = 73, .hburst_len = 32,
620 .vburst_start_f1 = 8, .vburst_end_f1 = 285,
621 .vburst_start_f2 = 8, .vburst_end_f2 = 286,
622 .vburst_start_f3 = 9, .vburst_end_f3 = 286,
623 .vburst_start_f4 = 9, .vburst_end_f4 = 285,
624
625
626 .dda1_inc = 168,
627 .dda2_inc = 4122, .dda2_size = 27648,
628 .dda3_inc = 67, .dda3_size = 625,
629 .sc_reset = TV_SC_RESET_EVERY_8,
630 .pal_burst = true,
631
632 .composite_levels = &pal_levels_composite,
633 .composite_color = &pal_csc_composite,
634 .svideo_levels = &pal_levels_svideo,
635 .svideo_color = &pal_csc_svideo,
636
637 .filter_table = filter_table,
638 },
639 {
640 .name = "480p",
641 .clock = 108000,
642 .refresh = 59940,
643 .oversample = 4,
644 .component_only = true,
645
646 .hsync_end = 64, .hblank_end = 122,
647 .hblank_start = 842, .htotal = 857,
648
649 .progressive = true, .trilevel_sync = false,
650
651 .vsync_start_f1 = 12, .vsync_start_f2 = 12,
652 .vsync_len = 12,
653
654 .veq_ena = false,
655
656 .vi_end_f1 = 44, .vi_end_f2 = 44,
657 .nbr_end = 479,
658
659 .burst_ena = false,
660
661 .filter_table = filter_table,
662 },
663 {
664 .name = "576p",
665 .clock = 108000,
666 .refresh = 50000,
667 .oversample = 4,
668 .component_only = true,
669
670 .hsync_end = 64, .hblank_end = 139,
671 .hblank_start = 859, .htotal = 863,
672
673 .progressive = true, .trilevel_sync = false,
674
675 .vsync_start_f1 = 10, .vsync_start_f2 = 10,
676 .vsync_len = 10,
677
678 .veq_ena = false,
679
680 .vi_end_f1 = 48, .vi_end_f2 = 48,
681 .nbr_end = 575,
682
683 .burst_ena = false,
684
685 .filter_table = filter_table,
686 },
687 {
688 .name = "720p@60Hz",
689 .clock = 148500,
690 .refresh = 60000,
691 .oversample = 2,
692 .component_only = true,
693
694 .hsync_end = 80, .hblank_end = 300,
695 .hblank_start = 1580, .htotal = 1649,
696
697 .progressive = true, .trilevel_sync = true,
698
699 .vsync_start_f1 = 10, .vsync_start_f2 = 10,
700 .vsync_len = 10,
701
702 .veq_ena = false,
703
704 .vi_end_f1 = 29, .vi_end_f2 = 29,
705 .nbr_end = 719,
706
707 .burst_ena = false,
708
709 .filter_table = filter_table,
710 },
711 {
712 .name = "720p@50Hz",
713 .clock = 148500,
714 .refresh = 50000,
715 .oversample = 2,
716 .component_only = true,
717
718 .hsync_end = 80, .hblank_end = 300,
719 .hblank_start = 1580, .htotal = 1979,
720
721 .progressive = true, .trilevel_sync = true,
722
723 .vsync_start_f1 = 10, .vsync_start_f2 = 10,
724 .vsync_len = 10,
725
726 .veq_ena = false,
727
728 .vi_end_f1 = 29, .vi_end_f2 = 29,
729 .nbr_end = 719,
730
731 .burst_ena = false,
732
733 .filter_table = filter_table,
734 },
735 {
736 .name = "1080i@50Hz",
737 .clock = 148500,
738 .refresh = 50000,
739 .oversample = 2,
740 .component_only = true,
741
742 .hsync_end = 88, .hblank_end = 235,
743 .hblank_start = 2155, .htotal = 2639,
744
745 .progressive = false, .trilevel_sync = true,
746
747 .vsync_start_f1 = 4, .vsync_start_f2 = 5,
748 .vsync_len = 10,
749
750 .veq_ena = true, .veq_start_f1 = 4,
751 .veq_start_f2 = 4, .veq_len = 10,
752
753
754 .vi_end_f1 = 21, .vi_end_f2 = 22,
755 .nbr_end = 539,
756
757 .burst_ena = false,
758
759 .filter_table = filter_table,
760 },
761 {
762 .name = "1080i@60Hz",
763 .clock = 148500,
764 .refresh = 60000,
765 .oversample = 2,
766 .component_only = true,
767
768 .hsync_end = 88, .hblank_end = 235,
769 .hblank_start = 2155, .htotal = 2199,
770
771 .progressive = false, .trilevel_sync = true,
772
773 .vsync_start_f1 = 4, .vsync_start_f2 = 5,
774 .vsync_len = 10,
775
776 .veq_ena = true, .veq_start_f1 = 4,
777 .veq_start_f2 = 4, .veq_len = 10,
778
779
780 .vi_end_f1 = 21, .vi_end_f2 = 22,
781 .nbr_end = 539,
782
783 .burst_ena = false,
784
785 .filter_table = filter_table,
786 },
787
788 {
789 .name = "1080p@30Hz",
790 .clock = 148500,
791 .refresh = 30000,
792 .oversample = 2,
793 .component_only = true,
794
795 .hsync_end = 88, .hblank_end = 235,
796 .hblank_start = 2155, .htotal = 2199,
797
798 .progressive = true, .trilevel_sync = true,
799
800 .vsync_start_f1 = 8, .vsync_start_f2 = 8,
801 .vsync_len = 10,
802
803 .veq_ena = false, .veq_start_f1 = 0,
804 .veq_start_f2 = 0, .veq_len = 0,
805
806 .vi_end_f1 = 44, .vi_end_f2 = 44,
807 .nbr_end = 1079,
808
809 .burst_ena = false,
810
811 .filter_table = filter_table,
812 },
813
814 {
815 .name = "1080p@50Hz",
816 .clock = 148500,
817 .refresh = 50000,
818 .oversample = 1,
819 .component_only = true,
820
821 .hsync_end = 88, .hblank_end = 235,
822 .hblank_start = 2155, .htotal = 2639,
823
824 .progressive = true, .trilevel_sync = true,
825
826 .vsync_start_f1 = 8, .vsync_start_f2 = 8,
827 .vsync_len = 10,
828
829 .veq_ena = false, .veq_start_f1 = 0,
830 .veq_start_f2 = 0, .veq_len = 0,
831
832 .vi_end_f1 = 44, .vi_end_f2 = 44,
833 .nbr_end = 1079,
834
835 .burst_ena = false,
836
837 .filter_table = filter_table,
838 },
839
840 {
841 .name = "1080p@60Hz",
842 .clock = 148500,
843 .refresh = 60000,
844 .oversample = 1,
845 .component_only = true,
846
847 .hsync_end = 88, .hblank_end = 235,
848 .hblank_start = 2155, .htotal = 2199,
849
850 .progressive = true, .trilevel_sync = true,
851
852 .vsync_start_f1 = 8, .vsync_start_f2 = 8,
853 .vsync_len = 10,
854
855 .veq_ena = false, .veq_start_f1 = 0,
856 .veq_start_f2 = 0, .veq_len = 0,
857
858 .vi_end_f1 = 44, .vi_end_f2 = 44,
859 .nbr_end = 1079,
860
861 .burst_ena = false,
862
863 .filter_table = filter_table,
864 },
865 };
866
867 struct intel_tv_connector_state {
868 struct drm_connector_state base;
869
870
871
872
873
874 struct {
875 u16 top, bottom;
876 } margins;
877
878 bool bypass_vfilter;
879 };
880
881 #define to_intel_tv_connector_state(x) container_of(x, struct intel_tv_connector_state, base)
882
883 static struct drm_connector_state *
884 intel_tv_connector_duplicate_state(struct drm_connector *connector)
885 {
886 struct intel_tv_connector_state *state;
887
888 state = kmemdup(connector->state, sizeof(*state), GFP_KERNEL);
889 if (!state)
890 return NULL;
891
892 __drm_atomic_helper_connector_duplicate_state(connector, &state->base);
893 return &state->base;
894 }
895
896 static struct intel_tv *enc_to_tv(struct intel_encoder *encoder)
897 {
898 return container_of(encoder, struct intel_tv, base);
899 }
900
901 static struct intel_tv *intel_attached_tv(struct drm_connector *connector)
902 {
903 return enc_to_tv(intel_attached_encoder(connector));
904 }
905
906 static bool
907 intel_tv_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe)
908 {
909 struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
910 u32 tmp = I915_READ(TV_CTL);
911
912 *pipe = (tmp & TV_ENC_PIPE_SEL_MASK) >> TV_ENC_PIPE_SEL_SHIFT;
913
914 return tmp & TV_ENC_ENABLE;
915 }
916
917 static void
918 intel_enable_tv(struct intel_encoder *encoder,
919 const struct intel_crtc_state *pipe_config,
920 const struct drm_connector_state *conn_state)
921 {
922 struct drm_device *dev = encoder->base.dev;
923 struct drm_i915_private *dev_priv = to_i915(dev);
924
925
926 intel_wait_for_vblank(dev_priv,
927 to_intel_crtc(pipe_config->base.crtc)->pipe);
928
929 I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE);
930 }
931
932 static void
933 intel_disable_tv(struct intel_encoder *encoder,
934 const struct intel_crtc_state *old_crtc_state,
935 const struct drm_connector_state *old_conn_state)
936 {
937 struct drm_device *dev = encoder->base.dev;
938 struct drm_i915_private *dev_priv = to_i915(dev);
939
940 I915_WRITE(TV_CTL, I915_READ(TV_CTL) & ~TV_ENC_ENABLE);
941 }
942
943 static const struct tv_mode *intel_tv_mode_find(const struct drm_connector_state *conn_state)
944 {
945 int format = conn_state->tv.mode;
946
947 return &tv_modes[format];
948 }
949
950 static enum drm_mode_status
951 intel_tv_mode_valid(struct drm_connector *connector,
952 struct drm_display_mode *mode)
953 {
954 const struct tv_mode *tv_mode = intel_tv_mode_find(connector->state);
955 int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
956
957 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
958 return MODE_NO_DBLESCAN;
959
960 if (mode->clock > max_dotclk)
961 return MODE_CLOCK_HIGH;
962
963
964 if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode) * 1000)
965 < 1000)
966 return MODE_OK;
967
968 return MODE_CLOCK_RANGE;
969 }
970
971 static int
972 intel_tv_mode_vdisplay(const struct tv_mode *tv_mode)
973 {
974 if (tv_mode->progressive)
975 return tv_mode->nbr_end + 1;
976 else
977 return 2 * (tv_mode->nbr_end + 1);
978 }
979
980 static void
981 intel_tv_mode_to_mode(struct drm_display_mode *mode,
982 const struct tv_mode *tv_mode)
983 {
984 mode->clock = tv_mode->clock /
985 (tv_mode->oversample >> !tv_mode->progressive);
986
987
988
989
990
991
992
993
994
995
996
997
998 mode->hdisplay =
999 tv_mode->hblank_start - tv_mode->hblank_end;
1000 mode->hsync_start = mode->hdisplay +
1001 tv_mode->htotal - tv_mode->hblank_start;
1002 mode->hsync_end = mode->hsync_start +
1003 tv_mode->hsync_end;
1004 mode->htotal = tv_mode->htotal + 1;
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017 mode->vdisplay = intel_tv_mode_vdisplay(tv_mode);
1018 if (tv_mode->progressive) {
1019 mode->vsync_start = mode->vdisplay +
1020 tv_mode->vsync_start_f1 + 1;
1021 mode->vsync_end = mode->vsync_start +
1022 tv_mode->vsync_len;
1023 mode->vtotal = mode->vdisplay +
1024 tv_mode->vi_end_f1 + 1;
1025 } else {
1026 mode->vsync_start = mode->vdisplay +
1027 tv_mode->vsync_start_f1 + 1 +
1028 tv_mode->vsync_start_f2 + 1;
1029 mode->vsync_end = mode->vsync_start +
1030 2 * tv_mode->vsync_len;
1031 mode->vtotal = mode->vdisplay +
1032 tv_mode->vi_end_f1 + 1 +
1033 tv_mode->vi_end_f2 + 1;
1034 }
1035
1036
1037 mode->flags = 0;
1038
1039 mode->vrefresh = 0;
1040 mode->vrefresh = drm_mode_vrefresh(mode);
1041
1042 snprintf(mode->name, sizeof(mode->name),
1043 "%dx%d%c (%s)",
1044 mode->hdisplay, mode->vdisplay,
1045 tv_mode->progressive ? 'p' : 'i',
1046 tv_mode->name);
1047 }
1048
1049 static void intel_tv_scale_mode_horiz(struct drm_display_mode *mode,
1050 int hdisplay, int left_margin,
1051 int right_margin)
1052 {
1053 int hsync_start = mode->hsync_start - mode->hdisplay + right_margin;
1054 int hsync_end = mode->hsync_end - mode->hdisplay + right_margin;
1055 int new_htotal = mode->htotal * hdisplay /
1056 (mode->hdisplay - left_margin - right_margin);
1057
1058 mode->clock = mode->clock * new_htotal / mode->htotal;
1059
1060 mode->hdisplay = hdisplay;
1061 mode->hsync_start = hdisplay + hsync_start * new_htotal / mode->htotal;
1062 mode->hsync_end = hdisplay + hsync_end * new_htotal / mode->htotal;
1063 mode->htotal = new_htotal;
1064 }
1065
1066 static void intel_tv_scale_mode_vert(struct drm_display_mode *mode,
1067 int vdisplay, int top_margin,
1068 int bottom_margin)
1069 {
1070 int vsync_start = mode->vsync_start - mode->vdisplay + bottom_margin;
1071 int vsync_end = mode->vsync_end - mode->vdisplay + bottom_margin;
1072 int new_vtotal = mode->vtotal * vdisplay /
1073 (mode->vdisplay - top_margin - bottom_margin);
1074
1075 mode->clock = mode->clock * new_vtotal / mode->vtotal;
1076
1077 mode->vdisplay = vdisplay;
1078 mode->vsync_start = vdisplay + vsync_start * new_vtotal / mode->vtotal;
1079 mode->vsync_end = vdisplay + vsync_end * new_vtotal / mode->vtotal;
1080 mode->vtotal = new_vtotal;
1081 }
1082
1083 static void
1084 intel_tv_get_config(struct intel_encoder *encoder,
1085 struct intel_crtc_state *pipe_config)
1086 {
1087 struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1088 struct drm_display_mode *adjusted_mode =
1089 &pipe_config->base.adjusted_mode;
1090 struct drm_display_mode mode = {};
1091 u32 tv_ctl, hctl1, hctl3, vctl1, vctl2, tmp;
1092 struct tv_mode tv_mode = {};
1093 int hdisplay = adjusted_mode->crtc_hdisplay;
1094 int vdisplay = adjusted_mode->crtc_vdisplay;
1095 int xsize, ysize, xpos, ypos;
1096
1097 pipe_config->output_types |= BIT(INTEL_OUTPUT_TVOUT);
1098
1099 tv_ctl = I915_READ(TV_CTL);
1100 hctl1 = I915_READ(TV_H_CTL_1);
1101 hctl3 = I915_READ(TV_H_CTL_3);
1102 vctl1 = I915_READ(TV_V_CTL_1);
1103 vctl2 = I915_READ(TV_V_CTL_2);
1104
1105 tv_mode.htotal = (hctl1 & TV_HTOTAL_MASK) >> TV_HTOTAL_SHIFT;
1106 tv_mode.hsync_end = (hctl1 & TV_HSYNC_END_MASK) >> TV_HSYNC_END_SHIFT;
1107
1108 tv_mode.hblank_start = (hctl3 & TV_HBLANK_START_MASK) >> TV_HBLANK_START_SHIFT;
1109 tv_mode.hblank_end = (hctl3 & TV_HSYNC_END_MASK) >> TV_HBLANK_END_SHIFT;
1110
1111 tv_mode.nbr_end = (vctl1 & TV_NBR_END_MASK) >> TV_NBR_END_SHIFT;
1112 tv_mode.vi_end_f1 = (vctl1 & TV_VI_END_F1_MASK) >> TV_VI_END_F1_SHIFT;
1113 tv_mode.vi_end_f2 = (vctl1 & TV_VI_END_F2_MASK) >> TV_VI_END_F2_SHIFT;
1114
1115 tv_mode.vsync_len = (vctl2 & TV_VSYNC_LEN_MASK) >> TV_VSYNC_LEN_SHIFT;
1116 tv_mode.vsync_start_f1 = (vctl2 & TV_VSYNC_START_F1_MASK) >> TV_VSYNC_START_F1_SHIFT;
1117 tv_mode.vsync_start_f2 = (vctl2 & TV_VSYNC_START_F2_MASK) >> TV_VSYNC_START_F2_SHIFT;
1118
1119 tv_mode.clock = pipe_config->port_clock;
1120
1121 tv_mode.progressive = tv_ctl & TV_PROGRESSIVE;
1122
1123 switch (tv_ctl & TV_OVERSAMPLE_MASK) {
1124 case TV_OVERSAMPLE_8X:
1125 tv_mode.oversample = 8;
1126 break;
1127 case TV_OVERSAMPLE_4X:
1128 tv_mode.oversample = 4;
1129 break;
1130 case TV_OVERSAMPLE_2X:
1131 tv_mode.oversample = 2;
1132 break;
1133 default:
1134 tv_mode.oversample = 1;
1135 break;
1136 }
1137
1138 tmp = I915_READ(TV_WIN_POS);
1139 xpos = tmp >> 16;
1140 ypos = tmp & 0xffff;
1141
1142 tmp = I915_READ(TV_WIN_SIZE);
1143 xsize = tmp >> 16;
1144 ysize = tmp & 0xffff;
1145
1146 intel_tv_mode_to_mode(&mode, &tv_mode);
1147
1148 DRM_DEBUG_KMS("TV mode:\n");
1149 drm_mode_debug_printmodeline(&mode);
1150
1151 intel_tv_scale_mode_horiz(&mode, hdisplay,
1152 xpos, mode.hdisplay - xsize - xpos);
1153 intel_tv_scale_mode_vert(&mode, vdisplay,
1154 ypos, mode.vdisplay - ysize - ypos);
1155
1156 adjusted_mode->crtc_clock = mode.clock;
1157 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
1158 adjusted_mode->crtc_clock /= 2;
1159
1160
1161 if (IS_I965GM(dev_priv))
1162 adjusted_mode->private_flags |=
1163 I915_MODE_FLAG_USE_SCANLINE_COUNTER;
1164 }
1165
1166 static bool intel_tv_source_too_wide(struct drm_i915_private *dev_priv,
1167 int hdisplay)
1168 {
1169 return IS_GEN(dev_priv, 3) && hdisplay > 1024;
1170 }
1171
1172 static bool intel_tv_vert_scaling(const struct drm_display_mode *tv_mode,
1173 const struct drm_connector_state *conn_state,
1174 int vdisplay)
1175 {
1176 return tv_mode->crtc_vdisplay -
1177 conn_state->tv.margins.top -
1178 conn_state->tv.margins.bottom !=
1179 vdisplay;
1180 }
1181
1182 static int
1183 intel_tv_compute_config(struct intel_encoder *encoder,
1184 struct intel_crtc_state *pipe_config,
1185 struct drm_connector_state *conn_state)
1186 {
1187 struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1188 struct intel_tv_connector_state *tv_conn_state =
1189 to_intel_tv_connector_state(conn_state);
1190 const struct tv_mode *tv_mode = intel_tv_mode_find(conn_state);
1191 struct drm_display_mode *adjusted_mode =
1192 &pipe_config->base.adjusted_mode;
1193 int hdisplay = adjusted_mode->crtc_hdisplay;
1194 int vdisplay = adjusted_mode->crtc_vdisplay;
1195
1196 if (!tv_mode)
1197 return -EINVAL;
1198
1199 if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
1200 return -EINVAL;
1201
1202 pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
1203
1204 DRM_DEBUG_KMS("forcing bpc to 8 for TV\n");
1205 pipe_config->pipe_bpp = 8*3;
1206
1207 pipe_config->port_clock = tv_mode->clock;
1208
1209 intel_tv_mode_to_mode(adjusted_mode, tv_mode);
1210 drm_mode_set_crtcinfo(adjusted_mode, 0);
1211
1212 if (intel_tv_source_too_wide(dev_priv, hdisplay) ||
1213 !intel_tv_vert_scaling(adjusted_mode, conn_state, vdisplay)) {
1214 int extra, top, bottom;
1215
1216 extra = adjusted_mode->crtc_vdisplay - vdisplay;
1217
1218 if (extra < 0) {
1219 DRM_DEBUG_KMS("No vertical scaling for >1024 pixel wide modes\n");
1220 return -EINVAL;
1221 }
1222
1223
1224
1225
1226 top = conn_state->tv.margins.top;
1227 bottom = conn_state->tv.margins.bottom;
1228
1229 if (top + bottom)
1230 top = extra * top / (top + bottom);
1231 else
1232 top = extra / 2;
1233 bottom = extra - top;
1234
1235 tv_conn_state->margins.top = top;
1236 tv_conn_state->margins.bottom = bottom;
1237
1238 tv_conn_state->bypass_vfilter = true;
1239
1240 if (!tv_mode->progressive) {
1241 adjusted_mode->clock /= 2;
1242 adjusted_mode->crtc_clock /= 2;
1243 adjusted_mode->flags |= DRM_MODE_FLAG_INTERLACE;
1244 }
1245 } else {
1246 tv_conn_state->margins.top = conn_state->tv.margins.top;
1247 tv_conn_state->margins.bottom = conn_state->tv.margins.bottom;
1248
1249 tv_conn_state->bypass_vfilter = false;
1250 }
1251
1252 DRM_DEBUG_KMS("TV mode:\n");
1253 drm_mode_debug_printmodeline(adjusted_mode);
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320 intel_tv_scale_mode_horiz(adjusted_mode, hdisplay,
1321 conn_state->tv.margins.left,
1322 conn_state->tv.margins.right);
1323 intel_tv_scale_mode_vert(adjusted_mode, vdisplay,
1324 tv_conn_state->margins.top,
1325 tv_conn_state->margins.bottom);
1326 drm_mode_set_crtcinfo(adjusted_mode, 0);
1327 adjusted_mode->name[0] = '\0';
1328
1329
1330 if (IS_I965GM(dev_priv))
1331 adjusted_mode->private_flags |=
1332 I915_MODE_FLAG_USE_SCANLINE_COUNTER;
1333
1334 return 0;
1335 }
1336
1337 static void
1338 set_tv_mode_timings(struct drm_i915_private *dev_priv,
1339 const struct tv_mode *tv_mode,
1340 bool burst_ena)
1341 {
1342 u32 hctl1, hctl2, hctl3;
1343 u32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
1344
1345 hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) |
1346 (tv_mode->htotal << TV_HTOTAL_SHIFT);
1347
1348 hctl2 = (tv_mode->hburst_start << 16) |
1349 (tv_mode->hburst_len << TV_HBURST_LEN_SHIFT);
1350
1351 if (burst_ena)
1352 hctl2 |= TV_BURST_ENA;
1353
1354 hctl3 = (tv_mode->hblank_start << TV_HBLANK_START_SHIFT) |
1355 (tv_mode->hblank_end << TV_HBLANK_END_SHIFT);
1356
1357 vctl1 = (tv_mode->nbr_end << TV_NBR_END_SHIFT) |
1358 (tv_mode->vi_end_f1 << TV_VI_END_F1_SHIFT) |
1359 (tv_mode->vi_end_f2 << TV_VI_END_F2_SHIFT);
1360
1361 vctl2 = (tv_mode->vsync_len << TV_VSYNC_LEN_SHIFT) |
1362 (tv_mode->vsync_start_f1 << TV_VSYNC_START_F1_SHIFT) |
1363 (tv_mode->vsync_start_f2 << TV_VSYNC_START_F2_SHIFT);
1364
1365 vctl3 = (tv_mode->veq_len << TV_VEQ_LEN_SHIFT) |
1366 (tv_mode->veq_start_f1 << TV_VEQ_START_F1_SHIFT) |
1367 (tv_mode->veq_start_f2 << TV_VEQ_START_F2_SHIFT);
1368
1369 if (tv_mode->veq_ena)
1370 vctl3 |= TV_EQUAL_ENA;
1371
1372 vctl4 = (tv_mode->vburst_start_f1 << TV_VBURST_START_F1_SHIFT) |
1373 (tv_mode->vburst_end_f1 << TV_VBURST_END_F1_SHIFT);
1374
1375 vctl5 = (tv_mode->vburst_start_f2 << TV_VBURST_START_F2_SHIFT) |
1376 (tv_mode->vburst_end_f2 << TV_VBURST_END_F2_SHIFT);
1377
1378 vctl6 = (tv_mode->vburst_start_f3 << TV_VBURST_START_F3_SHIFT) |
1379 (tv_mode->vburst_end_f3 << TV_VBURST_END_F3_SHIFT);
1380
1381 vctl7 = (tv_mode->vburst_start_f4 << TV_VBURST_START_F4_SHIFT) |
1382 (tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT);
1383
1384 I915_WRITE(TV_H_CTL_1, hctl1);
1385 I915_WRITE(TV_H_CTL_2, hctl2);
1386 I915_WRITE(TV_H_CTL_3, hctl3);
1387 I915_WRITE(TV_V_CTL_1, vctl1);
1388 I915_WRITE(TV_V_CTL_2, vctl2);
1389 I915_WRITE(TV_V_CTL_3, vctl3);
1390 I915_WRITE(TV_V_CTL_4, vctl4);
1391 I915_WRITE(TV_V_CTL_5, vctl5);
1392 I915_WRITE(TV_V_CTL_6, vctl6);
1393 I915_WRITE(TV_V_CTL_7, vctl7);
1394 }
1395
1396 static void set_color_conversion(struct drm_i915_private *dev_priv,
1397 const struct color_conversion *color_conversion)
1398 {
1399 if (!color_conversion)
1400 return;
1401
1402 I915_WRITE(TV_CSC_Y, (color_conversion->ry << 16) |
1403 color_conversion->gy);
1404 I915_WRITE(TV_CSC_Y2, (color_conversion->by << 16) |
1405 color_conversion->ay);
1406 I915_WRITE(TV_CSC_U, (color_conversion->ru << 16) |
1407 color_conversion->gu);
1408 I915_WRITE(TV_CSC_U2, (color_conversion->bu << 16) |
1409 color_conversion->au);
1410 I915_WRITE(TV_CSC_V, (color_conversion->rv << 16) |
1411 color_conversion->gv);
1412 I915_WRITE(TV_CSC_V2, (color_conversion->bv << 16) |
1413 color_conversion->av);
1414 }
1415
1416 static void intel_tv_pre_enable(struct intel_encoder *encoder,
1417 const struct intel_crtc_state *pipe_config,
1418 const struct drm_connector_state *conn_state)
1419 {
1420 struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1421 struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc);
1422 struct intel_tv *intel_tv = enc_to_tv(encoder);
1423 const struct intel_tv_connector_state *tv_conn_state =
1424 to_intel_tv_connector_state(conn_state);
1425 const struct tv_mode *tv_mode = intel_tv_mode_find(conn_state);
1426 u32 tv_ctl, tv_filter_ctl;
1427 u32 scctl1, scctl2, scctl3;
1428 int i, j;
1429 const struct video_levels *video_levels;
1430 const struct color_conversion *color_conversion;
1431 bool burst_ena;
1432 int xpos, ypos;
1433 unsigned int xsize, ysize;
1434
1435 if (!tv_mode)
1436 return;
1437
1438 tv_ctl = I915_READ(TV_CTL);
1439 tv_ctl &= TV_CTL_SAVE;
1440
1441 switch (intel_tv->type) {
1442 default:
1443 case DRM_MODE_CONNECTOR_Unknown:
1444 case DRM_MODE_CONNECTOR_Composite:
1445 tv_ctl |= TV_ENC_OUTPUT_COMPOSITE;
1446 video_levels = tv_mode->composite_levels;
1447 color_conversion = tv_mode->composite_color;
1448 burst_ena = tv_mode->burst_ena;
1449 break;
1450 case DRM_MODE_CONNECTOR_Component:
1451 tv_ctl |= TV_ENC_OUTPUT_COMPONENT;
1452 video_levels = &component_levels;
1453 if (tv_mode->burst_ena)
1454 color_conversion = &sdtv_csc_yprpb;
1455 else
1456 color_conversion = &hdtv_csc_yprpb;
1457 burst_ena = false;
1458 break;
1459 case DRM_MODE_CONNECTOR_SVIDEO:
1460 tv_ctl |= TV_ENC_OUTPUT_SVIDEO;
1461 video_levels = tv_mode->svideo_levels;
1462 color_conversion = tv_mode->svideo_color;
1463 burst_ena = tv_mode->burst_ena;
1464 break;
1465 }
1466
1467 tv_ctl |= TV_ENC_PIPE_SEL(intel_crtc->pipe);
1468
1469 switch (tv_mode->oversample) {
1470 case 8:
1471 tv_ctl |= TV_OVERSAMPLE_8X;
1472 break;
1473 case 4:
1474 tv_ctl |= TV_OVERSAMPLE_4X;
1475 break;
1476 case 2:
1477 tv_ctl |= TV_OVERSAMPLE_2X;
1478 break;
1479 default:
1480 tv_ctl |= TV_OVERSAMPLE_NONE;
1481 break;
1482 }
1483
1484 if (tv_mode->progressive)
1485 tv_ctl |= TV_PROGRESSIVE;
1486 if (tv_mode->trilevel_sync)
1487 tv_ctl |= TV_TRILEVEL_SYNC;
1488 if (tv_mode->pal_burst)
1489 tv_ctl |= TV_PAL_BURST;
1490
1491 scctl1 = 0;
1492 if (tv_mode->dda1_inc)
1493 scctl1 |= TV_SC_DDA1_EN;
1494 if (tv_mode->dda2_inc)
1495 scctl1 |= TV_SC_DDA2_EN;
1496 if (tv_mode->dda3_inc)
1497 scctl1 |= TV_SC_DDA3_EN;
1498 scctl1 |= tv_mode->sc_reset;
1499 if (video_levels)
1500 scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT;
1501 scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT;
1502
1503 scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
1504 tv_mode->dda2_inc << TV_SCDDA2_INC_SHIFT;
1505
1506 scctl3 = tv_mode->dda3_size << TV_SCDDA3_SIZE_SHIFT |
1507 tv_mode->dda3_inc << TV_SCDDA3_INC_SHIFT;
1508
1509
1510 if (IS_I915GM(dev_priv))
1511 tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
1512
1513 set_tv_mode_timings(dev_priv, tv_mode, burst_ena);
1514
1515 I915_WRITE(TV_SC_CTL_1, scctl1);
1516 I915_WRITE(TV_SC_CTL_2, scctl2);
1517 I915_WRITE(TV_SC_CTL_3, scctl3);
1518
1519 set_color_conversion(dev_priv, color_conversion);
1520
1521 if (INTEL_GEN(dev_priv) >= 4)
1522 I915_WRITE(TV_CLR_KNOBS, 0x00404000);
1523 else
1524 I915_WRITE(TV_CLR_KNOBS, 0x00606000);
1525
1526 if (video_levels)
1527 I915_WRITE(TV_CLR_LEVEL,
1528 ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
1529 (video_levels->blank << TV_BLANK_LEVEL_SHIFT)));
1530
1531 assert_pipe_disabled(dev_priv, intel_crtc->pipe);
1532
1533
1534 tv_filter_ctl = TV_AUTO_SCALE;
1535 if (tv_conn_state->bypass_vfilter)
1536 tv_filter_ctl |= TV_V_FILTER_BYPASS;
1537 I915_WRITE(TV_FILTER_CTL_1, tv_filter_ctl);
1538
1539 xsize = tv_mode->hblank_start - tv_mode->hblank_end;
1540 ysize = intel_tv_mode_vdisplay(tv_mode);
1541
1542 xpos = conn_state->tv.margins.left;
1543 ypos = tv_conn_state->margins.top;
1544 xsize -= (conn_state->tv.margins.left +
1545 conn_state->tv.margins.right);
1546 ysize -= (tv_conn_state->margins.top +
1547 tv_conn_state->margins.bottom);
1548 I915_WRITE(TV_WIN_POS, (xpos<<16)|ypos);
1549 I915_WRITE(TV_WIN_SIZE, (xsize<<16)|ysize);
1550
1551 j = 0;
1552 for (i = 0; i < 60; i++)
1553 I915_WRITE(TV_H_LUMA(i), tv_mode->filter_table[j++]);
1554 for (i = 0; i < 60; i++)
1555 I915_WRITE(TV_H_CHROMA(i), tv_mode->filter_table[j++]);
1556 for (i = 0; i < 43; i++)
1557 I915_WRITE(TV_V_LUMA(i), tv_mode->filter_table[j++]);
1558 for (i = 0; i < 43; i++)
1559 I915_WRITE(TV_V_CHROMA(i), tv_mode->filter_table[j++]);
1560 I915_WRITE(TV_DAC, I915_READ(TV_DAC) & TV_DAC_SAVE);
1561 I915_WRITE(TV_CTL, tv_ctl);
1562 }
1563
1564 static int
1565 intel_tv_detect_type(struct intel_tv *intel_tv,
1566 struct drm_connector *connector)
1567 {
1568 struct drm_crtc *crtc = connector->state->crtc;
1569 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1570 struct drm_device *dev = connector->dev;
1571 struct drm_i915_private *dev_priv = to_i915(dev);
1572 u32 tv_ctl, save_tv_ctl;
1573 u32 tv_dac, save_tv_dac;
1574 int type;
1575
1576
1577 if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
1578 spin_lock_irq(&dev_priv->irq_lock);
1579 i915_disable_pipestat(dev_priv, 0,
1580 PIPE_HOTPLUG_INTERRUPT_STATUS |
1581 PIPE_HOTPLUG_TV_INTERRUPT_STATUS);
1582 spin_unlock_irq(&dev_priv->irq_lock);
1583 }
1584
1585 save_tv_dac = tv_dac = I915_READ(TV_DAC);
1586 save_tv_ctl = tv_ctl = I915_READ(TV_CTL);
1587
1588
1589 tv_ctl &= ~(TV_ENC_ENABLE | TV_ENC_PIPE_SEL_MASK | TV_TEST_MODE_MASK);
1590 tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
1591 tv_ctl |= TV_ENC_PIPE_SEL(intel_crtc->pipe);
1592
1593 tv_dac &= ~(TVDAC_SENSE_MASK | DAC_A_MASK | DAC_B_MASK | DAC_C_MASK);
1594 tv_dac |= (TVDAC_STATE_CHG_EN |
1595 TVDAC_A_SENSE_CTL |
1596 TVDAC_B_SENSE_CTL |
1597 TVDAC_C_SENSE_CTL |
1598 DAC_CTL_OVERRIDE |
1599 DAC_A_0_7_V |
1600 DAC_B_0_7_V |
1601 DAC_C_0_7_V);
1602
1603
1604
1605
1606
1607
1608 if (IS_GM45(dev_priv))
1609 tv_dac &= ~(TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL |
1610 TVDAC_B_SENSE_CTL | TVDAC_C_SENSE_CTL);
1611
1612 I915_WRITE(TV_CTL, tv_ctl);
1613 I915_WRITE(TV_DAC, tv_dac);
1614 POSTING_READ(TV_DAC);
1615
1616 intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
1617
1618 type = -1;
1619 tv_dac = I915_READ(TV_DAC);
1620 DRM_DEBUG_KMS("TV detected: %x, %x\n", tv_ctl, tv_dac);
1621
1622
1623
1624
1625
1626
1627 if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
1628 DRM_DEBUG_KMS("Detected Composite TV connection\n");
1629 type = DRM_MODE_CONNECTOR_Composite;
1630 } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
1631 DRM_DEBUG_KMS("Detected S-Video TV connection\n");
1632 type = DRM_MODE_CONNECTOR_SVIDEO;
1633 } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
1634 DRM_DEBUG_KMS("Detected Component TV connection\n");
1635 type = DRM_MODE_CONNECTOR_Component;
1636 } else {
1637 DRM_DEBUG_KMS("Unrecognised TV connection\n");
1638 type = -1;
1639 }
1640
1641 I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
1642 I915_WRITE(TV_CTL, save_tv_ctl);
1643 POSTING_READ(TV_CTL);
1644
1645
1646 intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
1647
1648
1649 if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
1650 spin_lock_irq(&dev_priv->irq_lock);
1651 i915_enable_pipestat(dev_priv, 0,
1652 PIPE_HOTPLUG_INTERRUPT_STATUS |
1653 PIPE_HOTPLUG_TV_INTERRUPT_STATUS);
1654 spin_unlock_irq(&dev_priv->irq_lock);
1655 }
1656
1657 return type;
1658 }
1659
1660
1661
1662
1663
1664 static void intel_tv_find_better_format(struct drm_connector *connector)
1665 {
1666 struct intel_tv *intel_tv = intel_attached_tv(connector);
1667 const struct tv_mode *tv_mode = intel_tv_mode_find(connector->state);
1668 int i;
1669
1670
1671 if (intel_tv->type == DRM_MODE_CONNECTOR_Component)
1672 return;
1673
1674
1675 if (!tv_mode->component_only)
1676 return;
1677
1678 for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
1679 tv_mode = &tv_modes[i];
1680
1681 if (!tv_mode->component_only)
1682 break;
1683 }
1684
1685 connector->state->tv.mode = i;
1686 }
1687
1688 static int
1689 intel_tv_detect(struct drm_connector *connector,
1690 struct drm_modeset_acquire_ctx *ctx,
1691 bool force)
1692 {
1693 struct intel_tv *intel_tv = intel_attached_tv(connector);
1694 enum drm_connector_status status;
1695 int type;
1696
1697 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n",
1698 connector->base.id, connector->name,
1699 force);
1700
1701 if (force) {
1702 struct intel_load_detect_pipe tmp;
1703 int ret;
1704
1705 ret = intel_get_load_detect_pipe(connector, NULL, &tmp, ctx);
1706 if (ret < 0)
1707 return ret;
1708
1709 if (ret > 0) {
1710 type = intel_tv_detect_type(intel_tv, connector);
1711 intel_release_load_detect_pipe(connector, &tmp, ctx);
1712 status = type < 0 ?
1713 connector_status_disconnected :
1714 connector_status_connected;
1715 } else
1716 status = connector_status_unknown;
1717
1718 if (status == connector_status_connected) {
1719 intel_tv->type = type;
1720 intel_tv_find_better_format(connector);
1721 }
1722
1723 return status;
1724 } else
1725 return connector->status;
1726 }
1727
1728 static const struct input_res {
1729 u16 w, h;
1730 } input_res_table[] = {
1731 { 640, 480 },
1732 { 800, 600 },
1733 { 1024, 768 },
1734 { 1280, 1024 },
1735 { 848, 480 },
1736 { 1280, 720 },
1737 { 1920, 1080 },
1738 };
1739
1740
1741 static bool
1742 intel_tv_is_preferred_mode(const struct drm_display_mode *mode,
1743 const struct tv_mode *tv_mode)
1744 {
1745 int vdisplay = intel_tv_mode_vdisplay(tv_mode);
1746
1747
1748 if (vdisplay <= 576)
1749 vdisplay = 480;
1750
1751 return vdisplay == mode->vdisplay;
1752 }
1753
1754 static void
1755 intel_tv_set_mode_type(struct drm_display_mode *mode,
1756 const struct tv_mode *tv_mode)
1757 {
1758 mode->type = DRM_MODE_TYPE_DRIVER;
1759
1760 if (intel_tv_is_preferred_mode(mode, tv_mode))
1761 mode->type |= DRM_MODE_TYPE_PREFERRED;
1762 }
1763
1764 static int
1765 intel_tv_get_modes(struct drm_connector *connector)
1766 {
1767 struct drm_i915_private *dev_priv = to_i915(connector->dev);
1768 const struct tv_mode *tv_mode = intel_tv_mode_find(connector->state);
1769 int i, count = 0;
1770
1771 for (i = 0; i < ARRAY_SIZE(input_res_table); i++) {
1772 const struct input_res *input = &input_res_table[i];
1773 struct drm_display_mode *mode;
1774
1775 if (input->w > 1024 &&
1776 !tv_mode->progressive &&
1777 !tv_mode->component_only)
1778 continue;
1779
1780
1781 if (IS_GEN(dev_priv, 3) && input->w > 1024 &&
1782 input->h > intel_tv_mode_vdisplay(tv_mode))
1783 continue;
1784
1785 mode = drm_mode_create(connector->dev);
1786 if (!mode)
1787 continue;
1788
1789
1790
1791
1792
1793
1794
1795
1796 intel_tv_mode_to_mode(mode, tv_mode);
1797 if (count == 0) {
1798 DRM_DEBUG_KMS("TV mode:\n");
1799 drm_mode_debug_printmodeline(mode);
1800 }
1801 intel_tv_scale_mode_horiz(mode, input->w, 0, 0);
1802 intel_tv_scale_mode_vert(mode, input->h, 0, 0);
1803 intel_tv_set_mode_type(mode, tv_mode);
1804
1805 drm_mode_set_name(mode);
1806
1807 drm_mode_probed_add(connector, mode);
1808 count++;
1809 }
1810
1811 return count;
1812 }
1813
1814 static const struct drm_connector_funcs intel_tv_connector_funcs = {
1815 .late_register = intel_connector_register,
1816 .early_unregister = intel_connector_unregister,
1817 .destroy = intel_connector_destroy,
1818 .fill_modes = drm_helper_probe_single_connector_modes,
1819 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1820 .atomic_duplicate_state = intel_tv_connector_duplicate_state,
1821 };
1822
1823 static int intel_tv_atomic_check(struct drm_connector *connector,
1824 struct drm_atomic_state *state)
1825 {
1826 struct drm_connector_state *new_state;
1827 struct drm_crtc_state *new_crtc_state;
1828 struct drm_connector_state *old_state;
1829
1830 new_state = drm_atomic_get_new_connector_state(state, connector);
1831 if (!new_state->crtc)
1832 return 0;
1833
1834 old_state = drm_atomic_get_old_connector_state(state, connector);
1835 new_crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc);
1836
1837 if (old_state->tv.mode != new_state->tv.mode ||
1838 old_state->tv.margins.left != new_state->tv.margins.left ||
1839 old_state->tv.margins.right != new_state->tv.margins.right ||
1840 old_state->tv.margins.top != new_state->tv.margins.top ||
1841 old_state->tv.margins.bottom != new_state->tv.margins.bottom) {
1842
1843
1844 new_crtc_state->connectors_changed = true;
1845 }
1846
1847 return 0;
1848 }
1849
1850 static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = {
1851 .detect_ctx = intel_tv_detect,
1852 .mode_valid = intel_tv_mode_valid,
1853 .get_modes = intel_tv_get_modes,
1854 .atomic_check = intel_tv_atomic_check,
1855 };
1856
1857 static const struct drm_encoder_funcs intel_tv_enc_funcs = {
1858 .destroy = intel_encoder_destroy,
1859 };
1860
1861 void
1862 intel_tv_init(struct drm_i915_private *dev_priv)
1863 {
1864 struct drm_device *dev = &dev_priv->drm;
1865 struct drm_connector *connector;
1866 struct intel_tv *intel_tv;
1867 struct intel_encoder *intel_encoder;
1868 struct intel_connector *intel_connector;
1869 u32 tv_dac_on, tv_dac_off, save_tv_dac;
1870 const char *tv_format_names[ARRAY_SIZE(tv_modes)];
1871 int i, initial_mode = 0;
1872 struct drm_connector_state *state;
1873
1874 if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
1875 return;
1876
1877 if (!intel_bios_is_tv_present(dev_priv)) {
1878 DRM_DEBUG_KMS("Integrated TV is not present.\n");
1879 return;
1880 }
1881
1882
1883
1884
1885
1886 save_tv_dac = I915_READ(TV_DAC);
1887
1888 I915_WRITE(TV_DAC, save_tv_dac | TVDAC_STATE_CHG_EN);
1889 tv_dac_on = I915_READ(TV_DAC);
1890
1891 I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
1892 tv_dac_off = I915_READ(TV_DAC);
1893
1894 I915_WRITE(TV_DAC, save_tv_dac);
1895
1896
1897
1898
1899
1900
1901 if ((tv_dac_on & TVDAC_STATE_CHG_EN) == 0 ||
1902 (tv_dac_off & TVDAC_STATE_CHG_EN) != 0)
1903 return;
1904
1905 intel_tv = kzalloc(sizeof(*intel_tv), GFP_KERNEL);
1906 if (!intel_tv) {
1907 return;
1908 }
1909
1910 intel_connector = intel_connector_alloc();
1911 if (!intel_connector) {
1912 kfree(intel_tv);
1913 return;
1914 }
1915
1916 intel_encoder = &intel_tv->base;
1917 connector = &intel_connector->base;
1918 state = connector->state;
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930 intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
1931
1932 drm_connector_init(dev, connector, &intel_tv_connector_funcs,
1933 DRM_MODE_CONNECTOR_SVIDEO);
1934
1935 drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs,
1936 DRM_MODE_ENCODER_TVDAC, "TV");
1937
1938 intel_encoder->compute_config = intel_tv_compute_config;
1939 intel_encoder->get_config = intel_tv_get_config;
1940 intel_encoder->pre_enable = intel_tv_pre_enable;
1941 intel_encoder->enable = intel_enable_tv;
1942 intel_encoder->disable = intel_disable_tv;
1943 intel_encoder->get_hw_state = intel_tv_get_hw_state;
1944 intel_connector->get_hw_state = intel_connector_get_hw_state;
1945
1946 intel_connector_attach_encoder(intel_connector, intel_encoder);
1947
1948 intel_encoder->type = INTEL_OUTPUT_TVOUT;
1949 intel_encoder->power_domain = POWER_DOMAIN_PORT_OTHER;
1950 intel_encoder->port = PORT_NONE;
1951 intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
1952 intel_encoder->cloneable = 0;
1953 intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1));
1954 intel_tv->type = DRM_MODE_CONNECTOR_Unknown;
1955
1956
1957 state->tv.margins.left = 54;
1958 state->tv.margins.top = 36;
1959 state->tv.margins.right = 46;
1960 state->tv.margins.bottom = 37;
1961
1962 state->tv.mode = initial_mode;
1963
1964 drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs);
1965 connector->interlace_allowed = false;
1966 connector->doublescan_allowed = false;
1967
1968
1969 for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
1970
1971 if (IS_GEN(dev_priv, 3) &&
1972 tv_modes[i].oversample == 1)
1973 break;
1974
1975 tv_format_names[i] = tv_modes[i].name;
1976 }
1977 drm_mode_create_tv_properties(dev, i, tv_format_names);
1978
1979 drm_object_attach_property(&connector->base, dev->mode_config.tv_mode_property,
1980 state->tv.mode);
1981 drm_object_attach_property(&connector->base,
1982 dev->mode_config.tv_left_margin_property,
1983 state->tv.margins.left);
1984 drm_object_attach_property(&connector->base,
1985 dev->mode_config.tv_top_margin_property,
1986 state->tv.margins.top);
1987 drm_object_attach_property(&connector->base,
1988 dev->mode_config.tv_right_margin_property,
1989 state->tv.margins.right);
1990 drm_object_attach_property(&connector->base,
1991 dev->mode_config.tv_bottom_margin_property,
1992 state->tv.margins.bottom);
1993 }