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