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