1/*
2 * Integrated TV out support based on the GATOS code by
3 * Federico Ulivi <fulivi@lycos.com>
4 */
5
6#ifdef HAVE_CONFIG_H
7#include "config.h"
8#endif
9
10#include <string.h>
11#include <stdio.h>
12
13/* X and server generic header files */
14#include "xf86.h"
15#include "xf86_OSproc.h"
16#include "vgaHW.h"
17#include "xf86Modes.h"
18
19/* Driver data structures */
20#include "radeon.h"
21#include "radeon_reg.h"
22#include "radeon_macros.h"
23#include "radeon_probe.h"
24#include "radeon_version.h"
25#include "radeon_tv.h"
26#include "radeon_atombios.h"
27
28/**********************************************************************
29 *
30 * ModeConstants
31 *
32 * Storage of constants related to a single video mode
33 *
34 **********************************************************************/
35
36typedef struct
37{
38    uint16_t horResolution;
39    uint16_t verResolution;
40    TVStd  standard;
41    uint16_t horTotal;
42    uint16_t verTotal;
43    uint16_t horStart;
44    uint16_t horSyncStart;
45    uint16_t verSyncStart;
46    unsigned defRestart;
47    uint16_t crtcPLL_N;
48    uint8_t  crtcPLL_M;
49    uint8_t  crtcPLL_postDiv;
50    unsigned pixToTV;
51} TVModeConstants;
52
53static const uint16_t hor_timing_NTSC[] =
54{
55    0x0007,
56    0x003f,
57    0x0263,
58    0x0a24,
59    0x2a6b,
60    0x0a36,
61    0x126d, /* H_TABLE_POS1 */
62    0x1bfe,
63    0x1a8f, /* H_TABLE_POS2 */
64    0x1ec7,
65    0x3863,
66    0x1bfe,
67    0x1bfe,
68    0x1a2a,
69    0x1e95,
70    0x0e31,
71    0x201b,
72    0
73};
74
75static const uint16_t vert_timing_NTSC[] =
76{
77    0x2001,
78    0x200d,
79    0x1006,
80    0x0c06,
81    0x1006,
82    0x1818,
83    0x21e3,
84    0x1006,
85    0x0c06,
86    0x1006,
87    0x1817,
88    0x21d4,
89    0x0002,
90    0
91};
92
93static const uint16_t hor_timing_PAL[] =
94{
95    0x0007,
96    0x0058,
97    0x027c,
98    0x0a31,
99    0x2a77,
100    0x0a95,
101    0x124f, /* H_TABLE_POS1 */
102    0x1bfe,
103    0x1b22, /* H_TABLE_POS2 */
104    0x1ef9,
105    0x387c,
106    0x1bfe,
107    0x1bfe,
108    0x1b31,
109    0x1eb5,
110    0x0e43,
111    0x201b,
112    0
113};
114
115static const uint16_t vert_timing_PAL[] =
116{
117    0x2001,
118    0x200c,
119    0x1005,
120    0x0c05,
121    0x1005,
122    0x1401,
123    0x1821,
124    0x2240,
125    0x1005,
126    0x0c05,
127    0x1005,
128    0x1401,
129    0x1822,
130    0x2230,
131    0x0002,
132    0
133};
134
135/**********************************************************************
136 *
137 * availableModes
138 *
139 * Table of all allowed modes for tv output
140 *
141 **********************************************************************/
142static const TVModeConstants availableTVModes[] =
143{
144    {   /* NTSC timing for 27 Mhz ref clk */
145	800,                /* horResolution */
146	600,                /* verResolution */
147	TV_STD_NTSC,        /* standard */
148	990,                /* horTotal */
149	740,                /* verTotal */
150	813,                /* horStart */
151	824,                /* horSyncStart */
152	632,                /* verSyncStart */
153	625592,             /* defRestart */
154	592,                /* crtcPLL_N */
155	91,                 /* crtcPLL_M */
156	4,                  /* crtcPLL_postDiv */
157	1022,               /* pixToTV */
158    },
159    {   /* PAL timing for 27 Mhz ref clk */
160	800,               /* horResolution */
161	600,               /* verResolution */
162	TV_STD_PAL,        /* standard */
163	1144,              /* horTotal */
164	706,               /* verTotal */
165	812,               /* horStart */
166	824,               /* horSyncStart */
167	669,               /* verSyncStart */
168	696700,            /* defRestart */
169	1382,              /* crtcPLL_N */
170	231,               /* crtcPLL_M */
171	4,                 /* crtcPLL_postDiv */
172	759,               /* pixToTV */
173    },
174    {   /* NTSC timing for 14 Mhz ref clk */
175	800,                /* horResolution */
176	600,                /* verResolution */
177	TV_STD_NTSC,        /* standard */
178	1018,               /* horTotal */
179	727,                /* verTotal */
180	813,                /* horStart */
181	840,                /* horSyncStart */
182	633,                /* verSyncStart */
183	630627,             /* defRestart */
184	347,                /* crtcPLL_N */
185	14,                 /* crtcPLL_M */
186	8,                  /* crtcPLL_postDiv */
187	1022,               /* pixToTV */
188    },
189    {   /* PAL timing for 14 Mhz ref clk */
190	800,                /* horResolution */
191	600,                /* verResolution */
192	TV_STD_PAL,         /* standard */
193	1131,               /* horTotal */
194	742,                /* verTotal */
195	813,                /* horStart */
196	840,                /* horSyncStart */
197	633,                /* verSyncStart */
198	708369,             /* defRestart */
199	211,                /* crtcPLL_N */
200	9,                  /* crtcPLL_M */
201	8,                  /* crtcPLL_postDiv */
202	759,                /* pixToTV */
203    },
204};
205
206#define N_AVAILABLE_MODES (sizeof(availableModes) / sizeof(availableModes[ 0 ]))
207
208static long YCOEF_value[5] = { 2, 2, 0, 4, 0 };
209static long YCOEF_EN_value[5] = { 1, 1, 0, 1, 0 };
210static long SLOPE_value[5] = { 1, 2, 2, 4, 8 };
211static long SLOPE_limit[5] = { 6, 5, 4, 3, 2 };
212
213
214static void
215RADEONWaitPLLLock(ScrnInfoPtr pScrn, unsigned nTests,
216		  unsigned nWaitLoops, unsigned cntThreshold)
217{
218    RADEONInfoPtr  info       = RADEONPTR(pScrn);
219    unsigned char *RADEONMMIO = info->MMIO;
220    uint32_t savePLLTest;
221    unsigned i;
222    unsigned j;
223
224    OUTREG(RADEON_TEST_DEBUG_MUX, (INREG(RADEON_TEST_DEBUG_MUX) & 0xffff60ff) | 0x100);
225
226    savePLLTest = INPLL(pScrn, RADEON_PLL_TEST_CNTL);
227
228    OUTPLL(pScrn, RADEON_PLL_TEST_CNTL, savePLLTest & ~RADEON_PLL_MASK_READ_B);
229
230    /* XXX: these should probably be OUTPLL to avoid various PLL errata */
231
232    OUTREG8(RADEON_CLOCK_CNTL_INDEX, RADEON_PLL_TEST_CNTL);
233
234    for (i = 0; i < nTests; i++) {
235	OUTREG8(RADEON_CLOCK_CNTL_DATA + 3, 0);
236
237	for (j = 0; j < nWaitLoops; j++)
238	    if (INREG8(RADEON_CLOCK_CNTL_DATA + 3) >= cntThreshold)
239		break;
240    }
241
242    OUTPLL(pScrn, RADEON_PLL_TEST_CNTL, savePLLTest);
243
244    OUTREG(RADEON_TEST_DEBUG_MUX, INREG(RADEON_TEST_DEBUG_MUX) & 0xffffe0ff);
245}
246
247/* Write to TV FIFO RAM */
248static void
249RADEONWriteTVFIFO(ScrnInfoPtr pScrn, uint16_t addr,
250		  uint32_t value)
251{
252    RADEONInfoPtr  info       = RADEONPTR(pScrn);
253    unsigned char *RADEONMMIO = info->MMIO;
254    uint32_t tmp;
255    int i = 0;
256
257    OUTREG(RADEON_TV_HOST_WRITE_DATA, value);
258
259    OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr);
260    OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_WT);
261
262    do {
263	tmp = INREG(RADEON_TV_HOST_RD_WT_CNTL);
264	if ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0)
265	    break;
266	i++;
267    }
268    while (i < 10000);
269    /*while ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0);*/
270
271    OUTREG(RADEON_TV_HOST_RD_WT_CNTL, 0);
272}
273
274/* Read from TV FIFO RAM */
275static uint32_t
276RADEONReadTVFIFO(ScrnInfoPtr pScrn, uint16_t addr)
277{
278    RADEONInfoPtr  info       = RADEONPTR(pScrn);
279    unsigned char *RADEONMMIO = info->MMIO;
280    uint32_t tmp;
281    int i = 0;
282
283    OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr);
284    OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_RD);
285
286    do {
287	tmp = INREG(RADEON_TV_HOST_RD_WT_CNTL);
288	if ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0)
289	    break;
290	i++;
291    }
292    while (i < 10000);
293    /*while ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0);*/
294
295    OUTREG(RADEON_TV_HOST_RD_WT_CNTL, 0);
296
297    return INREG(RADEON_TV_HOST_READ_DATA);
298}
299
300/* Get FIFO addresses of horizontal & vertical code timing tables from
301 * settings of uv_adr register.
302 */
303static uint16_t
304RADEONGetHTimingTablesAddr(uint32_t tv_uv_adr)
305{
306    uint16_t hTable;
307
308    switch ((tv_uv_adr & RADEON_HCODE_TABLE_SEL_MASK) >> RADEON_HCODE_TABLE_SEL_SHIFT) {
309    case 0:
310	hTable = RADEON_TV_MAX_FIFO_ADDR_INTERNAL;
311	break;
312    case 1:
313	hTable = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2;
314	break;
315    case 2:
316	hTable = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2;
317	break;
318    default:
319	/* Of course, this should never happen */
320	hTable = 0;
321	break;
322    }
323    return hTable;
324}
325
326static uint16_t
327RADEONGetVTimingTablesAddr(uint32_t tv_uv_adr)
328{
329    uint16_t vTable;
330
331    switch ((tv_uv_adr & RADEON_VCODE_TABLE_SEL_MASK) >> RADEON_VCODE_TABLE_SEL_SHIFT) {
332    case 0:
333	vTable = ((tv_uv_adr & RADEON_MAX_UV_ADR_MASK) >> RADEON_MAX_UV_ADR_SHIFT) * 2 + 1;
334	break;
335    case 1:
336	vTable = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2 + 1;
337	break;
338    case 2:
339	vTable = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2 + 1;
340	break;
341    default:
342	/* Of course, this should never happen */
343	vTable = 0;
344	break;
345    }
346    return vTable;
347}
348
349/* Restore horizontal/vertical timing code tables */
350static void
351RADEONRestoreTVTimingTables(ScrnInfoPtr pScrn, RADEONSavePtr restore)
352{
353    RADEONInfoPtr  info       = RADEONPTR(pScrn);
354    unsigned char *RADEONMMIO = info->MMIO;
355    uint16_t hTable;
356    uint16_t vTable;
357    uint32_t tmp;
358    unsigned i;
359
360    OUTREG(RADEON_TV_UV_ADR, restore->tv_uv_adr);
361    hTable = RADEONGetHTimingTablesAddr(restore->tv_uv_adr);
362    vTable = RADEONGetVTimingTablesAddr(restore->tv_uv_adr);
363
364    for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2, hTable--) {
365	tmp = ((uint32_t)restore->h_code_timing[ i ] << 14) | ((uint32_t)restore->h_code_timing[ i + 1 ]);
366	RADEONWriteTVFIFO(pScrn, hTable, tmp);
367	if (restore->h_code_timing[ i ] == 0 || restore->h_code_timing[ i + 1 ] == 0)
368	    break;
369    }
370
371    for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2, vTable++) {
372	tmp = ((uint32_t)restore->v_code_timing[ i + 1 ] << 14) | ((uint32_t)restore->v_code_timing[ i ]);
373	RADEONWriteTVFIFO(pScrn, vTable, tmp);
374	if (restore->v_code_timing[ i ] == 0 || restore->v_code_timing[ i + 1 ] == 0)
375	    break;
376    }
377}
378
379/* restore TV PLLs */
380static void
381RADEONRestoreTVPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
382{
383
384    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVCLK_SRC_SEL_TVPLL);
385    OUTPLL(pScrn, RADEON_TV_PLL_CNTL, restore->tv_pll_cntl);
386    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, RADEON_TVPLL_RESET, ~RADEON_TVPLL_RESET);
387
388    RADEONWaitPLLLock(pScrn, 200, 800, 135);
389
390    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_RESET);
391
392    RADEONWaitPLLLock(pScrn, 300, 160, 27);
393    RADEONWaitPLLLock(pScrn, 200, 800, 135);
394
395    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~0xf);
396    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, RADEON_TVCLK_SRC_SEL_TVPLL, ~RADEON_TVCLK_SRC_SEL_TVPLL);
397
398    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, (1 << RADEON_TVPDC_SHIFT), ~RADEON_TVPDC_MASK);
399    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_SLEEP);
400}
401
402/* Restore TV horizontal/vertical settings */
403static void
404RADEONRestoreTVHVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
405{
406    RADEONInfoPtr  info       = RADEONPTR(pScrn);
407    unsigned char *RADEONMMIO = info->MMIO;
408
409    OUTREG(RADEON_TV_RGB_CNTL, restore->tv_rgb_cntl);
410
411    OUTREG(RADEON_TV_HTOTAL, restore->tv_htotal);
412    OUTREG(RADEON_TV_HDISP, restore->tv_hdisp);
413    OUTREG(RADEON_TV_HSTART, restore->tv_hstart);
414
415    OUTREG(RADEON_TV_VTOTAL, restore->tv_vtotal);
416    OUTREG(RADEON_TV_VDISP, restore->tv_vdisp);
417
418    OUTREG(RADEON_TV_FTOTAL, restore->tv_ftotal);
419
420    OUTREG(RADEON_TV_VSCALER_CNTL1, restore->tv_vscaler_cntl1);
421    OUTREG(RADEON_TV_VSCALER_CNTL2, restore->tv_vscaler_cntl2);
422
423    OUTREG(RADEON_TV_Y_FALL_CNTL, restore->tv_y_fall_cntl);
424    OUTREG(RADEON_TV_Y_RISE_CNTL, restore->tv_y_rise_cntl);
425    OUTREG(RADEON_TV_Y_SAW_TOOTH_CNTL, restore->tv_y_saw_tooth_cntl);
426}
427
428/* restore TV RESTART registers */
429static void
430RADEONRestoreTVRestarts(ScrnInfoPtr pScrn, RADEONSavePtr restore)
431{
432    RADEONInfoPtr  info       = RADEONPTR(pScrn);
433    unsigned char *RADEONMMIO = info->MMIO;
434
435    OUTREG(RADEON_TV_FRESTART, restore->tv_frestart);
436    OUTREG(RADEON_TV_HRESTART, restore->tv_hrestart);
437    OUTREG(RADEON_TV_VRESTART, restore->tv_vrestart);
438}
439
440/* restore tv standard & output muxes */
441static void
442RADEONRestoreTVOutputStd(ScrnInfoPtr pScrn, RADEONSavePtr restore)
443{
444    RADEONInfoPtr  info       = RADEONPTR(pScrn);
445    unsigned char *RADEONMMIO = info->MMIO;
446
447    OUTREG(RADEON_TV_SYNC_CNTL, restore->tv_sync_cntl);
448
449    OUTREG(RADEON_TV_TIMING_CNTL, restore->tv_timing_cntl);
450
451    OUTREG(RADEON_TV_MODULATOR_CNTL1, restore->tv_modulator_cntl1);
452    OUTREG(RADEON_TV_MODULATOR_CNTL2, restore->tv_modulator_cntl2);
453
454    OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, restore->tv_pre_dac_mux_cntl);
455
456    OUTREG(RADEON_TV_CRC_CNTL, restore->tv_crc_cntl);
457}
458
459/* Restore TV out regs */
460void
461RADEONRestoreTVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
462{
463    RADEONInfoPtr  info       = RADEONPTR(pScrn);
464    unsigned char *RADEONMMIO = info->MMIO;
465
466    ErrorF("Entering Restore TV\n");
467
468    OUTREG(RADEON_TV_MASTER_CNTL, (restore->tv_master_cntl
469				   | RADEON_TV_ASYNC_RST
470				   | RADEON_CRT_ASYNC_RST
471				   | RADEON_TV_FIFO_ASYNC_RST));
472
473    /* Temporarily turn the TV DAC off */
474    OUTREG(RADEON_TV_DAC_CNTL, ((restore->tv_dac_cntl & ~RADEON_TV_DAC_NBLANK)
475				| RADEON_TV_DAC_BGSLEEP
476				| RADEON_TV_DAC_RDACPD
477				| RADEON_TV_DAC_GDACPD
478				| RADEON_TV_DAC_BDACPD));
479
480    ErrorF("Restore TV PLL\n");
481    RADEONRestoreTVPLLRegisters(pScrn, restore);
482
483    ErrorF("Restore TVHV\n");
484    RADEONRestoreTVHVRegisters(pScrn, restore);
485
486    OUTREG(RADEON_TV_MASTER_CNTL, (restore->tv_master_cntl
487				   | RADEON_TV_ASYNC_RST
488				   | RADEON_CRT_ASYNC_RST));
489
490    ErrorF("Restore TV Restarts\n");
491    RADEONRestoreTVRestarts(pScrn, restore);
492
493    ErrorF("Restore Timing Tables\n");
494    RADEONRestoreTVTimingTables(pScrn, restore);
495
496
497    OUTREG(RADEON_TV_MASTER_CNTL, (restore->tv_master_cntl
498				   | RADEON_TV_ASYNC_RST));
499
500    ErrorF("Restore TV standard\n");
501    RADEONRestoreTVOutputStd(pScrn, restore);
502
503    OUTREG(RADEON_TV_MASTER_CNTL, restore->tv_master_cntl);
504
505    OUTREG(RADEON_TV_GAIN_LIMIT_SETTINGS, restore->tv_gain_limit_settings);
506    OUTREG(RADEON_TV_LINEAR_GAIN_SETTINGS, restore->tv_linear_gain_settings);
507
508    OUTREG(RADEON_TV_DAC_CNTL, restore->tv_dac_cntl);
509
510    ErrorF("Leaving Restore TV\n");
511}
512
513/* Save horizontal/vertical timing code tables */
514static void
515RADEONSaveTVTimingTables(ScrnInfoPtr pScrn, RADEONSavePtr save)
516{
517    RADEONInfoPtr  info       = RADEONPTR(pScrn);
518    unsigned char *RADEONMMIO = info->MMIO;
519    uint16_t hTable;
520    uint16_t vTable;
521    uint32_t tmp;
522    unsigned i;
523
524    save->tv_uv_adr = INREG(RADEON_TV_UV_ADR);
525    hTable = RADEONGetHTimingTablesAddr(save->tv_uv_adr);
526    vTable = RADEONGetVTimingTablesAddr(save->tv_uv_adr);
527
528    /*
529     * Reset FIFO arbiter in order to be able to access FIFO RAM
530     */
531
532    OUTREG(RADEON_TV_MASTER_CNTL, (RADEON_TV_ASYNC_RST
533				   | RADEON_CRT_ASYNC_RST
534				   | RADEON_RESTART_PHASE_FIX
535				   | RADEON_CRT_FIFO_CE_EN
536				   | RADEON_TV_FIFO_CE_EN
537				   | RADEON_TV_ON));
538
539    /*OUTREG(RADEON_TV_MASTER_CNTL, save->tv_master_cntl | RADEON_TV_ON);*/
540
541    ErrorF("saveTimingTables: reading timing tables\n");
542
543    for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2) {
544	tmp = RADEONReadTVFIFO(pScrn, hTable--);
545	save->h_code_timing[ i     ] = (uint16_t)((tmp >> 14) & 0x3fff);
546	save->h_code_timing[ i + 1 ] = (uint16_t)(tmp & 0x3fff);
547
548	if (save->h_code_timing[ i ] == 0 || save->h_code_timing[ i + 1 ] == 0)
549	    break;
550    }
551
552    for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2) {
553	tmp = RADEONReadTVFIFO(pScrn, vTable++);
554	save->v_code_timing[ i     ] = (uint16_t)(tmp & 0x3fff);
555	save->v_code_timing[ i + 1 ] = (uint16_t)((tmp >> 14) & 0x3fff);
556
557	if (save->v_code_timing[ i ] == 0 || save->v_code_timing[ i + 1 ] == 0)
558	    break;
559    }
560}
561
562/* read TV regs */
563void
564RADEONSaveTVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
565{
566    RADEONInfoPtr  info       = RADEONPTR(pScrn);
567    unsigned char *RADEONMMIO = info->MMIO;
568
569    ErrorF("Entering TV Save\n");
570
571    save->tv_crc_cntl = INREG(RADEON_TV_CRC_CNTL);
572    save->tv_frestart = INREG(RADEON_TV_FRESTART);
573    save->tv_hrestart = INREG(RADEON_TV_HRESTART);
574    save->tv_vrestart = INREG(RADEON_TV_VRESTART);
575    save->tv_gain_limit_settings = INREG(RADEON_TV_GAIN_LIMIT_SETTINGS);
576    save->tv_hdisp = INREG(RADEON_TV_HDISP);
577    save->tv_hstart = INREG(RADEON_TV_HSTART);
578    save->tv_htotal = INREG(RADEON_TV_HTOTAL);
579    save->tv_linear_gain_settings = INREG(RADEON_TV_LINEAR_GAIN_SETTINGS);
580    save->tv_master_cntl = INREG(RADEON_TV_MASTER_CNTL);
581    save->tv_rgb_cntl = INREG(RADEON_TV_RGB_CNTL);
582    save->tv_modulator_cntl1 = INREG(RADEON_TV_MODULATOR_CNTL1);
583    save->tv_modulator_cntl2 = INREG(RADEON_TV_MODULATOR_CNTL2);
584    save->tv_pre_dac_mux_cntl = INREG(RADEON_TV_PRE_DAC_MUX_CNTL);
585    save->tv_sync_cntl = INREG(RADEON_TV_SYNC_CNTL);
586    save->tv_timing_cntl = INREG(RADEON_TV_TIMING_CNTL);
587    save->tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
588    save->tv_upsamp_and_gain_cntl = INREG(RADEON_TV_UPSAMP_AND_GAIN_CNTL);
589    save->tv_vdisp = INREG(RADEON_TV_VDISP);
590    save->tv_ftotal = INREG(RADEON_TV_FTOTAL);
591    save->tv_vscaler_cntl1 = INREG(RADEON_TV_VSCALER_CNTL1);
592    save->tv_vscaler_cntl2 = INREG(RADEON_TV_VSCALER_CNTL2);
593    save->tv_vtotal = INREG(RADEON_TV_VTOTAL);
594    save->tv_y_fall_cntl = INREG(RADEON_TV_Y_FALL_CNTL);
595    save->tv_y_rise_cntl = INREG(RADEON_TV_Y_RISE_CNTL);
596    save->tv_y_saw_tooth_cntl = INREG(RADEON_TV_Y_SAW_TOOTH_CNTL);
597
598    save->tv_pll_cntl = INPLL(pScrn, RADEON_TV_PLL_CNTL);
599    save->tv_pll_cntl1 = INPLL(pScrn, RADEON_TV_PLL_CNTL1);
600
601    ErrorF("Save TV timing tables\n");
602
603    RADEONSaveTVTimingTables(pScrn, save);
604
605    ErrorF("TV Save done\n");
606}
607
608
609/* Compute F,V,H restarts from default restart position and hPos & vPos
610 * Return TRUE when code timing table was changed
611 */
612static Bool RADEONInitTVRestarts(xf86OutputPtr output, RADEONSavePtr save,
613				 DisplayModePtr mode)
614{
615    RADEONOutputPrivatePtr radeon_output = output->driver_private;
616    radeon_tvout_ptr tvout = &radeon_output->tvout;
617    RADEONInfoPtr  info       = RADEONPTR(output->scrn);
618    RADEONPLLPtr pll = &info->pll;
619    int restart;
620    unsigned hTotal;
621    unsigned vTotal;
622    unsigned fTotal;
623    int vOffset;
624    int hOffset;
625    uint16_t p1;
626    uint16_t p2;
627    Bool hChanged;
628    uint16_t hInc;
629    const TVModeConstants *constPtr;
630
631    /* FIXME: need to revisit this when we add more modes */
632    if (tvout->tvStd == TV_STD_NTSC ||
633	tvout->tvStd == TV_STD_NTSC_J ||
634	tvout->tvStd == TV_STD_PAL_M) {
635	if (pll->reference_freq == 2700)
636	    constPtr = &availableTVModes[0];
637	else
638	    constPtr = &availableTVModes[2];
639    } else {
640	if (pll->reference_freq == 2700)
641	    constPtr = &availableTVModes[1];
642	else
643	    constPtr = &availableTVModes[3];
644    }
645
646    hTotal = constPtr->horTotal;
647    vTotal = constPtr->verTotal;
648
649    if (tvout->tvStd == TV_STD_NTSC ||
650	tvout->tvStd == TV_STD_NTSC_J ||
651        tvout->tvStd == TV_STD_PAL_M ||
652        tvout->tvStd == TV_STD_PAL_60)
653	fTotal = NTSC_TV_VFTOTAL + 1;
654    else
655	fTotal = PAL_TV_VFTOTAL + 1;
656
657    /* Adjust positions 1&2 in hor. code timing table */
658    hOffset = tvout->hPos * H_POS_UNIT;
659
660    if (tvout->tvStd == TV_STD_NTSC ||
661	tvout->tvStd == TV_STD_NTSC_J ||
662	tvout->tvStd == TV_STD_PAL_M) {
663	/* improve image centering */
664	hOffset -= 50;
665	p1 = hor_timing_NTSC[ H_TABLE_POS1 ];
666	p2 = hor_timing_NTSC[ H_TABLE_POS2 ];
667    } else {
668	p1 = hor_timing_PAL[ H_TABLE_POS1 ];
669	p2 = hor_timing_PAL[ H_TABLE_POS2 ];
670    }
671
672
673    p1 = (uint16_t)((int)p1 + hOffset);
674    p2 = (uint16_t)((int)p2 - hOffset);
675
676    hChanged = (p1 != save->h_code_timing[ H_TABLE_POS1 ] ||
677		p2 != save->h_code_timing[ H_TABLE_POS2 ]);
678
679    save->h_code_timing[ H_TABLE_POS1 ] = p1;
680    save->h_code_timing[ H_TABLE_POS2 ] = p2;
681
682    /* Convert hOffset from n. of TV clock periods to n. of CRTC clock periods (CRTC pixels) */
683    hOffset = (hOffset * (int)(constPtr->pixToTV)) / 1000;
684
685    /* Adjust restart */
686    restart = constPtr->defRestart;
687
688    /*
689     * Convert vPos TV lines to n. of CRTC pixels
690     * Be verrrrry careful when mixing signed & unsigned values in C..
691     */
692    if (tvout->tvStd == TV_STD_NTSC ||
693	tvout->tvStd == TV_STD_NTSC_J ||
694	tvout->tvStd == TV_STD_PAL_M ||
695	tvout->tvStd == TV_STD_PAL_60)
696	vOffset = ((int)(vTotal * hTotal) * 2 * tvout->vPos) / (int)(NTSC_TV_LINES_PER_FRAME);
697    else
698	vOffset = ((int)(vTotal * hTotal) * 2 * tvout->vPos) / (int)(PAL_TV_LINES_PER_FRAME);
699
700    restart -= vOffset + hOffset;
701
702    ErrorF("computeRestarts: def = %u, h = %d, v = %d, p1=%04x, p2=%04x, restart = %d\n",
703	   constPtr->defRestart , tvout->hPos , tvout->vPos , p1 , p2 , restart);
704
705    save->tv_hrestart = restart % hTotal;
706    restart /= hTotal;
707    save->tv_vrestart = restart % vTotal;
708    restart /= vTotal;
709    save->tv_frestart = restart % fTotal;
710
711    ErrorF("computeRestarts: F/H/V=%u,%u,%u\n",
712	   (unsigned)save->tv_frestart, (unsigned)save->tv_vrestart,
713	   (unsigned)save->tv_hrestart);
714
715    /* Compute H_INC from hSize */
716    if (tvout->tvStd == TV_STD_NTSC ||
717	tvout->tvStd == TV_STD_NTSC_J ||
718	tvout->tvStd == TV_STD_PAL_M)
719	hInc = (uint16_t)((int)(constPtr->horResolution * 4096 * NTSC_TV_CLOCK_T) /
720			(tvout->hSize * (int)(NTSC_TV_H_SIZE_UNIT) + (int)(NTSC_TV_ZERO_H_SIZE)));
721    else
722	hInc = (uint16_t)((int)(constPtr->horResolution * 4096 * PAL_TV_CLOCK_T) /
723			(tvout->hSize * (int)(PAL_TV_H_SIZE_UNIT) + (int)(PAL_TV_ZERO_H_SIZE)));
724
725    save->tv_timing_cntl = (save->tv_timing_cntl & ~RADEON_H_INC_MASK) |
726	((uint32_t)hInc << RADEON_H_INC_SHIFT);
727
728    ErrorF("computeRestarts: hSize=%d,hInc=%u\n" , tvout->hSize , hInc);
729
730    return hChanged;
731}
732
733/* intit TV-out regs */
734void RADEONInitTVRegisters(xf86OutputPtr output, RADEONSavePtr save,
735                                  DisplayModePtr mode, BOOL IsPrimary)
736{
737    ScrnInfoPtr pScrn = output->scrn;
738    RADEONOutputPrivatePtr radeon_output = output->driver_private;
739    radeon_tvout_ptr tvout = &radeon_output->tvout;
740    RADEONInfoPtr  info = RADEONPTR(pScrn);
741    RADEONPLLPtr pll = &info->pll;
742    unsigned m, n, p;
743    unsigned i;
744    unsigned long vert_space, flicker_removal;
745    uint32_t tmp;
746    const TVModeConstants *constPtr;
747    const uint16_t *hor_timing;
748    const uint16_t *vert_timing;
749    radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
750    radeon_tvdac_ptr tvdac = NULL;
751
752    if (radeon_encoder == NULL)
753	return;
754
755    tvdac = (radeon_tvdac_ptr)radeon_encoder->dev_priv;
756
757    if (tvdac == NULL)
758	return;
759
760    /* FIXME: need to revisit this when we add more modes */
761    if (tvout->tvStd == TV_STD_NTSC ||
762	tvout->tvStd == TV_STD_NTSC_J ||
763	tvout->tvStd == TV_STD_PAL_M) {
764	if (pll->reference_freq == 2700)
765	    constPtr = &availableTVModes[0];
766	else
767	    constPtr = &availableTVModes[2];
768    } else {
769	if (pll->reference_freq == 2700)
770	    constPtr = &availableTVModes[1];
771	else
772	    constPtr = &availableTVModes[3];
773    }
774
775    save->tv_crc_cntl = 0;
776
777    save->tv_gain_limit_settings = (0x17f << RADEON_UV_GAIN_LIMIT_SHIFT) |
778	                           (0x5ff << RADEON_Y_GAIN_LIMIT_SHIFT);
779
780    save->tv_hdisp = constPtr->horResolution - 1;
781    save->tv_hstart = constPtr->horStart;
782    save->tv_htotal = constPtr->horTotal - 1;
783
784    save->tv_linear_gain_settings = (0x100 << RADEON_UV_GAIN_SHIFT) |
785	                            (0x100 << RADEON_Y_GAIN_SHIFT);
786
787    save->tv_master_cntl = (RADEON_VIN_ASYNC_RST
788			    | RADEON_CRT_FIFO_CE_EN
789			    | RADEON_TV_FIFO_CE_EN
790			    | RADEON_TV_ON);
791
792    if (!IS_R300_VARIANT)
793	save->tv_master_cntl |= RADEON_TVCLK_ALWAYS_ONb;
794
795    if (tvout->tvStd == TV_STD_NTSC ||
796	tvout->tvStd == TV_STD_NTSC_J)
797	save->tv_master_cntl |= RADEON_RESTART_PHASE_FIX;
798
799    save->tv_modulator_cntl1 = RADEON_SLEW_RATE_LIMIT
800	                       | RADEON_SYNC_TIP_LEVEL
801	                       | RADEON_YFLT_EN
802	                       | RADEON_UVFLT_EN
803	                       | (6 << RADEON_CY_FILT_BLEND_SHIFT);
804
805    if (tvout->tvStd == TV_STD_NTSC ||
806	tvout->tvStd == TV_STD_NTSC_J) {
807	save->tv_modulator_cntl1 |= (0x46 << RADEON_SET_UP_LEVEL_SHIFT)
808	                            | (0x3b << RADEON_BLANK_LEVEL_SHIFT);
809	save->tv_modulator_cntl2 = (-111 & RADEON_TV_U_BURST_LEVEL_MASK) |
810	    ((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT);
811    } else if (tvout->tvStd == TV_STD_SCART_PAL) {
812	save->tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN;
813	save->tv_modulator_cntl2 = (0 & RADEON_TV_U_BURST_LEVEL_MASK) |
814	    ((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT);
815    } else {
816	save->tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN
817	                            | (0x3b << RADEON_SET_UP_LEVEL_SHIFT)
818	                            | (0x3b << RADEON_BLANK_LEVEL_SHIFT);
819	save->tv_modulator_cntl2 = (-78 & RADEON_TV_U_BURST_LEVEL_MASK) |
820	    ((62 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT);
821    }
822
823    save->pll_test_cntl = 0;
824
825    save->tv_pre_dac_mux_cntl = (RADEON_Y_RED_EN
826				 | RADEON_C_GRN_EN
827				 | RADEON_CMP_BLU_EN
828				 | RADEON_DAC_DITHER_EN);
829
830    save->tv_rgb_cntl = (RADEON_RGB_DITHER_EN
831			 | RADEON_TVOUT_SCALE_EN
832			 | (0x0b << RADEON_UVRAM_READ_MARGIN_SHIFT)
833			 | (0x07 << RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT)
834			 | RADEON_RGB_ATTEN_SEL(0x3)
835			 | RADEON_RGB_ATTEN_VAL(0xc));
836
837    if (IsPrimary) {
838	if (radeon_output->Flags & RADEON_USE_RMX)
839	    save->tv_rgb_cntl |= RADEON_RGB_SRC_SEL_RMX;
840	else
841	    save->tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC1;
842    } else {
843	save->tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC2;
844    }
845
846    save->tv_sync_cntl = RADEON_SYNC_PUB | RADEON_TV_SYNC_IO_DRIVE;
847
848    save->tv_sync_size = constPtr->horResolution + 8;
849
850    if (tvout->tvStd == TV_STD_NTSC ||
851	tvout->tvStd == TV_STD_NTSC_J ||
852	tvout->tvStd == TV_STD_PAL_M ||
853	tvout->tvStd == TV_STD_PAL_60)
854	vert_space = constPtr->verTotal * 2 * 10000 / NTSC_TV_LINES_PER_FRAME;
855    else
856	vert_space = constPtr->verTotal * 2 * 10000 / PAL_TV_LINES_PER_FRAME;
857
858    save->tv_vscaler_cntl1 = RADEON_Y_W_EN;
859    save->tv_vscaler_cntl1 =
860	(save->tv_vscaler_cntl1 & 0xe3ff0000) | (vert_space * (1 << FRAC_BITS) / 10000);
861
862    if (pll->reference_freq == 2700)
863	save->tv_vscaler_cntl1 |= RADEON_RESTART_FIELD;
864
865    if (constPtr->horResolution == 1024)
866	save->tv_vscaler_cntl1 |= (4 << RADEON_Y_DEL_W_SIG_SHIFT);
867    else
868	save->tv_vscaler_cntl1 |= (2 << RADEON_Y_DEL_W_SIG_SHIFT);
869
870    if (tvout->tvStd == TV_STD_NTSC ||
871        tvout->tvStd == TV_STD_NTSC_J ||
872        tvout->tvStd == TV_STD_PAL_M ||
873        tvout->tvStd == TV_STD_PAL_60)
874	flicker_removal =
875	    (float) constPtr->verTotal * 2.0 / NTSC_TV_LINES_PER_FRAME + 0.5;
876    else
877	flicker_removal =
878	    (float) constPtr->verTotal * 2.0 / PAL_TV_LINES_PER_FRAME + 0.5;
879
880    if (flicker_removal < 3)
881	flicker_removal = 3;
882    for (i = 0; i < 6; ++i) {
883	if (flicker_removal == SLOPE_limit[i])
884	    break;
885    }
886    save->tv_y_saw_tooth_cntl =
887	(vert_space * SLOPE_value[i] * (1 << (FRAC_BITS - 1)) + 5001) / 10000 / 8
888	| ((SLOPE_value[i] * (1 << (FRAC_BITS - 1)) / 8) << 16);
889    save->tv_y_fall_cntl =
890	(YCOEF_EN_value[i] << 17) | ((YCOEF_value[i] * (1 << 8) / 8) << 24) |
891	RADEON_Y_FALL_PING_PONG | (272 * SLOPE_value[i] / 8) * (1 << (FRAC_BITS - 1)) /
892	1024;
893    save->tv_y_rise_cntl =
894	RADEON_Y_RISE_PING_PONG
895	| (flicker_removal * 1024 - 272) * SLOPE_value[i] / 8 * (1 << (FRAC_BITS - 1)) / 1024;
896
897    save->tv_vscaler_cntl2 = ((save->tv_vscaler_cntl2 & 0x00fffff0)
898			      | (0x10 << 24)
899			      | RADEON_DITHER_MODE
900			      | RADEON_Y_OUTPUT_DITHER_EN
901			      | RADEON_UV_OUTPUT_DITHER_EN
902			      | RADEON_UV_TO_BUF_DITHER_EN);
903
904    tmp = (save->tv_vscaler_cntl1 >> RADEON_UV_INC_SHIFT) & RADEON_UV_INC_MASK;
905    tmp = ((16384 * 256 * 10) / tmp + 5) / 10;
906    tmp = (tmp << RADEON_UV_OUTPUT_POST_SCALE_SHIFT) | 0x000b0000;
907    save->tv_timing_cntl = tmp;
908
909    if (tvout->tvStd == TV_STD_NTSC ||
910        tvout->tvStd == TV_STD_NTSC_J ||
911        tvout->tvStd == TV_STD_PAL_M ||
912        tvout->tvStd == TV_STD_PAL_60)
913	save->tv_dac_cntl = tvdac->ntsc_tvdac_adj;
914    else
915	save->tv_dac_cntl = tvdac->pal_tvdac_adj;
916
917    save->tv_dac_cntl |= (RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD);
918
919    if (tvout->tvStd == TV_STD_NTSC ||
920	tvout->tvStd == TV_STD_NTSC_J)
921	save->tv_dac_cntl |= RADEON_TV_DAC_STD_NTSC;
922    else
923	save->tv_dac_cntl |= RADEON_TV_DAC_STD_PAL;
924
925#if 0
926    /* needs fixes for r4xx */
927    save->tv_dac_cntl |= (RADEON_TV_DAC_RDACPD | RADEON_TV_DAC_GDACPD
928	                 | RADEON_TV_DAC_BDACPD);
929
930    if (radeon_output->MonType == MT_CTV) {
931	save->tv_dac_cntl &= ~RADEON_TV_DAC_BDACPD;
932    }
933
934    if (radeon_output->MonType == MT_STV) {
935	save->tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD |
936			       RADEON_TV_DAC_GDACPD);
937    }
938#endif
939
940    if (tvout->tvStd == TV_STD_NTSC ||
941	tvout->tvStd == TV_STD_NTSC_J) {
942	if (pll->reference_freq == 2700) {
943	    m = NTSC_TV_PLL_M_27;
944	    n = NTSC_TV_PLL_N_27;
945	    p = NTSC_TV_PLL_P_27;
946	} else {
947	    m = NTSC_TV_PLL_M_14;
948	    n = NTSC_TV_PLL_N_14;
949	    p = NTSC_TV_PLL_P_14;
950	}
951    } else {
952	if (pll->reference_freq == 2700) {
953	    m = PAL_TV_PLL_M_27;
954	    n = PAL_TV_PLL_N_27;
955	    p = PAL_TV_PLL_P_27;
956	} else {
957	    m = PAL_TV_PLL_M_14;
958	    n = PAL_TV_PLL_N_14;
959	    p = PAL_TV_PLL_P_14;
960	}
961    }
962    save->tv_pll_cntl = (m & RADEON_TV_M0LO_MASK) |
963	(((m >> 8) & RADEON_TV_M0HI_MASK) << RADEON_TV_M0HI_SHIFT) |
964	((n & RADEON_TV_N0LO_MASK) << RADEON_TV_N0LO_SHIFT) |
965	(((n >> 9) & RADEON_TV_N0HI_MASK) << RADEON_TV_N0HI_SHIFT) |
966	((p & RADEON_TV_P_MASK) << RADEON_TV_P_SHIFT);
967
968    save->tv_pll_cntl1 =  (((4 & RADEON_TVPCP_MASK)<< RADEON_TVPCP_SHIFT) |
969			   ((4 & RADEON_TVPVG_MASK) << RADEON_TVPVG_SHIFT) |
970			   ((1 & RADEON_TVPDC_MASK)<< RADEON_TVPDC_SHIFT) |
971			   RADEON_TVCLK_SRC_SEL_TVPLL |
972			   RADEON_TVPLL_TEST_DIS);
973
974    save->tv_upsamp_and_gain_cntl = RADEON_YUPSAMP_EN | RADEON_UVUPSAMP_EN;
975
976    save->tv_uv_adr = 0xc8;
977
978    save->tv_vdisp = constPtr->verResolution - 1;
979
980    if (tvout->tvStd == TV_STD_NTSC ||
981        tvout->tvStd == TV_STD_NTSC_J ||
982        tvout->tvStd == TV_STD_PAL_M ||
983        tvout->tvStd == TV_STD_PAL_60)
984	save->tv_ftotal = NTSC_TV_VFTOTAL;
985    else
986	save->tv_ftotal = PAL_TV_VFTOTAL;
987
988    save->tv_vtotal = constPtr->verTotal - 1;
989
990    if (tvout->tvStd == TV_STD_NTSC ||
991	tvout->tvStd == TV_STD_NTSC_J ||
992	tvout->tvStd == TV_STD_PAL_M) {
993	hor_timing = hor_timing_NTSC;
994    } else {
995	hor_timing = hor_timing_PAL;
996    }
997
998    if (tvout->tvStd == TV_STD_NTSC ||
999	tvout->tvStd == TV_STD_NTSC_J ||
1000	tvout->tvStd == TV_STD_PAL_M ||
1001	tvout->tvStd == TV_STD_PAL_60) {
1002	vert_timing = vert_timing_NTSC;
1003    } else {
1004	vert_timing = vert_timing_PAL;
1005    }
1006
1007    for (i = 0; i < MAX_H_CODE_TIMING_LEN; i++) {
1008	if ((save->h_code_timing[ i ] = hor_timing[ i ]) == 0)
1009	    break;
1010    }
1011
1012    for (i = 0; i < MAX_V_CODE_TIMING_LEN; i++) {
1013	if ((save->v_code_timing[ i ] = vert_timing[ i ]) == 0)
1014	    break;
1015    }
1016
1017    /*
1018     * This must be called AFTER loading timing tables as they are modified by this function
1019     */
1020    RADEONInitTVRestarts(output, save, mode);
1021
1022    save->dac_cntl &= ~RADEON_DAC_TVO_EN;
1023
1024    if (IS_R300_VARIANT)
1025        save->gpiopad_a = info->SavedReg->gpiopad_a & ~1;
1026
1027    if (IsPrimary) {
1028	save->disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
1029	save->disp_output_cntl |= (RADEON_DISP_TVDAC_SOURCE_CRTC
1030				   | RADEON_DISP_TV_SOURCE_CRTC);
1031    	if (info->ChipFamily >= CHIP_FAMILY_R200) {
1032	    save->disp_tv_out_cntl &= ~RADEON_DISP_TV_PATH_SRC_CRTC2;
1033    	} else {
1034            save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
1035    	}
1036    } else {
1037	save->disp_output_cntl &= ~RADEON_DISP_DAC_SOURCE_MASK;
1038	save->disp_output_cntl |= RADEON_DISP_TV_SOURCE_CRTC;
1039
1040    	if (info->ChipFamily >= CHIP_FAMILY_R200) {
1041	    save->disp_tv_out_cntl |= RADEON_DISP_TV_PATH_SRC_CRTC2;
1042    	} else {
1043            save->disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
1044    	}
1045    }
1046}
1047
1048
1049/* Set hw registers for a new h/v position & h size */
1050void RADEONUpdateHVPosition(xf86OutputPtr output, DisplayModePtr mode)
1051{
1052    ScrnInfoPtr pScrn = output->scrn;
1053    RADEONInfoPtr  info = RADEONPTR(pScrn);
1054    unsigned char *RADEONMMIO = info->MMIO;
1055    Bool reloadTable;
1056    RADEONSavePtr restore = info->ModeReg;
1057
1058    reloadTable = RADEONInitTVRestarts(output, restore, mode);
1059
1060    RADEONRestoreTVRestarts(pScrn, restore);
1061
1062    OUTREG(RADEON_TV_TIMING_CNTL, restore->tv_timing_cntl);
1063
1064    if (reloadTable) {
1065	 OUTREG(RADEON_TV_MASTER_CNTL, restore->tv_master_cntl
1066		                       | RADEON_TV_ASYNC_RST
1067		                       | RADEON_CRT_ASYNC_RST
1068		                       | RADEON_RESTART_PHASE_FIX);
1069
1070	RADEONRestoreTVTimingTables(pScrn, restore);
1071
1072	OUTREG(RADEON_TV_MASTER_CNTL, restore->tv_master_cntl);
1073    }
1074}
1075
1076void RADEONAdjustCrtcRegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save,
1077				    DisplayModePtr mode, xf86OutputPtr output)
1078{
1079    const TVModeConstants *constPtr;
1080    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1081    radeon_tvout_ptr tvout = &radeon_output->tvout;
1082    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1083    RADEONPLLPtr pll = &info->pll;
1084
1085    /* FIXME: need to revisit this when we add more modes */
1086    if (tvout->tvStd == TV_STD_NTSC ||
1087	tvout->tvStd == TV_STD_NTSC_J ||
1088	tvout->tvStd == TV_STD_PAL_M) {
1089	if (pll->reference_freq == 2700)
1090	    constPtr = &availableTVModes[0];
1091	else
1092	    constPtr = &availableTVModes[2];
1093    } else {
1094	if (pll->reference_freq == 2700)
1095	    constPtr = &availableTVModes[1];
1096	else
1097	    constPtr = &availableTVModes[3];
1098    }
1099
1100    save->crtc_h_total_disp = (((constPtr->horResolution / 8) - 1) << RADEON_CRTC_H_DISP_SHIFT) |
1101	(((constPtr->horTotal / 8) - 1) << RADEON_CRTC_H_TOTAL_SHIFT);
1102
1103    save->crtc_h_sync_strt_wid = (save->crtc_h_sync_strt_wid
1104				  & ~(RADEON_CRTC_H_SYNC_STRT_PIX | RADEON_CRTC_H_SYNC_STRT_CHAR)) |
1105	(((constPtr->horSyncStart / 8) - 1) << RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) |
1106	(constPtr->horSyncStart & 7);
1107
1108    save->crtc_v_total_disp = ((constPtr->verResolution - 1) << RADEON_CRTC_V_DISP_SHIFT) |
1109	((constPtr->verTotal - 1) << RADEON_CRTC_V_TOTAL_SHIFT);
1110
1111    save->crtc_v_sync_strt_wid = (save->crtc_v_sync_strt_wid & ~RADEON_CRTC_V_SYNC_STRT) |
1112	((constPtr->verSyncStart - 1) << RADEON_CRTC_V_SYNC_STRT_SHIFT);
1113
1114}
1115
1116void RADEONAdjustPLLRegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save,
1117				   DisplayModePtr mode, xf86OutputPtr output)
1118{
1119    unsigned postDiv;
1120    const TVModeConstants *constPtr;
1121    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1122    radeon_tvout_ptr tvout = &radeon_output->tvout;
1123    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1124    RADEONPLLPtr pll = &info->pll;
1125
1126    /* FIXME: need to revisit this when we add more modes */
1127    if (tvout->tvStd == TV_STD_NTSC ||
1128	tvout->tvStd == TV_STD_NTSC_J ||
1129	tvout->tvStd == TV_STD_PAL_M) {
1130	if (pll->reference_freq == 2700)
1131	    constPtr = &availableTVModes[0];
1132	else
1133	    constPtr = &availableTVModes[2];
1134    } else {
1135	if (pll->reference_freq == 2700)
1136	    constPtr = &availableTVModes[1];
1137	else
1138	    constPtr = &availableTVModes[3];
1139    }
1140
1141    save->htotal_cntl = (constPtr->horTotal & 0x7 /*0xf*/) | RADEON_HTOT_CNTL_VGA_EN;
1142
1143    save->ppll_ref_div = constPtr->crtcPLL_M;
1144
1145    switch (constPtr->crtcPLL_postDiv) {
1146    case 1:
1147	postDiv = 0;
1148	break;
1149    case 2:
1150	postDiv = 1;
1151	break;
1152    case 3:
1153	postDiv = 4;
1154	break;
1155    case 4:
1156	postDiv = 2;
1157	break;
1158    case 6:
1159	postDiv = 6;
1160	break;
1161    case 8:
1162	postDiv = 3;
1163	break;
1164    case 12:
1165	postDiv = 7;
1166	break;
1167    case 16:
1168    default:
1169	postDiv = 5;
1170	break;
1171    }
1172
1173    save->ppll_div_3 = (constPtr->crtcPLL_N & 0x7ff) | (postDiv << 16);
1174
1175    save->pixclks_cntl &= ~(RADEON_PIX2CLK_SRC_SEL_MASK | RADEON_PIXCLK_TV_SRC_SEL);
1176    save->pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK;
1177
1178}
1179
1180void RADEONAdjustCrtc2RegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save,
1181				     DisplayModePtr mode, xf86OutputPtr output)
1182{
1183    const TVModeConstants *constPtr;
1184    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1185    radeon_tvout_ptr tvout = &radeon_output->tvout;
1186    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1187    RADEONPLLPtr pll = &info->pll;
1188
1189    /* FIXME: need to revisit this when we add more modes */
1190    if (tvout->tvStd == TV_STD_NTSC ||
1191	tvout->tvStd == TV_STD_NTSC_J ||
1192	tvout->tvStd == TV_STD_PAL_M) {
1193	if (pll->reference_freq == 2700)
1194	    constPtr = &availableTVModes[0];
1195	else
1196	    constPtr = &availableTVModes[2];
1197    } else {
1198	if (pll->reference_freq == 2700)
1199	    constPtr = &availableTVModes[1];
1200	else
1201	    constPtr = &availableTVModes[3];
1202    }
1203
1204    save->crtc2_h_total_disp = (((constPtr->horResolution / 8) - 1) << RADEON_CRTC_H_DISP_SHIFT) |
1205	(((constPtr->horTotal / 8) - 1) << RADEON_CRTC_H_TOTAL_SHIFT);
1206
1207    save->crtc2_h_sync_strt_wid = (save->crtc2_h_sync_strt_wid
1208				  & ~(RADEON_CRTC_H_SYNC_STRT_PIX | RADEON_CRTC_H_SYNC_STRT_CHAR)) |
1209	(((constPtr->horSyncStart / 8) - 1) << RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) |
1210	(constPtr->horSyncStart & 7);
1211
1212    save->crtc2_v_total_disp = ((constPtr->verResolution - 1) << RADEON_CRTC_V_DISP_SHIFT) |
1213	((constPtr->verTotal - 1) << RADEON_CRTC_V_TOTAL_SHIFT);
1214
1215    save->crtc2_v_sync_strt_wid = (save->crtc2_v_sync_strt_wid & ~RADEON_CRTC_V_SYNC_STRT) |
1216	((constPtr->verSyncStart - 1) << RADEON_CRTC_V_SYNC_STRT_SHIFT);
1217
1218}
1219
1220void RADEONAdjustPLL2RegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save,
1221				    DisplayModePtr mode, xf86OutputPtr output)
1222{
1223    unsigned postDiv;
1224    const TVModeConstants *constPtr;
1225    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1226    radeon_tvout_ptr tvout = &radeon_output->tvout;
1227    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1228    RADEONPLLPtr pll = &info->pll;
1229
1230    /* FIXME: need to revisit this when we add more modes */
1231    if (tvout->tvStd == TV_STD_NTSC ||
1232	tvout->tvStd == TV_STD_NTSC_J ||
1233	tvout->tvStd == TV_STD_PAL_M) {
1234	if (pll->reference_freq == 2700)
1235	    constPtr = &availableTVModes[0];
1236	else
1237	    constPtr = &availableTVModes[2];
1238    } else {
1239	if (pll->reference_freq == 2700)
1240	    constPtr = &availableTVModes[1];
1241	else
1242	    constPtr = &availableTVModes[3];
1243    }
1244
1245    save->htotal_cntl2 = (constPtr->horTotal & 0x7); /* 0xf */
1246
1247    save->p2pll_ref_div = constPtr->crtcPLL_M;
1248
1249    switch (constPtr->crtcPLL_postDiv) {
1250    case 1:
1251	postDiv = 0;
1252	break;
1253    case 2:
1254	postDiv = 1;
1255	break;
1256    case 3:
1257	postDiv = 4;
1258	break;
1259    case 4:
1260	postDiv = 2;
1261	break;
1262    case 6:
1263	postDiv = 6;
1264	break;
1265    case 8:
1266	postDiv = 3;
1267	break;
1268    case 12:
1269	postDiv = 7;
1270	break;
1271    case 16:
1272    default:
1273	postDiv = 5;
1274	break;
1275    }
1276
1277    save->p2pll_div_0 = (constPtr->crtcPLL_N & 0x7ff) | (postDiv << 16);
1278
1279    save->pixclks_cntl &= ~RADEON_PIX2CLK_SRC_SEL_MASK;
1280    save->pixclks_cntl |= (RADEON_PIX2CLK_SRC_SEL_P2PLLCLK
1281			   | RADEON_PIXCLK_TV_SRC_SEL);
1282
1283}
1284