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