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