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