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