xref: /OK3568_Linux_fs/kernel/drivers/gpu/drm/radeon/radeon_legacy_tv.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: MIT
2*4882a593Smuzhiyun 
3*4882a593Smuzhiyun #include <drm/drm_crtc_helper.h>
4*4882a593Smuzhiyun #include <drm/drm_device.h>
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include "radeon.h"
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun /*
9*4882a593Smuzhiyun  * Integrated TV out support based on the GATOS code by
10*4882a593Smuzhiyun  * Federico Ulivi <fulivi@lycos.com>
11*4882a593Smuzhiyun  */
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun /*
15*4882a593Smuzhiyun  * Limits of h/v positions (hPos & vPos)
16*4882a593Smuzhiyun  */
17*4882a593Smuzhiyun #define MAX_H_POSITION 5 /* Range: [-5..5], negative is on the left, 0 is default, positive is on the right */
18*4882a593Smuzhiyun #define MAX_V_POSITION 5 /* Range: [-5..5], negative is up, 0 is default, positive is down */
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun /*
21*4882a593Smuzhiyun  * Unit for hPos (in TV clock periods)
22*4882a593Smuzhiyun  */
23*4882a593Smuzhiyun #define H_POS_UNIT 10
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun /*
26*4882a593Smuzhiyun  * Indexes in h. code timing table for horizontal line position adjustment
27*4882a593Smuzhiyun  */
28*4882a593Smuzhiyun #define H_TABLE_POS1 6
29*4882a593Smuzhiyun #define H_TABLE_POS2 8
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun /*
32*4882a593Smuzhiyun  * Limits of hor. size (hSize)
33*4882a593Smuzhiyun  */
34*4882a593Smuzhiyun #define MAX_H_SIZE 5 /* Range: [-5..5], negative is smaller, positive is larger */
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun /* tv standard constants */
37*4882a593Smuzhiyun #define NTSC_TV_CLOCK_T 233
38*4882a593Smuzhiyun #define NTSC_TV_VFTOTAL 1
39*4882a593Smuzhiyun #define NTSC_TV_LINES_PER_FRAME 525
40*4882a593Smuzhiyun #define NTSC_TV_ZERO_H_SIZE 479166
41*4882a593Smuzhiyun #define NTSC_TV_H_SIZE_UNIT 9478
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun #define PAL_TV_CLOCK_T 188
44*4882a593Smuzhiyun #define PAL_TV_VFTOTAL 3
45*4882a593Smuzhiyun #define PAL_TV_LINES_PER_FRAME 625
46*4882a593Smuzhiyun #define PAL_TV_ZERO_H_SIZE 473200
47*4882a593Smuzhiyun #define PAL_TV_H_SIZE_UNIT 9360
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun /* tv pll setting for 27 mhz ref clk */
50*4882a593Smuzhiyun #define NTSC_TV_PLL_M_27 22
51*4882a593Smuzhiyun #define NTSC_TV_PLL_N_27 175
52*4882a593Smuzhiyun #define NTSC_TV_PLL_P_27 5
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun #define PAL_TV_PLL_M_27 113
55*4882a593Smuzhiyun #define PAL_TV_PLL_N_27 668
56*4882a593Smuzhiyun #define PAL_TV_PLL_P_27 3
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun /* tv pll setting for 14 mhz ref clk */
59*4882a593Smuzhiyun #define NTSC_TV_PLL_M_14 33
60*4882a593Smuzhiyun #define NTSC_TV_PLL_N_14 693
61*4882a593Smuzhiyun #define NTSC_TV_PLL_P_14 7
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun #define PAL_TV_PLL_M_14 19
64*4882a593Smuzhiyun #define PAL_TV_PLL_N_14 353
65*4882a593Smuzhiyun #define PAL_TV_PLL_P_14 5
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun #define VERT_LEAD_IN_LINES 2
68*4882a593Smuzhiyun #define FRAC_BITS 0xe
69*4882a593Smuzhiyun #define FRAC_MASK 0x3fff
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun struct radeon_tv_mode_constants {
72*4882a593Smuzhiyun 	uint16_t hor_resolution;
73*4882a593Smuzhiyun 	uint16_t ver_resolution;
74*4882a593Smuzhiyun 	enum radeon_tv_std standard;
75*4882a593Smuzhiyun 	uint16_t hor_total;
76*4882a593Smuzhiyun 	uint16_t ver_total;
77*4882a593Smuzhiyun 	uint16_t hor_start;
78*4882a593Smuzhiyun 	uint16_t hor_syncstart;
79*4882a593Smuzhiyun 	uint16_t ver_syncstart;
80*4882a593Smuzhiyun 	unsigned def_restart;
81*4882a593Smuzhiyun 	uint16_t crtcPLL_N;
82*4882a593Smuzhiyun 	uint8_t  crtcPLL_M;
83*4882a593Smuzhiyun 	uint8_t  crtcPLL_post_div;
84*4882a593Smuzhiyun 	unsigned pix_to_tv;
85*4882a593Smuzhiyun };
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun static const uint16_t hor_timing_NTSC[MAX_H_CODE_TIMING_LEN] = {
88*4882a593Smuzhiyun 	0x0007,
89*4882a593Smuzhiyun 	0x003f,
90*4882a593Smuzhiyun 	0x0263,
91*4882a593Smuzhiyun 	0x0a24,
92*4882a593Smuzhiyun 	0x2a6b,
93*4882a593Smuzhiyun 	0x0a36,
94*4882a593Smuzhiyun 	0x126d, /* H_TABLE_POS1 */
95*4882a593Smuzhiyun 	0x1bfe,
96*4882a593Smuzhiyun 	0x1a8f, /* H_TABLE_POS2 */
97*4882a593Smuzhiyun 	0x1ec7,
98*4882a593Smuzhiyun 	0x3863,
99*4882a593Smuzhiyun 	0x1bfe,
100*4882a593Smuzhiyun 	0x1bfe,
101*4882a593Smuzhiyun 	0x1a2a,
102*4882a593Smuzhiyun 	0x1e95,
103*4882a593Smuzhiyun 	0x0e31,
104*4882a593Smuzhiyun 	0x201b,
105*4882a593Smuzhiyun 	0
106*4882a593Smuzhiyun };
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun static const uint16_t vert_timing_NTSC[MAX_V_CODE_TIMING_LEN] = {
109*4882a593Smuzhiyun 	0x2001,
110*4882a593Smuzhiyun 	0x200d,
111*4882a593Smuzhiyun 	0x1006,
112*4882a593Smuzhiyun 	0x0c06,
113*4882a593Smuzhiyun 	0x1006,
114*4882a593Smuzhiyun 	0x1818,
115*4882a593Smuzhiyun 	0x21e3,
116*4882a593Smuzhiyun 	0x1006,
117*4882a593Smuzhiyun 	0x0c06,
118*4882a593Smuzhiyun 	0x1006,
119*4882a593Smuzhiyun 	0x1817,
120*4882a593Smuzhiyun 	0x21d4,
121*4882a593Smuzhiyun 	0x0002,
122*4882a593Smuzhiyun 	0
123*4882a593Smuzhiyun };
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun static const uint16_t hor_timing_PAL[MAX_H_CODE_TIMING_LEN] = {
126*4882a593Smuzhiyun 	0x0007,
127*4882a593Smuzhiyun 	0x0058,
128*4882a593Smuzhiyun 	0x027c,
129*4882a593Smuzhiyun 	0x0a31,
130*4882a593Smuzhiyun 	0x2a77,
131*4882a593Smuzhiyun 	0x0a95,
132*4882a593Smuzhiyun 	0x124f, /* H_TABLE_POS1 */
133*4882a593Smuzhiyun 	0x1bfe,
134*4882a593Smuzhiyun 	0x1b22, /* H_TABLE_POS2 */
135*4882a593Smuzhiyun 	0x1ef9,
136*4882a593Smuzhiyun 	0x387c,
137*4882a593Smuzhiyun 	0x1bfe,
138*4882a593Smuzhiyun 	0x1bfe,
139*4882a593Smuzhiyun 	0x1b31,
140*4882a593Smuzhiyun 	0x1eb5,
141*4882a593Smuzhiyun 	0x0e43,
142*4882a593Smuzhiyun 	0x201b,
143*4882a593Smuzhiyun 	0
144*4882a593Smuzhiyun };
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun static const uint16_t vert_timing_PAL[MAX_V_CODE_TIMING_LEN] = {
147*4882a593Smuzhiyun 	0x2001,
148*4882a593Smuzhiyun 	0x200c,
149*4882a593Smuzhiyun 	0x1005,
150*4882a593Smuzhiyun 	0x0c05,
151*4882a593Smuzhiyun 	0x1005,
152*4882a593Smuzhiyun 	0x1401,
153*4882a593Smuzhiyun 	0x1821,
154*4882a593Smuzhiyun 	0x2240,
155*4882a593Smuzhiyun 	0x1005,
156*4882a593Smuzhiyun 	0x0c05,
157*4882a593Smuzhiyun 	0x1005,
158*4882a593Smuzhiyun 	0x1401,
159*4882a593Smuzhiyun 	0x1822,
160*4882a593Smuzhiyun 	0x2230,
161*4882a593Smuzhiyun 	0x0002,
162*4882a593Smuzhiyun 	0
163*4882a593Smuzhiyun };
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun /**********************************************************************
166*4882a593Smuzhiyun  *
167*4882a593Smuzhiyun  * availableModes
168*4882a593Smuzhiyun  *
169*4882a593Smuzhiyun  * Table of all allowed modes for tv output
170*4882a593Smuzhiyun  *
171*4882a593Smuzhiyun  **********************************************************************/
172*4882a593Smuzhiyun static const struct radeon_tv_mode_constants available_tv_modes[] = {
173*4882a593Smuzhiyun 	{   /* NTSC timing for 27 Mhz ref clk */
174*4882a593Smuzhiyun 		800,                /* horResolution */
175*4882a593Smuzhiyun 		600,                /* verResolution */
176*4882a593Smuzhiyun 		TV_STD_NTSC,        /* standard */
177*4882a593Smuzhiyun 		990,                /* horTotal */
178*4882a593Smuzhiyun 		740,                /* verTotal */
179*4882a593Smuzhiyun 		813,                /* horStart */
180*4882a593Smuzhiyun 		824,                /* horSyncStart */
181*4882a593Smuzhiyun 		632,                /* verSyncStart */
182*4882a593Smuzhiyun 		625592,             /* defRestart */
183*4882a593Smuzhiyun 		592,                /* crtcPLL_N */
184*4882a593Smuzhiyun 		91,                 /* crtcPLL_M */
185*4882a593Smuzhiyun 		4,                  /* crtcPLL_postDiv */
186*4882a593Smuzhiyun 		1022,               /* pixToTV */
187*4882a593Smuzhiyun 	},
188*4882a593Smuzhiyun 	{   /* PAL timing for 27 Mhz ref clk */
189*4882a593Smuzhiyun 		800,               /* horResolution */
190*4882a593Smuzhiyun 		600,               /* verResolution */
191*4882a593Smuzhiyun 		TV_STD_PAL,        /* standard */
192*4882a593Smuzhiyun 		1144,              /* horTotal */
193*4882a593Smuzhiyun 		706,               /* verTotal */
194*4882a593Smuzhiyun 		812,               /* horStart */
195*4882a593Smuzhiyun 		824,               /* horSyncStart */
196*4882a593Smuzhiyun 		669,               /* verSyncStart */
197*4882a593Smuzhiyun 		696700,            /* defRestart */
198*4882a593Smuzhiyun 		1382,              /* crtcPLL_N */
199*4882a593Smuzhiyun 		231,               /* crtcPLL_M */
200*4882a593Smuzhiyun 		4,                 /* crtcPLL_postDiv */
201*4882a593Smuzhiyun 		759,               /* pixToTV */
202*4882a593Smuzhiyun 	},
203*4882a593Smuzhiyun 	{   /* NTSC timing for 14 Mhz ref clk */
204*4882a593Smuzhiyun 		800,                /* horResolution */
205*4882a593Smuzhiyun 		600,                /* verResolution */
206*4882a593Smuzhiyun 		TV_STD_NTSC,        /* standard */
207*4882a593Smuzhiyun 		1018,               /* horTotal */
208*4882a593Smuzhiyun 		727,                /* verTotal */
209*4882a593Smuzhiyun 		813,                /* horStart */
210*4882a593Smuzhiyun 		840,                /* horSyncStart */
211*4882a593Smuzhiyun 		633,                /* verSyncStart */
212*4882a593Smuzhiyun 		630627,             /* defRestart */
213*4882a593Smuzhiyun 		347,                /* crtcPLL_N */
214*4882a593Smuzhiyun 		14,                 /* crtcPLL_M */
215*4882a593Smuzhiyun 		8,                  /* crtcPLL_postDiv */
216*4882a593Smuzhiyun 		1022,               /* pixToTV */
217*4882a593Smuzhiyun 	},
218*4882a593Smuzhiyun 	{ /* PAL timing for 14 Mhz ref clk */
219*4882a593Smuzhiyun 		800,                /* horResolution */
220*4882a593Smuzhiyun 		600,                /* verResolution */
221*4882a593Smuzhiyun 		TV_STD_PAL,         /* standard */
222*4882a593Smuzhiyun 		1131,               /* horTotal */
223*4882a593Smuzhiyun 		742,                /* verTotal */
224*4882a593Smuzhiyun 		813,                /* horStart */
225*4882a593Smuzhiyun 		840,                /* horSyncStart */
226*4882a593Smuzhiyun 		633,                /* verSyncStart */
227*4882a593Smuzhiyun 		708369,             /* defRestart */
228*4882a593Smuzhiyun 		211,                /* crtcPLL_N */
229*4882a593Smuzhiyun 		9,                  /* crtcPLL_M */
230*4882a593Smuzhiyun 		8,                  /* crtcPLL_postDiv */
231*4882a593Smuzhiyun 		759,                /* pixToTV */
232*4882a593Smuzhiyun 	},
233*4882a593Smuzhiyun };
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun #define N_AVAILABLE_MODES ARRAY_SIZE(available_tv_modes)
236*4882a593Smuzhiyun 
radeon_legacy_tv_get_std_mode(struct radeon_encoder * radeon_encoder,uint16_t * pll_ref_freq)237*4882a593Smuzhiyun static const struct radeon_tv_mode_constants *radeon_legacy_tv_get_std_mode(struct radeon_encoder *radeon_encoder,
238*4882a593Smuzhiyun 									    uint16_t *pll_ref_freq)
239*4882a593Smuzhiyun {
240*4882a593Smuzhiyun 	struct drm_device *dev = radeon_encoder->base.dev;
241*4882a593Smuzhiyun 	struct radeon_device *rdev = dev->dev_private;
242*4882a593Smuzhiyun 	struct radeon_crtc *radeon_crtc;
243*4882a593Smuzhiyun 	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
244*4882a593Smuzhiyun 	const struct radeon_tv_mode_constants *const_ptr;
245*4882a593Smuzhiyun 	struct radeon_pll *pll;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	radeon_crtc = to_radeon_crtc(radeon_encoder->base.crtc);
248*4882a593Smuzhiyun 	if (radeon_crtc->crtc_id == 1)
249*4882a593Smuzhiyun 		pll = &rdev->clock.p2pll;
250*4882a593Smuzhiyun 	else
251*4882a593Smuzhiyun 		pll = &rdev->clock.p1pll;
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	if (pll_ref_freq)
254*4882a593Smuzhiyun 		*pll_ref_freq = pll->reference_freq;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	if (tv_dac->tv_std == TV_STD_NTSC ||
257*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_NTSC_J ||
258*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_PAL_M) {
259*4882a593Smuzhiyun 		if (pll->reference_freq == 2700)
260*4882a593Smuzhiyun 			const_ptr = &available_tv_modes[0];
261*4882a593Smuzhiyun 		else
262*4882a593Smuzhiyun 			const_ptr = &available_tv_modes[2];
263*4882a593Smuzhiyun 	} else {
264*4882a593Smuzhiyun 		if (pll->reference_freq == 2700)
265*4882a593Smuzhiyun 			const_ptr = &available_tv_modes[1];
266*4882a593Smuzhiyun 		else
267*4882a593Smuzhiyun 			const_ptr = &available_tv_modes[3];
268*4882a593Smuzhiyun 	}
269*4882a593Smuzhiyun 	return const_ptr;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun static long YCOEF_value[5] = { 2, 2, 0, 4, 0 };
273*4882a593Smuzhiyun static long YCOEF_EN_value[5] = { 1, 1, 0, 1, 0 };
274*4882a593Smuzhiyun static long SLOPE_value[5] = { 1, 2, 2, 4, 8 };
275*4882a593Smuzhiyun static long SLOPE_limit[5] = { 6, 5, 4, 3, 2 };
276*4882a593Smuzhiyun 
radeon_wait_pll_lock(struct drm_encoder * encoder,unsigned n_tests,unsigned n_wait_loops,unsigned cnt_threshold)277*4882a593Smuzhiyun static void radeon_wait_pll_lock(struct drm_encoder *encoder, unsigned n_tests,
278*4882a593Smuzhiyun 				 unsigned n_wait_loops, unsigned cnt_threshold)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun 	struct drm_device *dev = encoder->dev;
281*4882a593Smuzhiyun 	struct radeon_device *rdev = dev->dev_private;
282*4882a593Smuzhiyun 	uint32_t save_pll_test;
283*4882a593Smuzhiyun 	unsigned int i, j;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	WREG32(RADEON_TEST_DEBUG_MUX, (RREG32(RADEON_TEST_DEBUG_MUX) & 0xffff60ff) | 0x100);
286*4882a593Smuzhiyun 	save_pll_test = RREG32_PLL(RADEON_PLL_TEST_CNTL);
287*4882a593Smuzhiyun 	WREG32_PLL(RADEON_PLL_TEST_CNTL, save_pll_test & ~RADEON_PLL_MASK_READ_B);
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	WREG8(RADEON_CLOCK_CNTL_INDEX, RADEON_PLL_TEST_CNTL);
290*4882a593Smuzhiyun 	for (i = 0; i < n_tests; i++) {
291*4882a593Smuzhiyun 		WREG8(RADEON_CLOCK_CNTL_DATA + 3, 0);
292*4882a593Smuzhiyun 		for (j = 0; j < n_wait_loops; j++)
293*4882a593Smuzhiyun 			if (RREG8(RADEON_CLOCK_CNTL_DATA + 3) >= cnt_threshold)
294*4882a593Smuzhiyun 				break;
295*4882a593Smuzhiyun 	}
296*4882a593Smuzhiyun 	WREG32_PLL(RADEON_PLL_TEST_CNTL, save_pll_test);
297*4882a593Smuzhiyun 	WREG32(RADEON_TEST_DEBUG_MUX, RREG32(RADEON_TEST_DEBUG_MUX) & 0xffffe0ff);
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 
radeon_legacy_tv_write_fifo(struct radeon_encoder * radeon_encoder,uint16_t addr,uint32_t value)301*4882a593Smuzhiyun static void radeon_legacy_tv_write_fifo(struct radeon_encoder *radeon_encoder,
302*4882a593Smuzhiyun 					uint16_t addr, uint32_t value)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun 	struct drm_device *dev = radeon_encoder->base.dev;
305*4882a593Smuzhiyun 	struct radeon_device *rdev = dev->dev_private;
306*4882a593Smuzhiyun 	uint32_t tmp;
307*4882a593Smuzhiyun 	int i = 0;
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	WREG32(RADEON_TV_HOST_WRITE_DATA, value);
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr);
312*4882a593Smuzhiyun 	WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_WT);
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	do {
315*4882a593Smuzhiyun 		tmp = RREG32(RADEON_TV_HOST_RD_WT_CNTL);
316*4882a593Smuzhiyun 		if ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0)
317*4882a593Smuzhiyun 			break;
318*4882a593Smuzhiyun 		i++;
319*4882a593Smuzhiyun 	} while (i < 10000);
320*4882a593Smuzhiyun 	WREG32(RADEON_TV_HOST_RD_WT_CNTL, 0);
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun #if 0 /* included for completeness */
324*4882a593Smuzhiyun static uint32_t radeon_legacy_tv_read_fifo(struct radeon_encoder *radeon_encoder, uint16_t addr)
325*4882a593Smuzhiyun {
326*4882a593Smuzhiyun 	struct drm_device *dev = radeon_encoder->base.dev;
327*4882a593Smuzhiyun 	struct radeon_device *rdev = dev->dev_private;
328*4882a593Smuzhiyun 	uint32_t tmp;
329*4882a593Smuzhiyun 	int i = 0;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr);
332*4882a593Smuzhiyun 	WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_RD);
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	do {
335*4882a593Smuzhiyun 		tmp = RREG32(RADEON_TV_HOST_RD_WT_CNTL);
336*4882a593Smuzhiyun 		if ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0)
337*4882a593Smuzhiyun 			break;
338*4882a593Smuzhiyun 		i++;
339*4882a593Smuzhiyun 	} while (i < 10000);
340*4882a593Smuzhiyun 	WREG32(RADEON_TV_HOST_RD_WT_CNTL, 0);
341*4882a593Smuzhiyun 	return RREG32(RADEON_TV_HOST_READ_DATA);
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun #endif
344*4882a593Smuzhiyun 
radeon_get_htiming_tables_addr(uint32_t tv_uv_adr)345*4882a593Smuzhiyun static uint16_t radeon_get_htiming_tables_addr(uint32_t tv_uv_adr)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun 	uint16_t h_table;
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	switch ((tv_uv_adr & RADEON_HCODE_TABLE_SEL_MASK) >> RADEON_HCODE_TABLE_SEL_SHIFT) {
350*4882a593Smuzhiyun 	case 0:
351*4882a593Smuzhiyun 		h_table = RADEON_TV_MAX_FIFO_ADDR_INTERNAL;
352*4882a593Smuzhiyun 		break;
353*4882a593Smuzhiyun 	case 1:
354*4882a593Smuzhiyun 		h_table = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2;
355*4882a593Smuzhiyun 		break;
356*4882a593Smuzhiyun 	case 2:
357*4882a593Smuzhiyun 		h_table = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2;
358*4882a593Smuzhiyun 		break;
359*4882a593Smuzhiyun 	default:
360*4882a593Smuzhiyun 		h_table = 0;
361*4882a593Smuzhiyun 		break;
362*4882a593Smuzhiyun 	}
363*4882a593Smuzhiyun 	return h_table;
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun 
radeon_get_vtiming_tables_addr(uint32_t tv_uv_adr)366*4882a593Smuzhiyun static uint16_t radeon_get_vtiming_tables_addr(uint32_t tv_uv_adr)
367*4882a593Smuzhiyun {
368*4882a593Smuzhiyun 	uint16_t v_table;
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	switch ((tv_uv_adr & RADEON_VCODE_TABLE_SEL_MASK) >> RADEON_VCODE_TABLE_SEL_SHIFT) {
371*4882a593Smuzhiyun 	case 0:
372*4882a593Smuzhiyun 		v_table = ((tv_uv_adr & RADEON_MAX_UV_ADR_MASK) >> RADEON_MAX_UV_ADR_SHIFT) * 2 + 1;
373*4882a593Smuzhiyun 		break;
374*4882a593Smuzhiyun 	case 1:
375*4882a593Smuzhiyun 		v_table = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2 + 1;
376*4882a593Smuzhiyun 		break;
377*4882a593Smuzhiyun 	case 2:
378*4882a593Smuzhiyun 		v_table = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2 + 1;
379*4882a593Smuzhiyun 		break;
380*4882a593Smuzhiyun 	default:
381*4882a593Smuzhiyun 		v_table = 0;
382*4882a593Smuzhiyun 		break;
383*4882a593Smuzhiyun 	}
384*4882a593Smuzhiyun 	return v_table;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun 
radeon_restore_tv_timing_tables(struct radeon_encoder * radeon_encoder)387*4882a593Smuzhiyun static void radeon_restore_tv_timing_tables(struct radeon_encoder *radeon_encoder)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun 	struct drm_device *dev = radeon_encoder->base.dev;
390*4882a593Smuzhiyun 	struct radeon_device *rdev = dev->dev_private;
391*4882a593Smuzhiyun 	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
392*4882a593Smuzhiyun 	uint16_t h_table, v_table;
393*4882a593Smuzhiyun 	uint32_t tmp;
394*4882a593Smuzhiyun 	int i;
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	WREG32(RADEON_TV_UV_ADR, tv_dac->tv.tv_uv_adr);
397*4882a593Smuzhiyun 	h_table = radeon_get_htiming_tables_addr(tv_dac->tv.tv_uv_adr);
398*4882a593Smuzhiyun 	v_table = radeon_get_vtiming_tables_addr(tv_dac->tv.tv_uv_adr);
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2, h_table--) {
401*4882a593Smuzhiyun 		tmp = ((uint32_t)tv_dac->tv.h_code_timing[i] << 14) | ((uint32_t)tv_dac->tv.h_code_timing[i+1]);
402*4882a593Smuzhiyun 		radeon_legacy_tv_write_fifo(radeon_encoder, h_table, tmp);
403*4882a593Smuzhiyun 		if (tv_dac->tv.h_code_timing[i] == 0 || tv_dac->tv.h_code_timing[i + 1] == 0)
404*4882a593Smuzhiyun 			break;
405*4882a593Smuzhiyun 	}
406*4882a593Smuzhiyun 	for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2, v_table++) {
407*4882a593Smuzhiyun 		tmp = ((uint32_t)tv_dac->tv.v_code_timing[i+1] << 14) | ((uint32_t)tv_dac->tv.v_code_timing[i]);
408*4882a593Smuzhiyun 		radeon_legacy_tv_write_fifo(radeon_encoder, v_table, tmp);
409*4882a593Smuzhiyun 		if (tv_dac->tv.v_code_timing[i] == 0 || tv_dac->tv.v_code_timing[i + 1] == 0)
410*4882a593Smuzhiyun 			break;
411*4882a593Smuzhiyun 	}
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun 
radeon_legacy_write_tv_restarts(struct radeon_encoder * radeon_encoder)414*4882a593Smuzhiyun static void radeon_legacy_write_tv_restarts(struct radeon_encoder *radeon_encoder)
415*4882a593Smuzhiyun {
416*4882a593Smuzhiyun 	struct drm_device *dev = radeon_encoder->base.dev;
417*4882a593Smuzhiyun 	struct radeon_device *rdev = dev->dev_private;
418*4882a593Smuzhiyun 	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
419*4882a593Smuzhiyun 	WREG32(RADEON_TV_FRESTART, tv_dac->tv.frestart);
420*4882a593Smuzhiyun 	WREG32(RADEON_TV_HRESTART, tv_dac->tv.hrestart);
421*4882a593Smuzhiyun 	WREG32(RADEON_TV_VRESTART, tv_dac->tv.vrestart);
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun 
radeon_legacy_tv_init_restarts(struct drm_encoder * encoder)424*4882a593Smuzhiyun static bool radeon_legacy_tv_init_restarts(struct drm_encoder *encoder)
425*4882a593Smuzhiyun {
426*4882a593Smuzhiyun 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
427*4882a593Smuzhiyun 	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
428*4882a593Smuzhiyun 	int restart;
429*4882a593Smuzhiyun 	unsigned int h_total, v_total, f_total;
430*4882a593Smuzhiyun 	int v_offset, h_offset;
431*4882a593Smuzhiyun 	u16 p1, p2, h_inc;
432*4882a593Smuzhiyun 	bool h_changed;
433*4882a593Smuzhiyun 	const struct radeon_tv_mode_constants *const_ptr;
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
436*4882a593Smuzhiyun 	if (!const_ptr)
437*4882a593Smuzhiyun 		return false;
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	h_total = const_ptr->hor_total;
440*4882a593Smuzhiyun 	v_total = const_ptr->ver_total;
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	if (tv_dac->tv_std == TV_STD_NTSC ||
443*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_NTSC_J ||
444*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_PAL_M ||
445*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_PAL_60)
446*4882a593Smuzhiyun 		f_total = NTSC_TV_VFTOTAL + 1;
447*4882a593Smuzhiyun 	else
448*4882a593Smuzhiyun 		f_total = PAL_TV_VFTOTAL + 1;
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	/* adjust positions 1&2 in hor. cod timing table */
451*4882a593Smuzhiyun 	h_offset = tv_dac->h_pos * H_POS_UNIT;
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	if (tv_dac->tv_std == TV_STD_NTSC ||
454*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_NTSC_J ||
455*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_PAL_M) {
456*4882a593Smuzhiyun 		h_offset -= 50;
457*4882a593Smuzhiyun 		p1 = hor_timing_NTSC[H_TABLE_POS1];
458*4882a593Smuzhiyun 		p2 = hor_timing_NTSC[H_TABLE_POS2];
459*4882a593Smuzhiyun 	} else {
460*4882a593Smuzhiyun 		p1 = hor_timing_PAL[H_TABLE_POS1];
461*4882a593Smuzhiyun 		p2 = hor_timing_PAL[H_TABLE_POS2];
462*4882a593Smuzhiyun 	}
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	p1 = (u16)((int)p1 + h_offset);
465*4882a593Smuzhiyun 	p2 = (u16)((int)p2 - h_offset);
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 	h_changed = (p1 != tv_dac->tv.h_code_timing[H_TABLE_POS1] ||
468*4882a593Smuzhiyun 		     p2 != tv_dac->tv.h_code_timing[H_TABLE_POS2]);
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	tv_dac->tv.h_code_timing[H_TABLE_POS1] = p1;
471*4882a593Smuzhiyun 	tv_dac->tv.h_code_timing[H_TABLE_POS2] = p2;
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun 	/* Convert hOffset from n. of TV clock periods to n. of CRTC clock periods (CRTC pixels) */
474*4882a593Smuzhiyun 	h_offset = (h_offset * (int)(const_ptr->pix_to_tv)) / 1000;
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	/* adjust restart */
477*4882a593Smuzhiyun 	restart = const_ptr->def_restart;
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	/*
480*4882a593Smuzhiyun 	 * convert v_pos TV lines to n. of CRTC pixels
481*4882a593Smuzhiyun 	 */
482*4882a593Smuzhiyun 	if (tv_dac->tv_std == TV_STD_NTSC ||
483*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_NTSC_J ||
484*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_PAL_M ||
485*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_PAL_60)
486*4882a593Smuzhiyun 		v_offset = ((int)(v_total * h_total) * 2 * tv_dac->v_pos) / (int)(NTSC_TV_LINES_PER_FRAME);
487*4882a593Smuzhiyun 	else
488*4882a593Smuzhiyun 		v_offset = ((int)(v_total * h_total) * 2 * tv_dac->v_pos) / (int)(PAL_TV_LINES_PER_FRAME);
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	restart -= v_offset + h_offset;
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 	DRM_DEBUG_KMS("compute_restarts: def = %u h = %d v = %d, p1 = %04x, p2 = %04x, restart = %d\n",
493*4882a593Smuzhiyun 		  const_ptr->def_restart, tv_dac->h_pos, tv_dac->v_pos, p1, p2, restart);
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun 	tv_dac->tv.hrestart = restart % h_total;
496*4882a593Smuzhiyun 	restart /= h_total;
497*4882a593Smuzhiyun 	tv_dac->tv.vrestart = restart % v_total;
498*4882a593Smuzhiyun 	restart /= v_total;
499*4882a593Smuzhiyun 	tv_dac->tv.frestart = restart % f_total;
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 	DRM_DEBUG_KMS("compute_restart: F/H/V=%u,%u,%u\n",
502*4882a593Smuzhiyun 		  (unsigned)tv_dac->tv.frestart,
503*4882a593Smuzhiyun 		  (unsigned)tv_dac->tv.vrestart,
504*4882a593Smuzhiyun 		  (unsigned)tv_dac->tv.hrestart);
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	/* compute h_inc from hsize */
507*4882a593Smuzhiyun 	if (tv_dac->tv_std == TV_STD_NTSC ||
508*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_NTSC_J ||
509*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_PAL_M)
510*4882a593Smuzhiyun 		h_inc = (u16)((int)(const_ptr->hor_resolution * 4096 * NTSC_TV_CLOCK_T) /
511*4882a593Smuzhiyun 			      (tv_dac->h_size * (int)(NTSC_TV_H_SIZE_UNIT) + (int)(NTSC_TV_ZERO_H_SIZE)));
512*4882a593Smuzhiyun 	else
513*4882a593Smuzhiyun 		h_inc = (u16)((int)(const_ptr->hor_resolution * 4096 * PAL_TV_CLOCK_T) /
514*4882a593Smuzhiyun 			      (tv_dac->h_size * (int)(PAL_TV_H_SIZE_UNIT) + (int)(PAL_TV_ZERO_H_SIZE)));
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	tv_dac->tv.timing_cntl = (tv_dac->tv.timing_cntl & ~RADEON_H_INC_MASK) |
517*4882a593Smuzhiyun 		((u32)h_inc << RADEON_H_INC_SHIFT);
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun 	DRM_DEBUG_KMS("compute_restart: h_size = %d h_inc = %d\n", tv_dac->h_size, h_inc);
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	return h_changed;
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun 
radeon_legacy_tv_mode_set(struct drm_encoder * encoder,struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)524*4882a593Smuzhiyun void radeon_legacy_tv_mode_set(struct drm_encoder *encoder,
525*4882a593Smuzhiyun 			       struct drm_display_mode *mode,
526*4882a593Smuzhiyun 			       struct drm_display_mode *adjusted_mode)
527*4882a593Smuzhiyun {
528*4882a593Smuzhiyun 	struct drm_device *dev = encoder->dev;
529*4882a593Smuzhiyun 	struct radeon_device *rdev = dev->dev_private;
530*4882a593Smuzhiyun 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
531*4882a593Smuzhiyun 	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
532*4882a593Smuzhiyun 	const struct radeon_tv_mode_constants *const_ptr;
533*4882a593Smuzhiyun 	struct radeon_crtc *radeon_crtc;
534*4882a593Smuzhiyun 	int i;
535*4882a593Smuzhiyun 	uint16_t pll_ref_freq;
536*4882a593Smuzhiyun 	uint32_t vert_space, flicker_removal, tmp;
537*4882a593Smuzhiyun 	uint32_t tv_master_cntl, tv_rgb_cntl, tv_dac_cntl;
538*4882a593Smuzhiyun 	uint32_t tv_modulator_cntl1, tv_modulator_cntl2;
539*4882a593Smuzhiyun 	uint32_t tv_vscaler_cntl1, tv_vscaler_cntl2;
540*4882a593Smuzhiyun 	uint32_t tv_pll_cntl, tv_ftotal;
541*4882a593Smuzhiyun 	uint32_t tv_y_fall_cntl, tv_y_rise_cntl, tv_y_saw_tooth_cntl;
542*4882a593Smuzhiyun 	uint32_t m, n, p;
543*4882a593Smuzhiyun 	const uint16_t *hor_timing;
544*4882a593Smuzhiyun 	const uint16_t *vert_timing;
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun 	const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, &pll_ref_freq);
547*4882a593Smuzhiyun 	if (!const_ptr)
548*4882a593Smuzhiyun 		return;
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun 	radeon_crtc = to_radeon_crtc(encoder->crtc);
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 	tv_master_cntl = (RADEON_VIN_ASYNC_RST |
553*4882a593Smuzhiyun 			  RADEON_CRT_FIFO_CE_EN |
554*4882a593Smuzhiyun 			  RADEON_TV_FIFO_CE_EN |
555*4882a593Smuzhiyun 			  RADEON_TV_ON);
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 	if (!ASIC_IS_R300(rdev))
558*4882a593Smuzhiyun 		tv_master_cntl |= RADEON_TVCLK_ALWAYS_ONb;
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 	if (tv_dac->tv_std == TV_STD_NTSC ||
561*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_NTSC_J)
562*4882a593Smuzhiyun 		tv_master_cntl |= RADEON_RESTART_PHASE_FIX;
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	tv_modulator_cntl1 = (RADEON_SLEW_RATE_LIMIT |
565*4882a593Smuzhiyun 			      RADEON_SYNC_TIP_LEVEL |
566*4882a593Smuzhiyun 			      RADEON_YFLT_EN |
567*4882a593Smuzhiyun 			      RADEON_UVFLT_EN |
568*4882a593Smuzhiyun 			      (6 << RADEON_CY_FILT_BLEND_SHIFT));
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 	if (tv_dac->tv_std == TV_STD_NTSC ||
571*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_NTSC_J) {
572*4882a593Smuzhiyun 		tv_modulator_cntl1 |= (0x46 << RADEON_SET_UP_LEVEL_SHIFT) |
573*4882a593Smuzhiyun 			(0x3b << RADEON_BLANK_LEVEL_SHIFT);
574*4882a593Smuzhiyun 		tv_modulator_cntl2 = (-111 & RADEON_TV_U_BURST_LEVEL_MASK) |
575*4882a593Smuzhiyun 			((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT);
576*4882a593Smuzhiyun 	} else if (tv_dac->tv_std == TV_STD_SCART_PAL) {
577*4882a593Smuzhiyun 		tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN;
578*4882a593Smuzhiyun 		tv_modulator_cntl2 = (0 & RADEON_TV_U_BURST_LEVEL_MASK) |
579*4882a593Smuzhiyun 			((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT);
580*4882a593Smuzhiyun 	} else {
581*4882a593Smuzhiyun 		tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN |
582*4882a593Smuzhiyun 			(0x3b << RADEON_SET_UP_LEVEL_SHIFT) |
583*4882a593Smuzhiyun 			(0x3b << RADEON_BLANK_LEVEL_SHIFT);
584*4882a593Smuzhiyun 		tv_modulator_cntl2 = (-78 & RADEON_TV_U_BURST_LEVEL_MASK) |
585*4882a593Smuzhiyun 			((62 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT);
586*4882a593Smuzhiyun 	}
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 	tv_rgb_cntl = (RADEON_RGB_DITHER_EN
590*4882a593Smuzhiyun 		       | RADEON_TVOUT_SCALE_EN
591*4882a593Smuzhiyun 		       | (0x0b << RADEON_UVRAM_READ_MARGIN_SHIFT)
592*4882a593Smuzhiyun 		       | (0x07 << RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT)
593*4882a593Smuzhiyun 		       | RADEON_RGB_ATTEN_SEL(0x3)
594*4882a593Smuzhiyun 		       | RADEON_RGB_ATTEN_VAL(0xc));
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun 	if (radeon_crtc->crtc_id == 1)
597*4882a593Smuzhiyun 		tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC2;
598*4882a593Smuzhiyun 	else {
599*4882a593Smuzhiyun 		if (radeon_crtc->rmx_type != RMX_OFF)
600*4882a593Smuzhiyun 			tv_rgb_cntl |= RADEON_RGB_SRC_SEL_RMX;
601*4882a593Smuzhiyun 		else
602*4882a593Smuzhiyun 			tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC1;
603*4882a593Smuzhiyun 	}
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun 	if (tv_dac->tv_std == TV_STD_NTSC ||
606*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_NTSC_J ||
607*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_PAL_M ||
608*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_PAL_60)
609*4882a593Smuzhiyun 		vert_space = const_ptr->ver_total * 2 * 10000 / NTSC_TV_LINES_PER_FRAME;
610*4882a593Smuzhiyun 	else
611*4882a593Smuzhiyun 		vert_space = const_ptr->ver_total * 2 * 10000 / PAL_TV_LINES_PER_FRAME;
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 	tmp = RREG32(RADEON_TV_VSCALER_CNTL1);
614*4882a593Smuzhiyun 	tmp &= 0xe3ff0000;
615*4882a593Smuzhiyun 	tmp |= (vert_space * (1 << FRAC_BITS) / 10000);
616*4882a593Smuzhiyun 	tv_vscaler_cntl1 = tmp;
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun 	if (pll_ref_freq == 2700)
619*4882a593Smuzhiyun 		tv_vscaler_cntl1 |= RADEON_RESTART_FIELD;
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun 	if (const_ptr->hor_resolution == 1024)
622*4882a593Smuzhiyun 		tv_vscaler_cntl1 |= (4 << RADEON_Y_DEL_W_SIG_SHIFT);
623*4882a593Smuzhiyun 	else
624*4882a593Smuzhiyun 		tv_vscaler_cntl1 |= (2 << RADEON_Y_DEL_W_SIG_SHIFT);
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun 	/* scale up for int divide */
627*4882a593Smuzhiyun 	tmp = const_ptr->ver_total * 2 * 1000;
628*4882a593Smuzhiyun 	if (tv_dac->tv_std == TV_STD_NTSC ||
629*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_NTSC_J ||
630*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_PAL_M ||
631*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_PAL_60) {
632*4882a593Smuzhiyun 		tmp /= NTSC_TV_LINES_PER_FRAME;
633*4882a593Smuzhiyun 	} else {
634*4882a593Smuzhiyun 		tmp /= PAL_TV_LINES_PER_FRAME;
635*4882a593Smuzhiyun 	}
636*4882a593Smuzhiyun 	flicker_removal = (tmp + 500) / 1000;
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 	if (flicker_removal < 3)
639*4882a593Smuzhiyun 		flicker_removal = 3;
640*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(SLOPE_limit); ++i) {
641*4882a593Smuzhiyun 		if (flicker_removal == SLOPE_limit[i])
642*4882a593Smuzhiyun 			break;
643*4882a593Smuzhiyun 	}
644*4882a593Smuzhiyun 
645*4882a593Smuzhiyun 	tv_y_saw_tooth_cntl = (vert_space * SLOPE_value[i] * (1 << (FRAC_BITS - 1)) +
646*4882a593Smuzhiyun 				5001) / 10000 / 8 | ((SLOPE_value[i] *
647*4882a593Smuzhiyun 				(1 << (FRAC_BITS - 1)) / 8) << 16);
648*4882a593Smuzhiyun 	tv_y_fall_cntl =
649*4882a593Smuzhiyun 		(YCOEF_EN_value[i] << 17) | ((YCOEF_value[i] * (1 << 8) / 8) << 24) |
650*4882a593Smuzhiyun 		RADEON_Y_FALL_PING_PONG | (272 * SLOPE_value[i] / 8) * (1 << (FRAC_BITS - 1)) /
651*4882a593Smuzhiyun 		1024;
652*4882a593Smuzhiyun 	tv_y_rise_cntl = RADEON_Y_RISE_PING_PONG|
653*4882a593Smuzhiyun 		(flicker_removal * 1024 - 272) * SLOPE_value[i] / 8 * (1 << (FRAC_BITS - 1)) / 1024;
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun 	tv_vscaler_cntl2 = RREG32(RADEON_TV_VSCALER_CNTL2) & 0x00fffff0;
656*4882a593Smuzhiyun 	tv_vscaler_cntl2 |= (0x10 << 24) |
657*4882a593Smuzhiyun 		RADEON_DITHER_MODE |
658*4882a593Smuzhiyun 		RADEON_Y_OUTPUT_DITHER_EN |
659*4882a593Smuzhiyun 		RADEON_UV_OUTPUT_DITHER_EN |
660*4882a593Smuzhiyun 		RADEON_UV_TO_BUF_DITHER_EN;
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun 	tmp = (tv_vscaler_cntl1 >> RADEON_UV_INC_SHIFT) & RADEON_UV_INC_MASK;
663*4882a593Smuzhiyun 	tmp = ((16384 * 256 * 10) / tmp + 5) / 10;
664*4882a593Smuzhiyun 	tmp = (tmp << RADEON_UV_OUTPUT_POST_SCALE_SHIFT) | 0x000b0000;
665*4882a593Smuzhiyun 	tv_dac->tv.timing_cntl = tmp;
666*4882a593Smuzhiyun 
667*4882a593Smuzhiyun 	if (tv_dac->tv_std == TV_STD_NTSC ||
668*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_NTSC_J ||
669*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_PAL_M ||
670*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_PAL_60)
671*4882a593Smuzhiyun 		tv_dac_cntl = tv_dac->ntsc_tvdac_adj;
672*4882a593Smuzhiyun 	else
673*4882a593Smuzhiyun 		tv_dac_cntl = tv_dac->pal_tvdac_adj;
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun 	tv_dac_cntl |= RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD;
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun 	if (tv_dac->tv_std == TV_STD_NTSC ||
678*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_NTSC_J)
679*4882a593Smuzhiyun 		tv_dac_cntl |= RADEON_TV_DAC_STD_NTSC;
680*4882a593Smuzhiyun 	else
681*4882a593Smuzhiyun 		tv_dac_cntl |= RADEON_TV_DAC_STD_PAL;
682*4882a593Smuzhiyun 
683*4882a593Smuzhiyun 	if (tv_dac->tv_std == TV_STD_NTSC ||
684*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_NTSC_J) {
685*4882a593Smuzhiyun 		if (pll_ref_freq == 2700) {
686*4882a593Smuzhiyun 			m = NTSC_TV_PLL_M_27;
687*4882a593Smuzhiyun 			n = NTSC_TV_PLL_N_27;
688*4882a593Smuzhiyun 			p = NTSC_TV_PLL_P_27;
689*4882a593Smuzhiyun 		} else {
690*4882a593Smuzhiyun 			m = NTSC_TV_PLL_M_14;
691*4882a593Smuzhiyun 			n = NTSC_TV_PLL_N_14;
692*4882a593Smuzhiyun 			p = NTSC_TV_PLL_P_14;
693*4882a593Smuzhiyun 		}
694*4882a593Smuzhiyun 	} else {
695*4882a593Smuzhiyun 		if (pll_ref_freq == 2700) {
696*4882a593Smuzhiyun 			m = PAL_TV_PLL_M_27;
697*4882a593Smuzhiyun 			n = PAL_TV_PLL_N_27;
698*4882a593Smuzhiyun 			p = PAL_TV_PLL_P_27;
699*4882a593Smuzhiyun 		} else {
700*4882a593Smuzhiyun 			m = PAL_TV_PLL_M_14;
701*4882a593Smuzhiyun 			n = PAL_TV_PLL_N_14;
702*4882a593Smuzhiyun 			p = PAL_TV_PLL_P_14;
703*4882a593Smuzhiyun 		}
704*4882a593Smuzhiyun 	}
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun 	tv_pll_cntl = (m & RADEON_TV_M0LO_MASK) |
707*4882a593Smuzhiyun 		(((m >> 8) & RADEON_TV_M0HI_MASK) << RADEON_TV_M0HI_SHIFT) |
708*4882a593Smuzhiyun 		((n & RADEON_TV_N0LO_MASK) << RADEON_TV_N0LO_SHIFT) |
709*4882a593Smuzhiyun 		(((n >> 9) & RADEON_TV_N0HI_MASK) << RADEON_TV_N0HI_SHIFT) |
710*4882a593Smuzhiyun 		((p & RADEON_TV_P_MASK) << RADEON_TV_P_SHIFT);
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun 	tv_dac->tv.tv_uv_adr = 0xc8;
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun 	if (tv_dac->tv_std == TV_STD_NTSC ||
715*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_NTSC_J ||
716*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_PAL_M ||
717*4882a593Smuzhiyun 	    tv_dac->tv_std == TV_STD_PAL_60) {
718*4882a593Smuzhiyun 		tv_ftotal = NTSC_TV_VFTOTAL;
719*4882a593Smuzhiyun 		hor_timing = hor_timing_NTSC;
720*4882a593Smuzhiyun 		vert_timing = vert_timing_NTSC;
721*4882a593Smuzhiyun 	} else {
722*4882a593Smuzhiyun 		hor_timing = hor_timing_PAL;
723*4882a593Smuzhiyun 		vert_timing = vert_timing_PAL;
724*4882a593Smuzhiyun 		tv_ftotal = PAL_TV_VFTOTAL;
725*4882a593Smuzhiyun 	}
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun 	for (i = 0; i < MAX_H_CODE_TIMING_LEN; i++) {
728*4882a593Smuzhiyun 		if ((tv_dac->tv.h_code_timing[i] = hor_timing[i]) == 0)
729*4882a593Smuzhiyun 			break;
730*4882a593Smuzhiyun 	}
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun 	for (i = 0; i < MAX_V_CODE_TIMING_LEN; i++) {
733*4882a593Smuzhiyun 		if ((tv_dac->tv.v_code_timing[i] = vert_timing[i]) == 0)
734*4882a593Smuzhiyun 			break;
735*4882a593Smuzhiyun 	}
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun 	radeon_legacy_tv_init_restarts(encoder);
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	/* play with DAC_CNTL */
740*4882a593Smuzhiyun 	/* play with GPIOPAD_A */
741*4882a593Smuzhiyun 	/* DISP_OUTPUT_CNTL */
742*4882a593Smuzhiyun 	/* use reference freq */
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun 	/* program the TV registers */
745*4882a593Smuzhiyun 	WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST |
746*4882a593Smuzhiyun 				       RADEON_CRT_ASYNC_RST | RADEON_TV_FIFO_ASYNC_RST));
747*4882a593Smuzhiyun 
748*4882a593Smuzhiyun 	tmp = RREG32(RADEON_TV_DAC_CNTL);
749*4882a593Smuzhiyun 	tmp &= ~RADEON_TV_DAC_NBLANK;
750*4882a593Smuzhiyun 	tmp |= RADEON_TV_DAC_BGSLEEP |
751*4882a593Smuzhiyun 		RADEON_TV_DAC_RDACPD |
752*4882a593Smuzhiyun 		RADEON_TV_DAC_GDACPD |
753*4882a593Smuzhiyun 		RADEON_TV_DAC_BDACPD;
754*4882a593Smuzhiyun 	WREG32(RADEON_TV_DAC_CNTL, tmp);
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun 	/* TV PLL */
757*4882a593Smuzhiyun 	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVCLK_SRC_SEL_TVPLL);
758*4882a593Smuzhiyun 	WREG32_PLL(RADEON_TV_PLL_CNTL, tv_pll_cntl);
759*4882a593Smuzhiyun 	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, RADEON_TVPLL_RESET, ~RADEON_TVPLL_RESET);
760*4882a593Smuzhiyun 
761*4882a593Smuzhiyun 	radeon_wait_pll_lock(encoder, 200, 800, 135);
762*4882a593Smuzhiyun 
763*4882a593Smuzhiyun 	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_RESET);
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun 	radeon_wait_pll_lock(encoder, 300, 160, 27);
766*4882a593Smuzhiyun 	radeon_wait_pll_lock(encoder, 200, 800, 135);
767*4882a593Smuzhiyun 
768*4882a593Smuzhiyun 	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~0xf);
769*4882a593Smuzhiyun 	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, RADEON_TVCLK_SRC_SEL_TVPLL, ~RADEON_TVCLK_SRC_SEL_TVPLL);
770*4882a593Smuzhiyun 
771*4882a593Smuzhiyun 	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, (1 << RADEON_TVPDC_SHIFT), ~RADEON_TVPDC_MASK);
772*4882a593Smuzhiyun 	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_SLEEP);
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun 	/* TV HV */
775*4882a593Smuzhiyun 	WREG32(RADEON_TV_RGB_CNTL, tv_rgb_cntl);
776*4882a593Smuzhiyun 	WREG32(RADEON_TV_HTOTAL, const_ptr->hor_total - 1);
777*4882a593Smuzhiyun 	WREG32(RADEON_TV_HDISP, const_ptr->hor_resolution - 1);
778*4882a593Smuzhiyun 	WREG32(RADEON_TV_HSTART, const_ptr->hor_start);
779*4882a593Smuzhiyun 
780*4882a593Smuzhiyun 	WREG32(RADEON_TV_VTOTAL, const_ptr->ver_total - 1);
781*4882a593Smuzhiyun 	WREG32(RADEON_TV_VDISP, const_ptr->ver_resolution - 1);
782*4882a593Smuzhiyun 	WREG32(RADEON_TV_FTOTAL, tv_ftotal);
783*4882a593Smuzhiyun 	WREG32(RADEON_TV_VSCALER_CNTL1, tv_vscaler_cntl1);
784*4882a593Smuzhiyun 	WREG32(RADEON_TV_VSCALER_CNTL2, tv_vscaler_cntl2);
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun 	WREG32(RADEON_TV_Y_FALL_CNTL, tv_y_fall_cntl);
787*4882a593Smuzhiyun 	WREG32(RADEON_TV_Y_RISE_CNTL, tv_y_rise_cntl);
788*4882a593Smuzhiyun 	WREG32(RADEON_TV_Y_SAW_TOOTH_CNTL, tv_y_saw_tooth_cntl);
789*4882a593Smuzhiyun 
790*4882a593Smuzhiyun 	WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST |
791*4882a593Smuzhiyun 				       RADEON_CRT_ASYNC_RST));
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun 	/* TV restarts */
794*4882a593Smuzhiyun 	radeon_legacy_write_tv_restarts(radeon_encoder);
795*4882a593Smuzhiyun 
796*4882a593Smuzhiyun 	/* tv timings */
797*4882a593Smuzhiyun 	radeon_restore_tv_timing_tables(radeon_encoder);
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun 	WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST));
800*4882a593Smuzhiyun 
801*4882a593Smuzhiyun 	/* tv std */
802*4882a593Smuzhiyun 	WREG32(RADEON_TV_SYNC_CNTL, (RADEON_SYNC_PUB | RADEON_TV_SYNC_IO_DRIVE));
803*4882a593Smuzhiyun 	WREG32(RADEON_TV_TIMING_CNTL, tv_dac->tv.timing_cntl);
804*4882a593Smuzhiyun 	WREG32(RADEON_TV_MODULATOR_CNTL1, tv_modulator_cntl1);
805*4882a593Smuzhiyun 	WREG32(RADEON_TV_MODULATOR_CNTL2, tv_modulator_cntl2);
806*4882a593Smuzhiyun 	WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, (RADEON_Y_RED_EN |
807*4882a593Smuzhiyun 					    RADEON_C_GRN_EN |
808*4882a593Smuzhiyun 					    RADEON_CMP_BLU_EN |
809*4882a593Smuzhiyun 					    RADEON_DAC_DITHER_EN));
810*4882a593Smuzhiyun 
811*4882a593Smuzhiyun 	WREG32(RADEON_TV_CRC_CNTL, 0);
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun 	WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
814*4882a593Smuzhiyun 
815*4882a593Smuzhiyun 	WREG32(RADEON_TV_GAIN_LIMIT_SETTINGS, ((0x17f << RADEON_UV_GAIN_LIMIT_SHIFT) |
816*4882a593Smuzhiyun 					       (0x5ff << RADEON_Y_GAIN_LIMIT_SHIFT)));
817*4882a593Smuzhiyun 	WREG32(RADEON_TV_LINEAR_GAIN_SETTINGS, ((0x100 << RADEON_UV_GAIN_SHIFT) |
818*4882a593Smuzhiyun 						(0x100 << RADEON_Y_GAIN_SHIFT)));
819*4882a593Smuzhiyun 
820*4882a593Smuzhiyun 	WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
821*4882a593Smuzhiyun 
822*4882a593Smuzhiyun }
823*4882a593Smuzhiyun 
radeon_legacy_tv_adjust_crtc_reg(struct drm_encoder * encoder,uint32_t * h_total_disp,uint32_t * h_sync_strt_wid,uint32_t * v_total_disp,uint32_t * v_sync_strt_wid)824*4882a593Smuzhiyun void radeon_legacy_tv_adjust_crtc_reg(struct drm_encoder *encoder,
825*4882a593Smuzhiyun 				      uint32_t *h_total_disp, uint32_t *h_sync_strt_wid,
826*4882a593Smuzhiyun 				      uint32_t *v_total_disp, uint32_t *v_sync_strt_wid)
827*4882a593Smuzhiyun {
828*4882a593Smuzhiyun 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
829*4882a593Smuzhiyun 	const struct radeon_tv_mode_constants *const_ptr;
830*4882a593Smuzhiyun 	uint32_t tmp;
831*4882a593Smuzhiyun 
832*4882a593Smuzhiyun 	const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
833*4882a593Smuzhiyun 	if (!const_ptr)
834*4882a593Smuzhiyun 		return;
835*4882a593Smuzhiyun 
836*4882a593Smuzhiyun 	*h_total_disp = (((const_ptr->hor_resolution / 8) - 1) << RADEON_CRTC_H_DISP_SHIFT) |
837*4882a593Smuzhiyun 		(((const_ptr->hor_total / 8) - 1) << RADEON_CRTC_H_TOTAL_SHIFT);
838*4882a593Smuzhiyun 
839*4882a593Smuzhiyun 	tmp = *h_sync_strt_wid;
840*4882a593Smuzhiyun 	tmp &= ~(RADEON_CRTC_H_SYNC_STRT_PIX | RADEON_CRTC_H_SYNC_STRT_CHAR);
841*4882a593Smuzhiyun 	tmp |= (((const_ptr->hor_syncstart / 8) - 1) << RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) |
842*4882a593Smuzhiyun 		(const_ptr->hor_syncstart & 7);
843*4882a593Smuzhiyun 	*h_sync_strt_wid = tmp;
844*4882a593Smuzhiyun 
845*4882a593Smuzhiyun 	*v_total_disp = ((const_ptr->ver_resolution - 1) << RADEON_CRTC_V_DISP_SHIFT) |
846*4882a593Smuzhiyun 		((const_ptr->ver_total - 1) << RADEON_CRTC_V_TOTAL_SHIFT);
847*4882a593Smuzhiyun 
848*4882a593Smuzhiyun 	tmp = *v_sync_strt_wid;
849*4882a593Smuzhiyun 	tmp &= ~RADEON_CRTC_V_SYNC_STRT;
850*4882a593Smuzhiyun 	tmp |= ((const_ptr->ver_syncstart - 1) << RADEON_CRTC_V_SYNC_STRT_SHIFT);
851*4882a593Smuzhiyun 	*v_sync_strt_wid = tmp;
852*4882a593Smuzhiyun }
853*4882a593Smuzhiyun 
get_post_div(int value)854*4882a593Smuzhiyun static int get_post_div(int value)
855*4882a593Smuzhiyun {
856*4882a593Smuzhiyun 	int post_div;
857*4882a593Smuzhiyun 	switch (value) {
858*4882a593Smuzhiyun 	case 1: post_div = 0; break;
859*4882a593Smuzhiyun 	case 2: post_div = 1; break;
860*4882a593Smuzhiyun 	case 3: post_div = 4; break;
861*4882a593Smuzhiyun 	case 4: post_div = 2; break;
862*4882a593Smuzhiyun 	case 6: post_div = 6; break;
863*4882a593Smuzhiyun 	case 8: post_div = 3; break;
864*4882a593Smuzhiyun 	case 12: post_div = 7; break;
865*4882a593Smuzhiyun 	case 16:
866*4882a593Smuzhiyun 	default: post_div = 5; break;
867*4882a593Smuzhiyun 	}
868*4882a593Smuzhiyun 	return post_div;
869*4882a593Smuzhiyun }
870*4882a593Smuzhiyun 
radeon_legacy_tv_adjust_pll1(struct drm_encoder * encoder,uint32_t * htotal_cntl,uint32_t * ppll_ref_div,uint32_t * ppll_div_3,uint32_t * pixclks_cntl)871*4882a593Smuzhiyun void radeon_legacy_tv_adjust_pll1(struct drm_encoder *encoder,
872*4882a593Smuzhiyun 				  uint32_t *htotal_cntl, uint32_t *ppll_ref_div,
873*4882a593Smuzhiyun 				  uint32_t *ppll_div_3, uint32_t *pixclks_cntl)
874*4882a593Smuzhiyun {
875*4882a593Smuzhiyun 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
876*4882a593Smuzhiyun 	const struct radeon_tv_mode_constants *const_ptr;
877*4882a593Smuzhiyun 
878*4882a593Smuzhiyun 	const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
879*4882a593Smuzhiyun 	if (!const_ptr)
880*4882a593Smuzhiyun 		return;
881*4882a593Smuzhiyun 
882*4882a593Smuzhiyun 	*htotal_cntl = (const_ptr->hor_total & 0x7) | RADEON_HTOT_CNTL_VGA_EN;
883*4882a593Smuzhiyun 
884*4882a593Smuzhiyun 	*ppll_ref_div = const_ptr->crtcPLL_M;
885*4882a593Smuzhiyun 
886*4882a593Smuzhiyun 	*ppll_div_3 = (const_ptr->crtcPLL_N & 0x7ff) | (get_post_div(const_ptr->crtcPLL_post_div) << 16);
887*4882a593Smuzhiyun 	*pixclks_cntl &= ~(RADEON_PIX2CLK_SRC_SEL_MASK | RADEON_PIXCLK_TV_SRC_SEL);
888*4882a593Smuzhiyun 	*pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK;
889*4882a593Smuzhiyun }
890*4882a593Smuzhiyun 
radeon_legacy_tv_adjust_pll2(struct drm_encoder * encoder,uint32_t * htotal2_cntl,uint32_t * p2pll_ref_div,uint32_t * p2pll_div_0,uint32_t * pixclks_cntl)891*4882a593Smuzhiyun void radeon_legacy_tv_adjust_pll2(struct drm_encoder *encoder,
892*4882a593Smuzhiyun 				  uint32_t *htotal2_cntl, uint32_t *p2pll_ref_div,
893*4882a593Smuzhiyun 				  uint32_t *p2pll_div_0, uint32_t *pixclks_cntl)
894*4882a593Smuzhiyun {
895*4882a593Smuzhiyun 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
896*4882a593Smuzhiyun 	const struct radeon_tv_mode_constants *const_ptr;
897*4882a593Smuzhiyun 
898*4882a593Smuzhiyun 	const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
899*4882a593Smuzhiyun 	if (!const_ptr)
900*4882a593Smuzhiyun 		return;
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun 	*htotal2_cntl = (const_ptr->hor_total & 0x7);
903*4882a593Smuzhiyun 
904*4882a593Smuzhiyun 	*p2pll_ref_div = const_ptr->crtcPLL_M;
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun 	*p2pll_div_0 = (const_ptr->crtcPLL_N & 0x7ff) | (get_post_div(const_ptr->crtcPLL_post_div) << 16);
907*4882a593Smuzhiyun 	*pixclks_cntl &= ~RADEON_PIX2CLK_SRC_SEL_MASK;
908*4882a593Smuzhiyun 	*pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK | RADEON_PIXCLK_TV_SRC_SEL;
909*4882a593Smuzhiyun }
910*4882a593Smuzhiyun 
911