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