xref: /linux/drivers/gpu/drm/radeon/radeon_legacy_tv.c (revision a940daa52167e9db8ecce82213813b735a9d9f23)
146924030SJonathan Gray // SPDX-License-Identifier: MIT
2f9183127SSam Ravnborg 
3f9183127SSam Ravnborg #include <drm/drm_device.h>
4f9183127SSam Ravnborg 
54ce001abSDave Airlie #include "radeon.h"
64ce001abSDave Airlie 
74ce001abSDave Airlie /*
84ce001abSDave Airlie  * Integrated TV out support based on the GATOS code by
94ce001abSDave Airlie  * Federico Ulivi <fulivi@lycos.com>
104ce001abSDave Airlie  */
114ce001abSDave Airlie 
124ce001abSDave Airlie 
134ce001abSDave Airlie /*
144ce001abSDave Airlie  * Limits of h/v positions (hPos & vPos)
154ce001abSDave Airlie  */
164ce001abSDave Airlie #define MAX_H_POSITION 5 /* Range: [-5..5], negative is on the left, 0 is default, positive is on the right */
174ce001abSDave Airlie #define MAX_V_POSITION 5 /* Range: [-5..5], negative is up, 0 is default, positive is down */
184ce001abSDave Airlie 
194ce001abSDave Airlie /*
204ce001abSDave Airlie  * Unit for hPos (in TV clock periods)
214ce001abSDave Airlie  */
224ce001abSDave Airlie #define H_POS_UNIT 10
234ce001abSDave Airlie 
244ce001abSDave Airlie /*
254ce001abSDave Airlie  * Indexes in h. code timing table for horizontal line position adjustment
264ce001abSDave Airlie  */
274ce001abSDave Airlie #define H_TABLE_POS1 6
284ce001abSDave Airlie #define H_TABLE_POS2 8
294ce001abSDave Airlie 
304ce001abSDave Airlie /*
314ce001abSDave Airlie  * Limits of hor. size (hSize)
324ce001abSDave Airlie  */
334ce001abSDave Airlie #define MAX_H_SIZE 5 /* Range: [-5..5], negative is smaller, positive is larger */
344ce001abSDave Airlie 
354ce001abSDave Airlie /* tv standard constants */
364ce001abSDave Airlie #define NTSC_TV_CLOCK_T 233
374ce001abSDave Airlie #define NTSC_TV_VFTOTAL 1
384ce001abSDave Airlie #define NTSC_TV_LINES_PER_FRAME 525
394ce001abSDave Airlie #define NTSC_TV_ZERO_H_SIZE 479166
404ce001abSDave Airlie #define NTSC_TV_H_SIZE_UNIT 9478
414ce001abSDave Airlie 
424ce001abSDave Airlie #define PAL_TV_CLOCK_T 188
434ce001abSDave Airlie #define PAL_TV_VFTOTAL 3
444ce001abSDave Airlie #define PAL_TV_LINES_PER_FRAME 625
454ce001abSDave Airlie #define PAL_TV_ZERO_H_SIZE 473200
464ce001abSDave Airlie #define PAL_TV_H_SIZE_UNIT 9360
474ce001abSDave Airlie 
484ce001abSDave Airlie /* tv pll setting for 27 mhz ref clk */
494ce001abSDave Airlie #define NTSC_TV_PLL_M_27 22
504ce001abSDave Airlie #define NTSC_TV_PLL_N_27 175
514ce001abSDave Airlie #define NTSC_TV_PLL_P_27 5
524ce001abSDave Airlie 
534ce001abSDave Airlie #define PAL_TV_PLL_M_27 113
544ce001abSDave Airlie #define PAL_TV_PLL_N_27 668
554ce001abSDave Airlie #define PAL_TV_PLL_P_27 3
564ce001abSDave Airlie 
574ce001abSDave Airlie /* tv pll setting for 14 mhz ref clk */
584ce001abSDave Airlie #define NTSC_TV_PLL_M_14 33
594ce001abSDave Airlie #define NTSC_TV_PLL_N_14 693
604ce001abSDave Airlie #define NTSC_TV_PLL_P_14 7
614ce001abSDave Airlie 
6215f72077SAlex Deucher #define PAL_TV_PLL_M_14 19
6315f72077SAlex Deucher #define PAL_TV_PLL_N_14 353
6415f72077SAlex Deucher #define PAL_TV_PLL_P_14 5
6515f72077SAlex Deucher 
664ce001abSDave Airlie #define VERT_LEAD_IN_LINES 2
674ce001abSDave Airlie #define FRAC_BITS 0xe
684ce001abSDave Airlie #define FRAC_MASK 0x3fff
694ce001abSDave Airlie 
704ce001abSDave Airlie struct radeon_tv_mode_constants {
714ce001abSDave Airlie 	uint16_t hor_resolution;
724ce001abSDave Airlie 	uint16_t ver_resolution;
734ce001abSDave Airlie 	enum radeon_tv_std standard;
744ce001abSDave Airlie 	uint16_t hor_total;
754ce001abSDave Airlie 	uint16_t ver_total;
764ce001abSDave Airlie 	uint16_t hor_start;
774ce001abSDave Airlie 	uint16_t hor_syncstart;
784ce001abSDave Airlie 	uint16_t ver_syncstart;
794ce001abSDave Airlie 	unsigned def_restart;
804ce001abSDave Airlie 	uint16_t crtcPLL_N;
814ce001abSDave Airlie 	uint8_t  crtcPLL_M;
824ce001abSDave Airlie 	uint8_t  crtcPLL_post_div;
834ce001abSDave Airlie 	unsigned pix_to_tv;
844ce001abSDave Airlie };
854ce001abSDave Airlie 
86fc9a89f9SDarren Jenkins static const uint16_t hor_timing_NTSC[MAX_H_CODE_TIMING_LEN] = {
874ce001abSDave Airlie 	0x0007,
884ce001abSDave Airlie 	0x003f,
894ce001abSDave Airlie 	0x0263,
904ce001abSDave Airlie 	0x0a24,
914ce001abSDave Airlie 	0x2a6b,
924ce001abSDave Airlie 	0x0a36,
934ce001abSDave Airlie 	0x126d, /* H_TABLE_POS1 */
944ce001abSDave Airlie 	0x1bfe,
954ce001abSDave Airlie 	0x1a8f, /* H_TABLE_POS2 */
964ce001abSDave Airlie 	0x1ec7,
974ce001abSDave Airlie 	0x3863,
984ce001abSDave Airlie 	0x1bfe,
994ce001abSDave Airlie 	0x1bfe,
1004ce001abSDave Airlie 	0x1a2a,
1014ce001abSDave Airlie 	0x1e95,
1024ce001abSDave Airlie 	0x0e31,
1034ce001abSDave Airlie 	0x201b,
1044ce001abSDave Airlie 	0
1054ce001abSDave Airlie };
1064ce001abSDave Airlie 
107fc9a89f9SDarren Jenkins static const uint16_t vert_timing_NTSC[MAX_V_CODE_TIMING_LEN] = {
1084ce001abSDave Airlie 	0x2001,
1094ce001abSDave Airlie 	0x200d,
1104ce001abSDave Airlie 	0x1006,
1114ce001abSDave Airlie 	0x0c06,
1124ce001abSDave Airlie 	0x1006,
1134ce001abSDave Airlie 	0x1818,
1144ce001abSDave Airlie 	0x21e3,
1154ce001abSDave Airlie 	0x1006,
1164ce001abSDave Airlie 	0x0c06,
1174ce001abSDave Airlie 	0x1006,
1184ce001abSDave Airlie 	0x1817,
1194ce001abSDave Airlie 	0x21d4,
1204ce001abSDave Airlie 	0x0002,
1214ce001abSDave Airlie 	0
1224ce001abSDave Airlie };
1234ce001abSDave Airlie 
124fc9a89f9SDarren Jenkins static const uint16_t hor_timing_PAL[MAX_H_CODE_TIMING_LEN] = {
1254ce001abSDave Airlie 	0x0007,
1264ce001abSDave Airlie 	0x0058,
1274ce001abSDave Airlie 	0x027c,
1284ce001abSDave Airlie 	0x0a31,
1294ce001abSDave Airlie 	0x2a77,
1304ce001abSDave Airlie 	0x0a95,
1314ce001abSDave Airlie 	0x124f, /* H_TABLE_POS1 */
1324ce001abSDave Airlie 	0x1bfe,
1334ce001abSDave Airlie 	0x1b22, /* H_TABLE_POS2 */
1344ce001abSDave Airlie 	0x1ef9,
1354ce001abSDave Airlie 	0x387c,
1364ce001abSDave Airlie 	0x1bfe,
1374ce001abSDave Airlie 	0x1bfe,
1384ce001abSDave Airlie 	0x1b31,
1394ce001abSDave Airlie 	0x1eb5,
1404ce001abSDave Airlie 	0x0e43,
1414ce001abSDave Airlie 	0x201b,
1424ce001abSDave Airlie 	0
1434ce001abSDave Airlie };
1444ce001abSDave Airlie 
145fc9a89f9SDarren Jenkins static const uint16_t vert_timing_PAL[MAX_V_CODE_TIMING_LEN] = {
1464ce001abSDave Airlie 	0x2001,
1474ce001abSDave Airlie 	0x200c,
1484ce001abSDave Airlie 	0x1005,
1494ce001abSDave Airlie 	0x0c05,
1504ce001abSDave Airlie 	0x1005,
1514ce001abSDave Airlie 	0x1401,
1524ce001abSDave Airlie 	0x1821,
1534ce001abSDave Airlie 	0x2240,
1544ce001abSDave Airlie 	0x1005,
1554ce001abSDave Airlie 	0x0c05,
1564ce001abSDave Airlie 	0x1005,
1574ce001abSDave Airlie 	0x1401,
1584ce001abSDave Airlie 	0x1822,
1594ce001abSDave Airlie 	0x2230,
1604ce001abSDave Airlie 	0x0002,
1614ce001abSDave Airlie 	0
1624ce001abSDave Airlie };
1634ce001abSDave Airlie 
1644ce001abSDave Airlie /**********************************************************************
1654ce001abSDave Airlie  *
1664ce001abSDave Airlie  * availableModes
1674ce001abSDave Airlie  *
1684ce001abSDave Airlie  * Table of all allowed modes for tv output
1694ce001abSDave Airlie  *
1704ce001abSDave Airlie  **********************************************************************/
1714ce001abSDave Airlie static const struct radeon_tv_mode_constants available_tv_modes[] = {
1724ce001abSDave Airlie 	{   /* NTSC timing for 27 Mhz ref clk */
1734ce001abSDave Airlie 		800,                /* horResolution */
1744ce001abSDave Airlie 		600,                /* verResolution */
1754ce001abSDave Airlie 		TV_STD_NTSC,        /* standard */
1764ce001abSDave Airlie 		990,                /* horTotal */
1774ce001abSDave Airlie 		740,                /* verTotal */
1784ce001abSDave Airlie 		813,                /* horStart */
1794ce001abSDave Airlie 		824,                /* horSyncStart */
1804ce001abSDave Airlie 		632,                /* verSyncStart */
1814ce001abSDave Airlie 		625592,             /* defRestart */
1824ce001abSDave Airlie 		592,                /* crtcPLL_N */
1834ce001abSDave Airlie 		91,                 /* crtcPLL_M */
1844ce001abSDave Airlie 		4,                  /* crtcPLL_postDiv */
1854ce001abSDave Airlie 		1022,               /* pixToTV */
1864ce001abSDave Airlie 	},
1874ce001abSDave Airlie 	{   /* PAL timing for 27 Mhz ref clk */
1884ce001abSDave Airlie 		800,               /* horResolution */
1894ce001abSDave Airlie 		600,               /* verResolution */
1904ce001abSDave Airlie 		TV_STD_PAL,        /* standard */
1914ce001abSDave Airlie 		1144,              /* horTotal */
1924ce001abSDave Airlie 		706,               /* verTotal */
1934ce001abSDave Airlie 		812,               /* horStart */
1944ce001abSDave Airlie 		824,               /* horSyncStart */
1954ce001abSDave Airlie 		669,               /* verSyncStart */
1964ce001abSDave Airlie 		696700,            /* defRestart */
1974ce001abSDave Airlie 		1382,              /* crtcPLL_N */
1984ce001abSDave Airlie 		231,               /* crtcPLL_M */
1994ce001abSDave Airlie 		4,                 /* crtcPLL_postDiv */
2004ce001abSDave Airlie 		759,               /* pixToTV */
2014ce001abSDave Airlie 	},
2024ce001abSDave Airlie 	{   /* NTSC timing for 14 Mhz ref clk */
2034ce001abSDave Airlie 		800,                /* horResolution */
2044ce001abSDave Airlie 		600,                /* verResolution */
2054ce001abSDave Airlie 		TV_STD_NTSC,        /* standard */
2064ce001abSDave Airlie 		1018,               /* horTotal */
2074ce001abSDave Airlie 		727,                /* verTotal */
2084ce001abSDave Airlie 		813,                /* horStart */
2094ce001abSDave Airlie 		840,                /* horSyncStart */
2104ce001abSDave Airlie 		633,                /* verSyncStart */
2114ce001abSDave Airlie 		630627,             /* defRestart */
2124ce001abSDave Airlie 		347,                /* crtcPLL_N */
2134ce001abSDave Airlie 		14,                 /* crtcPLL_M */
2144ce001abSDave Airlie 		8,                  /* crtcPLL_postDiv */
2154ce001abSDave Airlie 		1022,               /* pixToTV */
2164ce001abSDave Airlie 	},
21715f72077SAlex Deucher 	{ /* PAL timing for 14 Mhz ref clk */
21815f72077SAlex Deucher 		800,                /* horResolution */
21915f72077SAlex Deucher 		600,                /* verResolution */
22015f72077SAlex Deucher 		TV_STD_PAL,         /* standard */
22115f72077SAlex Deucher 		1131,               /* horTotal */
22215f72077SAlex Deucher 		742,                /* verTotal */
22315f72077SAlex Deucher 		813,                /* horStart */
22415f72077SAlex Deucher 		840,                /* horSyncStart */
22515f72077SAlex Deucher 		633,                /* verSyncStart */
22615f72077SAlex Deucher 		708369,             /* defRestart */
22715f72077SAlex Deucher 		211,                /* crtcPLL_N */
22815f72077SAlex Deucher 		9,                  /* crtcPLL_M */
22915f72077SAlex Deucher 		8,                  /* crtcPLL_postDiv */
23015f72077SAlex Deucher 		759,                /* pixToTV */
23115f72077SAlex Deucher 	},
2324ce001abSDave Airlie };
2334ce001abSDave Airlie 
2344ce001abSDave Airlie #define N_AVAILABLE_MODES ARRAY_SIZE(available_tv_modes)
2354ce001abSDave Airlie 
radeon_legacy_tv_get_std_mode(struct radeon_encoder * radeon_encoder,uint16_t * pll_ref_freq)2364ce001abSDave Airlie static const struct radeon_tv_mode_constants *radeon_legacy_tv_get_std_mode(struct radeon_encoder *radeon_encoder,
2374ce001abSDave Airlie 									    uint16_t *pll_ref_freq)
2384ce001abSDave Airlie {
2394ce001abSDave Airlie 	struct drm_device *dev = radeon_encoder->base.dev;
2404ce001abSDave Airlie 	struct radeon_device *rdev = dev->dev_private;
2414ce001abSDave Airlie 	struct radeon_crtc *radeon_crtc;
2424ce001abSDave Airlie 	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
2434ce001abSDave Airlie 	const struct radeon_tv_mode_constants *const_ptr;
2444ce001abSDave Airlie 	struct radeon_pll *pll;
2454ce001abSDave Airlie 
2464ce001abSDave Airlie 	radeon_crtc = to_radeon_crtc(radeon_encoder->base.crtc);
2474ce001abSDave Airlie 	if (radeon_crtc->crtc_id == 1)
2484ce001abSDave Airlie 		pll = &rdev->clock.p2pll;
2494ce001abSDave Airlie 	else
2504ce001abSDave Airlie 		pll = &rdev->clock.p1pll;
2514ce001abSDave Airlie 
2524ce001abSDave Airlie 	if (pll_ref_freq)
2534ce001abSDave Airlie 		*pll_ref_freq = pll->reference_freq;
2544ce001abSDave Airlie 
2554ce001abSDave Airlie 	if (tv_dac->tv_std == TV_STD_NTSC ||
2564ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_NTSC_J ||
2574ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_PAL_M) {
2584ce001abSDave Airlie 		if (pll->reference_freq == 2700)
2594ce001abSDave Airlie 			const_ptr = &available_tv_modes[0];
2604ce001abSDave Airlie 		else
2614ce001abSDave Airlie 			const_ptr = &available_tv_modes[2];
2624ce001abSDave Airlie 	} else {
2634ce001abSDave Airlie 		if (pll->reference_freq == 2700)
2644ce001abSDave Airlie 			const_ptr = &available_tv_modes[1];
2654ce001abSDave Airlie 		else
26615f72077SAlex Deucher 			const_ptr = &available_tv_modes[3];
2674ce001abSDave Airlie 	}
2684ce001abSDave Airlie 	return const_ptr;
2694ce001abSDave Airlie }
2704ce001abSDave Airlie 
2714ce001abSDave Airlie static long YCOEF_value[5] = { 2, 2, 0, 4, 0 };
2724ce001abSDave Airlie static long YCOEF_EN_value[5] = { 1, 1, 0, 1, 0 };
2734ce001abSDave Airlie static long SLOPE_value[5] = { 1, 2, 2, 4, 8 };
2744ce001abSDave Airlie static long SLOPE_limit[5] = { 6, 5, 4, 3, 2 };
2754ce001abSDave Airlie 
radeon_wait_pll_lock(struct drm_encoder * encoder,unsigned n_tests,unsigned n_wait_loops,unsigned cnt_threshold)2764ce001abSDave Airlie static void radeon_wait_pll_lock(struct drm_encoder *encoder, unsigned n_tests,
2774ce001abSDave Airlie 				 unsigned n_wait_loops, unsigned cnt_threshold)
2784ce001abSDave Airlie {
2794ce001abSDave Airlie 	struct drm_device *dev = encoder->dev;
2804ce001abSDave Airlie 	struct radeon_device *rdev = dev->dev_private;
2814ce001abSDave Airlie 	uint32_t save_pll_test;
2824ce001abSDave Airlie 	unsigned int i, j;
2834ce001abSDave Airlie 
2844ce001abSDave Airlie 	WREG32(RADEON_TEST_DEBUG_MUX, (RREG32(RADEON_TEST_DEBUG_MUX) & 0xffff60ff) | 0x100);
2854ce001abSDave Airlie 	save_pll_test = RREG32_PLL(RADEON_PLL_TEST_CNTL);
2864ce001abSDave Airlie 	WREG32_PLL(RADEON_PLL_TEST_CNTL, save_pll_test & ~RADEON_PLL_MASK_READ_B);
2874ce001abSDave Airlie 
2884ce001abSDave Airlie 	WREG8(RADEON_CLOCK_CNTL_INDEX, RADEON_PLL_TEST_CNTL);
2894ce001abSDave Airlie 	for (i = 0; i < n_tests; i++) {
2904ce001abSDave Airlie 		WREG8(RADEON_CLOCK_CNTL_DATA + 3, 0);
2914ce001abSDave Airlie 		for (j = 0; j < n_wait_loops; j++)
2924ce001abSDave Airlie 			if (RREG8(RADEON_CLOCK_CNTL_DATA + 3) >= cnt_threshold)
2934ce001abSDave Airlie 				break;
2944ce001abSDave Airlie 	}
2954ce001abSDave Airlie 	WREG32_PLL(RADEON_PLL_TEST_CNTL, save_pll_test);
2964ce001abSDave Airlie 	WREG32(RADEON_TEST_DEBUG_MUX, RREG32(RADEON_TEST_DEBUG_MUX) & 0xffffe0ff);
2974ce001abSDave Airlie }
2984ce001abSDave Airlie 
2994ce001abSDave Airlie 
radeon_legacy_tv_write_fifo(struct radeon_encoder * radeon_encoder,uint16_t addr,uint32_t value)3004ce001abSDave Airlie static void radeon_legacy_tv_write_fifo(struct radeon_encoder *radeon_encoder,
3014ce001abSDave Airlie 					uint16_t addr, uint32_t value)
3024ce001abSDave Airlie {
3034ce001abSDave Airlie 	struct drm_device *dev = radeon_encoder->base.dev;
3044ce001abSDave Airlie 	struct radeon_device *rdev = dev->dev_private;
3054ce001abSDave Airlie 	uint32_t tmp;
3064ce001abSDave Airlie 	int i = 0;
3074ce001abSDave Airlie 
3084ce001abSDave Airlie 	WREG32(RADEON_TV_HOST_WRITE_DATA, value);
3094ce001abSDave Airlie 
3104ce001abSDave Airlie 	WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr);
3114ce001abSDave Airlie 	WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_WT);
3124ce001abSDave Airlie 
3134ce001abSDave Airlie 	do {
3144ce001abSDave Airlie 		tmp = RREG32(RADEON_TV_HOST_RD_WT_CNTL);
3154ce001abSDave Airlie 		if ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0)
3164ce001abSDave Airlie 			break;
3174ce001abSDave Airlie 		i++;
3184ce001abSDave Airlie 	} while (i < 10000);
3194ce001abSDave Airlie 	WREG32(RADEON_TV_HOST_RD_WT_CNTL, 0);
3204ce001abSDave Airlie }
3214ce001abSDave Airlie 
3224ce001abSDave Airlie #if 0 /* included for completeness */
3234ce001abSDave Airlie static uint32_t radeon_legacy_tv_read_fifo(struct radeon_encoder *radeon_encoder, uint16_t addr)
3244ce001abSDave Airlie {
3254ce001abSDave Airlie 	struct drm_device *dev = radeon_encoder->base.dev;
3264ce001abSDave Airlie 	struct radeon_device *rdev = dev->dev_private;
3274ce001abSDave Airlie 	uint32_t tmp;
3284ce001abSDave Airlie 	int i = 0;
3294ce001abSDave Airlie 
3304ce001abSDave Airlie 	WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr);
3314ce001abSDave Airlie 	WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_RD);
3324ce001abSDave Airlie 
3334ce001abSDave Airlie 	do {
3344ce001abSDave Airlie 		tmp = RREG32(RADEON_TV_HOST_RD_WT_CNTL);
3354ce001abSDave Airlie 		if ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0)
3364ce001abSDave Airlie 			break;
3374ce001abSDave Airlie 		i++;
3384ce001abSDave Airlie 	} while (i < 10000);
3394ce001abSDave Airlie 	WREG32(RADEON_TV_HOST_RD_WT_CNTL, 0);
3404ce001abSDave Airlie 	return RREG32(RADEON_TV_HOST_READ_DATA);
3414ce001abSDave Airlie }
3424ce001abSDave Airlie #endif
3434ce001abSDave Airlie 
radeon_get_htiming_tables_addr(uint32_t tv_uv_adr)3444ce001abSDave Airlie static uint16_t radeon_get_htiming_tables_addr(uint32_t tv_uv_adr)
3454ce001abSDave Airlie {
3464ce001abSDave Airlie 	uint16_t h_table;
3474ce001abSDave Airlie 
3484ce001abSDave Airlie 	switch ((tv_uv_adr & RADEON_HCODE_TABLE_SEL_MASK) >> RADEON_HCODE_TABLE_SEL_SHIFT) {
3494ce001abSDave Airlie 	case 0:
3504ce001abSDave Airlie 		h_table = RADEON_TV_MAX_FIFO_ADDR_INTERNAL;
3514ce001abSDave Airlie 		break;
3524ce001abSDave Airlie 	case 1:
3534ce001abSDave Airlie 		h_table = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2;
3544ce001abSDave Airlie 		break;
3554ce001abSDave Airlie 	case 2:
3564ce001abSDave Airlie 		h_table = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2;
3574ce001abSDave Airlie 		break;
3584ce001abSDave Airlie 	default:
3594ce001abSDave Airlie 		h_table = 0;
3604ce001abSDave Airlie 		break;
3614ce001abSDave Airlie 	}
3624ce001abSDave Airlie 	return h_table;
3634ce001abSDave Airlie }
3644ce001abSDave Airlie 
radeon_get_vtiming_tables_addr(uint32_t tv_uv_adr)3654ce001abSDave Airlie static uint16_t radeon_get_vtiming_tables_addr(uint32_t tv_uv_adr)
3664ce001abSDave Airlie {
3674ce001abSDave Airlie 	uint16_t v_table;
3684ce001abSDave Airlie 
3694ce001abSDave Airlie 	switch ((tv_uv_adr & RADEON_VCODE_TABLE_SEL_MASK) >> RADEON_VCODE_TABLE_SEL_SHIFT) {
3704ce001abSDave Airlie 	case 0:
3714ce001abSDave Airlie 		v_table = ((tv_uv_adr & RADEON_MAX_UV_ADR_MASK) >> RADEON_MAX_UV_ADR_SHIFT) * 2 + 1;
3724ce001abSDave Airlie 		break;
3734ce001abSDave Airlie 	case 1:
3744ce001abSDave Airlie 		v_table = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2 + 1;
3754ce001abSDave Airlie 		break;
3764ce001abSDave Airlie 	case 2:
3774ce001abSDave Airlie 		v_table = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2 + 1;
3784ce001abSDave Airlie 		break;
3794ce001abSDave Airlie 	default:
3804ce001abSDave Airlie 		v_table = 0;
3814ce001abSDave Airlie 		break;
3824ce001abSDave Airlie 	}
3834ce001abSDave Airlie 	return v_table;
3844ce001abSDave Airlie }
3854ce001abSDave Airlie 
radeon_restore_tv_timing_tables(struct radeon_encoder * radeon_encoder)3864ce001abSDave Airlie static void radeon_restore_tv_timing_tables(struct radeon_encoder *radeon_encoder)
3874ce001abSDave Airlie {
3884ce001abSDave Airlie 	struct drm_device *dev = radeon_encoder->base.dev;
3894ce001abSDave Airlie 	struct radeon_device *rdev = dev->dev_private;
3904ce001abSDave Airlie 	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
3914ce001abSDave Airlie 	uint16_t h_table, v_table;
3924ce001abSDave Airlie 	uint32_t tmp;
3934ce001abSDave Airlie 	int i;
3944ce001abSDave Airlie 
3954ce001abSDave Airlie 	WREG32(RADEON_TV_UV_ADR, tv_dac->tv.tv_uv_adr);
3964ce001abSDave Airlie 	h_table = radeon_get_htiming_tables_addr(tv_dac->tv.tv_uv_adr);
3974ce001abSDave Airlie 	v_table = radeon_get_vtiming_tables_addr(tv_dac->tv.tv_uv_adr);
3984ce001abSDave Airlie 
3994ce001abSDave Airlie 	for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2, h_table--) {
4004ce001abSDave Airlie 		tmp = ((uint32_t)tv_dac->tv.h_code_timing[i] << 14) | ((uint32_t)tv_dac->tv.h_code_timing[i+1]);
4014ce001abSDave Airlie 		radeon_legacy_tv_write_fifo(radeon_encoder, h_table, tmp);
4024ce001abSDave Airlie 		if (tv_dac->tv.h_code_timing[i] == 0 || tv_dac->tv.h_code_timing[i + 1] == 0)
4034ce001abSDave Airlie 			break;
4044ce001abSDave Airlie 	}
4054ce001abSDave Airlie 	for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2, v_table++) {
4064ce001abSDave Airlie 		tmp = ((uint32_t)tv_dac->tv.v_code_timing[i+1] << 14) | ((uint32_t)tv_dac->tv.v_code_timing[i]);
4074ce001abSDave Airlie 		radeon_legacy_tv_write_fifo(radeon_encoder, v_table, tmp);
4084ce001abSDave Airlie 		if (tv_dac->tv.v_code_timing[i] == 0 || tv_dac->tv.v_code_timing[i + 1] == 0)
4094ce001abSDave Airlie 			break;
4104ce001abSDave Airlie 	}
4114ce001abSDave Airlie }
4124ce001abSDave Airlie 
radeon_legacy_write_tv_restarts(struct radeon_encoder * radeon_encoder)4134ce001abSDave Airlie static void radeon_legacy_write_tv_restarts(struct radeon_encoder *radeon_encoder)
4144ce001abSDave Airlie {
4154ce001abSDave Airlie 	struct drm_device *dev = radeon_encoder->base.dev;
4164ce001abSDave Airlie 	struct radeon_device *rdev = dev->dev_private;
4174ce001abSDave Airlie 	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
4184ce001abSDave Airlie 	WREG32(RADEON_TV_FRESTART, tv_dac->tv.frestart);
4194ce001abSDave Airlie 	WREG32(RADEON_TV_HRESTART, tv_dac->tv.hrestart);
4204ce001abSDave Airlie 	WREG32(RADEON_TV_VRESTART, tv_dac->tv.vrestart);
4214ce001abSDave Airlie }
4224ce001abSDave Airlie 
radeon_legacy_tv_init_restarts(struct drm_encoder * encoder)4234ce001abSDave Airlie static bool radeon_legacy_tv_init_restarts(struct drm_encoder *encoder)
4244ce001abSDave Airlie {
4254ce001abSDave Airlie 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
4264ce001abSDave Airlie 	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
4274ce001abSDave Airlie 	int restart;
4284ce001abSDave Airlie 	unsigned int h_total, v_total, f_total;
4294ce001abSDave Airlie 	int v_offset, h_offset;
4304ce001abSDave Airlie 	u16 p1, p2, h_inc;
4314ce001abSDave Airlie 	bool h_changed;
4324ce001abSDave Airlie 	const struct radeon_tv_mode_constants *const_ptr;
4334ce001abSDave Airlie 
4344ce001abSDave Airlie 	const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
4354ce001abSDave Airlie 	if (!const_ptr)
4364ce001abSDave Airlie 		return false;
4374ce001abSDave Airlie 
4384ce001abSDave Airlie 	h_total = const_ptr->hor_total;
4394ce001abSDave Airlie 	v_total = const_ptr->ver_total;
4404ce001abSDave Airlie 
4414ce001abSDave Airlie 	if (tv_dac->tv_std == TV_STD_NTSC ||
4424ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_NTSC_J ||
4434ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_PAL_M ||
4444ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_PAL_60)
4454ce001abSDave Airlie 		f_total = NTSC_TV_VFTOTAL + 1;
4464ce001abSDave Airlie 	else
4474ce001abSDave Airlie 		f_total = PAL_TV_VFTOTAL + 1;
4484ce001abSDave Airlie 
4494ce001abSDave Airlie 	/* adjust positions 1&2 in hor. cod timing table */
4504ce001abSDave Airlie 	h_offset = tv_dac->h_pos * H_POS_UNIT;
4514ce001abSDave Airlie 
4524ce001abSDave Airlie 	if (tv_dac->tv_std == TV_STD_NTSC ||
4534ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_NTSC_J ||
4544ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_PAL_M) {
4554ce001abSDave Airlie 		h_offset -= 50;
4564ce001abSDave Airlie 		p1 = hor_timing_NTSC[H_TABLE_POS1];
4574ce001abSDave Airlie 		p2 = hor_timing_NTSC[H_TABLE_POS2];
4584ce001abSDave Airlie 	} else {
4594ce001abSDave Airlie 		p1 = hor_timing_PAL[H_TABLE_POS1];
4604ce001abSDave Airlie 		p2 = hor_timing_PAL[H_TABLE_POS2];
4614ce001abSDave Airlie 	}
4624ce001abSDave Airlie 
4634ce001abSDave Airlie 	p1 = (u16)((int)p1 + h_offset);
4644ce001abSDave Airlie 	p2 = (u16)((int)p2 - h_offset);
4654ce001abSDave Airlie 
4664ce001abSDave Airlie 	h_changed = (p1 != tv_dac->tv.h_code_timing[H_TABLE_POS1] ||
4674ce001abSDave Airlie 		     p2 != tv_dac->tv.h_code_timing[H_TABLE_POS2]);
4684ce001abSDave Airlie 
4694ce001abSDave Airlie 	tv_dac->tv.h_code_timing[H_TABLE_POS1] = p1;
4704ce001abSDave Airlie 	tv_dac->tv.h_code_timing[H_TABLE_POS2] = p2;
4714ce001abSDave Airlie 
4724ce001abSDave Airlie 	/* Convert hOffset from n. of TV clock periods to n. of CRTC clock periods (CRTC pixels) */
4734ce001abSDave Airlie 	h_offset = (h_offset * (int)(const_ptr->pix_to_tv)) / 1000;
4744ce001abSDave Airlie 
4754ce001abSDave Airlie 	/* adjust restart */
4764ce001abSDave Airlie 	restart = const_ptr->def_restart;
4774ce001abSDave Airlie 
4784ce001abSDave Airlie 	/*
4794ce001abSDave Airlie 	 * convert v_pos TV lines to n. of CRTC pixels
4804ce001abSDave Airlie 	 */
4814ce001abSDave Airlie 	if (tv_dac->tv_std == TV_STD_NTSC ||
4824ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_NTSC_J ||
4834ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_PAL_M ||
4844ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_PAL_60)
4854ce001abSDave Airlie 		v_offset = ((int)(v_total * h_total) * 2 * tv_dac->v_pos) / (int)(NTSC_TV_LINES_PER_FRAME);
4864ce001abSDave Airlie 	else
4874ce001abSDave Airlie 		v_offset = ((int)(v_total * h_total) * 2 * tv_dac->v_pos) / (int)(PAL_TV_LINES_PER_FRAME);
4884ce001abSDave Airlie 
4894ce001abSDave Airlie 	restart -= v_offset + h_offset;
4904ce001abSDave Airlie 
491d9fdaafbSDave Airlie 	DRM_DEBUG_KMS("compute_restarts: def = %u h = %d v = %d, p1 = %04x, p2 = %04x, restart = %d\n",
4924ce001abSDave Airlie 		  const_ptr->def_restart, tv_dac->h_pos, tv_dac->v_pos, p1, p2, restart);
4934ce001abSDave Airlie 
4944ce001abSDave Airlie 	tv_dac->tv.hrestart = restart % h_total;
4954ce001abSDave Airlie 	restart /= h_total;
4964ce001abSDave Airlie 	tv_dac->tv.vrestart = restart % v_total;
4974ce001abSDave Airlie 	restart /= v_total;
4984ce001abSDave Airlie 	tv_dac->tv.frestart = restart % f_total;
4994ce001abSDave Airlie 
500d9fdaafbSDave Airlie 	DRM_DEBUG_KMS("compute_restart: F/H/V=%u,%u,%u\n",
5014ce001abSDave Airlie 		  (unsigned)tv_dac->tv.frestart,
5024ce001abSDave Airlie 		  (unsigned)tv_dac->tv.vrestart,
5034ce001abSDave Airlie 		  (unsigned)tv_dac->tv.hrestart);
5044ce001abSDave Airlie 
5054ce001abSDave Airlie 	/* compute h_inc from hsize */
5064ce001abSDave Airlie 	if (tv_dac->tv_std == TV_STD_NTSC ||
5074ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_NTSC_J ||
5084ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_PAL_M)
5094ce001abSDave Airlie 		h_inc = (u16)((int)(const_ptr->hor_resolution * 4096 * NTSC_TV_CLOCK_T) /
5104ce001abSDave Airlie 			      (tv_dac->h_size * (int)(NTSC_TV_H_SIZE_UNIT) + (int)(NTSC_TV_ZERO_H_SIZE)));
5114ce001abSDave Airlie 	else
5124ce001abSDave Airlie 		h_inc = (u16)((int)(const_ptr->hor_resolution * 4096 * PAL_TV_CLOCK_T) /
5134ce001abSDave Airlie 			      (tv_dac->h_size * (int)(PAL_TV_H_SIZE_UNIT) + (int)(PAL_TV_ZERO_H_SIZE)));
5144ce001abSDave Airlie 
5154ce001abSDave Airlie 	tv_dac->tv.timing_cntl = (tv_dac->tv.timing_cntl & ~RADEON_H_INC_MASK) |
5164ce001abSDave Airlie 		((u32)h_inc << RADEON_H_INC_SHIFT);
5174ce001abSDave Airlie 
518d9fdaafbSDave Airlie 	DRM_DEBUG_KMS("compute_restart: h_size = %d h_inc = %d\n", tv_dac->h_size, h_inc);
5194ce001abSDave Airlie 
5204ce001abSDave Airlie 	return h_changed;
5214ce001abSDave Airlie }
5224ce001abSDave Airlie 
radeon_legacy_tv_mode_set(struct drm_encoder * encoder,struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)5234ce001abSDave Airlie void radeon_legacy_tv_mode_set(struct drm_encoder *encoder,
5244ce001abSDave Airlie 			       struct drm_display_mode *mode,
5254ce001abSDave Airlie 			       struct drm_display_mode *adjusted_mode)
5264ce001abSDave Airlie {
5274ce001abSDave Airlie 	struct drm_device *dev = encoder->dev;
5284ce001abSDave Airlie 	struct radeon_device *rdev = dev->dev_private;
5294ce001abSDave Airlie 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
5304ce001abSDave Airlie 	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
5314ce001abSDave Airlie 	const struct radeon_tv_mode_constants *const_ptr;
5324ce001abSDave Airlie 	struct radeon_crtc *radeon_crtc;
5334ce001abSDave Airlie 	int i;
5344ce001abSDave Airlie 	uint16_t pll_ref_freq;
5354ce001abSDave Airlie 	uint32_t vert_space, flicker_removal, tmp;
5364ce001abSDave Airlie 	uint32_t tv_master_cntl, tv_rgb_cntl, tv_dac_cntl;
5374ce001abSDave Airlie 	uint32_t tv_modulator_cntl1, tv_modulator_cntl2;
5384ce001abSDave Airlie 	uint32_t tv_vscaler_cntl1, tv_vscaler_cntl2;
539dc9b3dbdSzhengbin 	uint32_t tv_pll_cntl, tv_ftotal;
5404ce001abSDave Airlie 	uint32_t tv_y_fall_cntl, tv_y_rise_cntl, tv_y_saw_tooth_cntl;
5414ce001abSDave Airlie 	uint32_t m, n, p;
5424ce001abSDave Airlie 	const uint16_t *hor_timing;
5434ce001abSDave Airlie 	const uint16_t *vert_timing;
5444ce001abSDave Airlie 
5454ce001abSDave Airlie 	const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, &pll_ref_freq);
5464ce001abSDave Airlie 	if (!const_ptr)
5474ce001abSDave Airlie 		return;
5484ce001abSDave Airlie 
5494ce001abSDave Airlie 	radeon_crtc = to_radeon_crtc(encoder->crtc);
5504ce001abSDave Airlie 
5514ce001abSDave Airlie 	tv_master_cntl = (RADEON_VIN_ASYNC_RST |
5524ce001abSDave Airlie 			  RADEON_CRT_FIFO_CE_EN |
5534ce001abSDave Airlie 			  RADEON_TV_FIFO_CE_EN |
5544ce001abSDave Airlie 			  RADEON_TV_ON);
5554ce001abSDave Airlie 
5564ce001abSDave Airlie 	if (!ASIC_IS_R300(rdev))
5574ce001abSDave Airlie 		tv_master_cntl |= RADEON_TVCLK_ALWAYS_ONb;
5584ce001abSDave Airlie 
5594ce001abSDave Airlie 	if (tv_dac->tv_std == TV_STD_NTSC ||
5604ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_NTSC_J)
5614ce001abSDave Airlie 		tv_master_cntl |= RADEON_RESTART_PHASE_FIX;
5624ce001abSDave Airlie 
5634ce001abSDave Airlie 	tv_modulator_cntl1 = (RADEON_SLEW_RATE_LIMIT |
5644ce001abSDave Airlie 			      RADEON_SYNC_TIP_LEVEL |
5654ce001abSDave Airlie 			      RADEON_YFLT_EN |
5664ce001abSDave Airlie 			      RADEON_UVFLT_EN |
5674ce001abSDave Airlie 			      (6 << RADEON_CY_FILT_BLEND_SHIFT));
5684ce001abSDave Airlie 
5694ce001abSDave Airlie 	if (tv_dac->tv_std == TV_STD_NTSC ||
5704ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_NTSC_J) {
5714ce001abSDave Airlie 		tv_modulator_cntl1 |= (0x46 << RADEON_SET_UP_LEVEL_SHIFT) |
5724ce001abSDave Airlie 			(0x3b << RADEON_BLANK_LEVEL_SHIFT);
5734ce001abSDave Airlie 		tv_modulator_cntl2 = (-111 & RADEON_TV_U_BURST_LEVEL_MASK) |
5744ce001abSDave Airlie 			((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT);
5754ce001abSDave Airlie 	} else if (tv_dac->tv_std == TV_STD_SCART_PAL) {
5764ce001abSDave Airlie 		tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN;
5774ce001abSDave Airlie 		tv_modulator_cntl2 = (0 & RADEON_TV_U_BURST_LEVEL_MASK) |
5784ce001abSDave Airlie 			((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT);
5794ce001abSDave Airlie 	} else {
5804ce001abSDave Airlie 		tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN |
5814ce001abSDave Airlie 			(0x3b << RADEON_SET_UP_LEVEL_SHIFT) |
5824ce001abSDave Airlie 			(0x3b << RADEON_BLANK_LEVEL_SHIFT);
5834ce001abSDave Airlie 		tv_modulator_cntl2 = (-78 & RADEON_TV_U_BURST_LEVEL_MASK) |
5844ce001abSDave Airlie 			((62 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT);
5854ce001abSDave Airlie 	}
5864ce001abSDave Airlie 
5874ce001abSDave Airlie 
5884ce001abSDave Airlie 	tv_rgb_cntl = (RADEON_RGB_DITHER_EN
5894ce001abSDave Airlie 		       | RADEON_TVOUT_SCALE_EN
5904ce001abSDave Airlie 		       | (0x0b << RADEON_UVRAM_READ_MARGIN_SHIFT)
5914ce001abSDave Airlie 		       | (0x07 << RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT)
5924ce001abSDave Airlie 		       | RADEON_RGB_ATTEN_SEL(0x3)
5934ce001abSDave Airlie 		       | RADEON_RGB_ATTEN_VAL(0xc));
5944ce001abSDave Airlie 
5954ce001abSDave Airlie 	if (radeon_crtc->crtc_id == 1)
5964ce001abSDave Airlie 		tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC2;
5974ce001abSDave Airlie 	else {
5984ce001abSDave Airlie 		if (radeon_crtc->rmx_type != RMX_OFF)
5994ce001abSDave Airlie 			tv_rgb_cntl |= RADEON_RGB_SRC_SEL_RMX;
6004ce001abSDave Airlie 		else
6014ce001abSDave Airlie 			tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC1;
6024ce001abSDave Airlie 	}
6034ce001abSDave Airlie 
6044ce001abSDave Airlie 	if (tv_dac->tv_std == TV_STD_NTSC ||
6054ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_NTSC_J ||
6064ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_PAL_M ||
6074ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_PAL_60)
6084ce001abSDave Airlie 		vert_space = const_ptr->ver_total * 2 * 10000 / NTSC_TV_LINES_PER_FRAME;
6094ce001abSDave Airlie 	else
6104ce001abSDave Airlie 		vert_space = const_ptr->ver_total * 2 * 10000 / PAL_TV_LINES_PER_FRAME;
6114ce001abSDave Airlie 
6124ce001abSDave Airlie 	tmp = RREG32(RADEON_TV_VSCALER_CNTL1);
6134ce001abSDave Airlie 	tmp &= 0xe3ff0000;
6144ce001abSDave Airlie 	tmp |= (vert_space * (1 << FRAC_BITS) / 10000);
6154ce001abSDave Airlie 	tv_vscaler_cntl1 = tmp;
6164ce001abSDave Airlie 
6174ce001abSDave Airlie 	if (pll_ref_freq == 2700)
6184ce001abSDave Airlie 		tv_vscaler_cntl1 |= RADEON_RESTART_FIELD;
6194ce001abSDave Airlie 
6204ce001abSDave Airlie 	if (const_ptr->hor_resolution == 1024)
6214ce001abSDave Airlie 		tv_vscaler_cntl1 |= (4 << RADEON_Y_DEL_W_SIG_SHIFT);
6224ce001abSDave Airlie 	else
6234ce001abSDave Airlie 		tv_vscaler_cntl1 |= (2 << RADEON_Y_DEL_W_SIG_SHIFT);
6244ce001abSDave Airlie 
6254ce001abSDave Airlie 	/* scale up for int divide */
6264ce001abSDave Airlie 	tmp = const_ptr->ver_total * 2 * 1000;
6274ce001abSDave Airlie 	if (tv_dac->tv_std == TV_STD_NTSC ||
6284ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_NTSC_J ||
6294ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_PAL_M ||
6304ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_PAL_60) {
6314ce001abSDave Airlie 		tmp /= NTSC_TV_LINES_PER_FRAME;
6324ce001abSDave Airlie 	} else {
6334ce001abSDave Airlie 		tmp /= PAL_TV_LINES_PER_FRAME;
6344ce001abSDave Airlie 	}
6354ce001abSDave Airlie 	flicker_removal = (tmp + 500) / 1000;
6364ce001abSDave Airlie 
637ff3f011cSAlex Deucher 	if (flicker_removal < 3)
638ff3f011cSAlex Deucher 		flicker_removal = 3;
639fc9a89f9SDarren Jenkins 	for (i = 0; i < ARRAY_SIZE(SLOPE_limit); ++i) {
6404ce001abSDave Airlie 		if (flicker_removal == SLOPE_limit[i])
6414ce001abSDave Airlie 			break;
6424ce001abSDave Airlie 	}
6434ce001abSDave Airlie 
6444ce001abSDave Airlie 	tv_y_saw_tooth_cntl = (vert_space * SLOPE_value[i] * (1 << (FRAC_BITS - 1)) +
6454ce001abSDave Airlie 				5001) / 10000 / 8 | ((SLOPE_value[i] *
6464ce001abSDave Airlie 				(1 << (FRAC_BITS - 1)) / 8) << 16);
6474ce001abSDave Airlie 	tv_y_fall_cntl =
6484ce001abSDave Airlie 		(YCOEF_EN_value[i] << 17) | ((YCOEF_value[i] * (1 << 8) / 8) << 24) |
6494ce001abSDave Airlie 		RADEON_Y_FALL_PING_PONG | (272 * SLOPE_value[i] / 8) * (1 << (FRAC_BITS - 1)) /
6504ce001abSDave Airlie 		1024;
6514ce001abSDave Airlie 	tv_y_rise_cntl = RADEON_Y_RISE_PING_PONG|
6524ce001abSDave Airlie 		(flicker_removal * 1024 - 272) * SLOPE_value[i] / 8 * (1 << (FRAC_BITS - 1)) / 1024;
6534ce001abSDave Airlie 
6544ce001abSDave Airlie 	tv_vscaler_cntl2 = RREG32(RADEON_TV_VSCALER_CNTL2) & 0x00fffff0;
6554ce001abSDave Airlie 	tv_vscaler_cntl2 |= (0x10 << 24) |
6564ce001abSDave Airlie 		RADEON_DITHER_MODE |
6574ce001abSDave Airlie 		RADEON_Y_OUTPUT_DITHER_EN |
6584ce001abSDave Airlie 		RADEON_UV_OUTPUT_DITHER_EN |
6594ce001abSDave Airlie 		RADEON_UV_TO_BUF_DITHER_EN;
6604ce001abSDave Airlie 
6614ce001abSDave Airlie 	tmp = (tv_vscaler_cntl1 >> RADEON_UV_INC_SHIFT) & RADEON_UV_INC_MASK;
6624ce001abSDave Airlie 	tmp = ((16384 * 256 * 10) / tmp + 5) / 10;
6634ce001abSDave Airlie 	tmp = (tmp << RADEON_UV_OUTPUT_POST_SCALE_SHIFT) | 0x000b0000;
6644ce001abSDave Airlie 	tv_dac->tv.timing_cntl = tmp;
6654ce001abSDave Airlie 
6664ce001abSDave Airlie 	if (tv_dac->tv_std == TV_STD_NTSC ||
6674ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_NTSC_J ||
6684ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_PAL_M ||
6694ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_PAL_60)
6704ce001abSDave Airlie 		tv_dac_cntl = tv_dac->ntsc_tvdac_adj;
6714ce001abSDave Airlie 	else
6724ce001abSDave Airlie 		tv_dac_cntl = tv_dac->pal_tvdac_adj;
6734ce001abSDave Airlie 
6744ce001abSDave Airlie 	tv_dac_cntl |= RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD;
6754ce001abSDave Airlie 
6764ce001abSDave Airlie 	if (tv_dac->tv_std == TV_STD_NTSC ||
6774ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_NTSC_J)
6784ce001abSDave Airlie 		tv_dac_cntl |= RADEON_TV_DAC_STD_NTSC;
6794ce001abSDave Airlie 	else
6804ce001abSDave Airlie 		tv_dac_cntl |= RADEON_TV_DAC_STD_PAL;
6814ce001abSDave Airlie 
6824ce001abSDave Airlie 	if (tv_dac->tv_std == TV_STD_NTSC ||
6834ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_NTSC_J) {
6844ce001abSDave Airlie 		if (pll_ref_freq == 2700) {
6854ce001abSDave Airlie 			m = NTSC_TV_PLL_M_27;
6864ce001abSDave Airlie 			n = NTSC_TV_PLL_N_27;
6874ce001abSDave Airlie 			p = NTSC_TV_PLL_P_27;
6884ce001abSDave Airlie 		} else {
6894ce001abSDave Airlie 			m = NTSC_TV_PLL_M_14;
6904ce001abSDave Airlie 			n = NTSC_TV_PLL_N_14;
6914ce001abSDave Airlie 			p = NTSC_TV_PLL_P_14;
6924ce001abSDave Airlie 		}
6934ce001abSDave Airlie 	} else {
6944ce001abSDave Airlie 		if (pll_ref_freq == 2700) {
6954ce001abSDave Airlie 			m = PAL_TV_PLL_M_27;
6964ce001abSDave Airlie 			n = PAL_TV_PLL_N_27;
6974ce001abSDave Airlie 			p = PAL_TV_PLL_P_27;
6984ce001abSDave Airlie 		} else {
69915f72077SAlex Deucher 			m = PAL_TV_PLL_M_14;
70015f72077SAlex Deucher 			n = PAL_TV_PLL_N_14;
70115f72077SAlex Deucher 			p = PAL_TV_PLL_P_14;
7024ce001abSDave Airlie 		}
7034ce001abSDave Airlie 	}
7044ce001abSDave Airlie 
7054ce001abSDave Airlie 	tv_pll_cntl = (m & RADEON_TV_M0LO_MASK) |
7064ce001abSDave Airlie 		(((m >> 8) & RADEON_TV_M0HI_MASK) << RADEON_TV_M0HI_SHIFT) |
7074ce001abSDave Airlie 		((n & RADEON_TV_N0LO_MASK) << RADEON_TV_N0LO_SHIFT) |
7084ce001abSDave Airlie 		(((n >> 9) & RADEON_TV_N0HI_MASK) << RADEON_TV_N0HI_SHIFT) |
7094ce001abSDave Airlie 		((p & RADEON_TV_P_MASK) << RADEON_TV_P_SHIFT);
7104ce001abSDave Airlie 
7114ce001abSDave Airlie 	tv_dac->tv.tv_uv_adr = 0xc8;
7124ce001abSDave Airlie 
7134ce001abSDave Airlie 	if (tv_dac->tv_std == TV_STD_NTSC ||
7144ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_NTSC_J ||
7154ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_PAL_M ||
7164ce001abSDave Airlie 	    tv_dac->tv_std == TV_STD_PAL_60) {
7174ce001abSDave Airlie 		tv_ftotal = NTSC_TV_VFTOTAL;
7184ce001abSDave Airlie 		hor_timing = hor_timing_NTSC;
7194ce001abSDave Airlie 		vert_timing = vert_timing_NTSC;
7204ce001abSDave Airlie 	} else {
7214ce001abSDave Airlie 		hor_timing = hor_timing_PAL;
7224ce001abSDave Airlie 		vert_timing = vert_timing_PAL;
7234ce001abSDave Airlie 		tv_ftotal = PAL_TV_VFTOTAL;
7244ce001abSDave Airlie 	}
7254ce001abSDave Airlie 
7264ce001abSDave Airlie 	for (i = 0; i < MAX_H_CODE_TIMING_LEN; i++) {
727*819362e4SRan Sun 		tv_dac->tv.h_code_timing[i] = hor_timing[i];
728*819362e4SRan Sun 		if (tv_dac->tv.h_code_timing[i] == 0)
7294ce001abSDave Airlie 			break;
7304ce001abSDave Airlie 	}
7314ce001abSDave Airlie 
7324ce001abSDave Airlie 	for (i = 0; i < MAX_V_CODE_TIMING_LEN; i++) {
733*819362e4SRan Sun 		tv_dac->tv.v_code_timing[i] = vert_timing[i];
734*819362e4SRan Sun 		if (tv_dac->tv.v_code_timing[i] == 0)
7354ce001abSDave Airlie 			break;
7364ce001abSDave Airlie 	}
7374ce001abSDave Airlie 
7384ce001abSDave Airlie 	radeon_legacy_tv_init_restarts(encoder);
7394ce001abSDave Airlie 
7404ce001abSDave Airlie 	/* play with DAC_CNTL */
7414ce001abSDave Airlie 	/* play with GPIOPAD_A */
7424ce001abSDave Airlie 	/* DISP_OUTPUT_CNTL */
7434ce001abSDave Airlie 	/* use reference freq */
7444ce001abSDave Airlie 
7454ce001abSDave Airlie 	/* program the TV registers */
7464ce001abSDave Airlie 	WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST |
7474ce001abSDave Airlie 				       RADEON_CRT_ASYNC_RST | RADEON_TV_FIFO_ASYNC_RST));
7484ce001abSDave Airlie 
7494ce001abSDave Airlie 	tmp = RREG32(RADEON_TV_DAC_CNTL);
7504ce001abSDave Airlie 	tmp &= ~RADEON_TV_DAC_NBLANK;
7514ce001abSDave Airlie 	tmp |= RADEON_TV_DAC_BGSLEEP |
7524ce001abSDave Airlie 		RADEON_TV_DAC_RDACPD |
7534ce001abSDave Airlie 		RADEON_TV_DAC_GDACPD |
7544ce001abSDave Airlie 		RADEON_TV_DAC_BDACPD;
7554ce001abSDave Airlie 	WREG32(RADEON_TV_DAC_CNTL, tmp);
7564ce001abSDave Airlie 
7574ce001abSDave Airlie 	/* TV PLL */
7584ce001abSDave Airlie 	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVCLK_SRC_SEL_TVPLL);
7594ce001abSDave Airlie 	WREG32_PLL(RADEON_TV_PLL_CNTL, tv_pll_cntl);
7604ce001abSDave Airlie 	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, RADEON_TVPLL_RESET, ~RADEON_TVPLL_RESET);
7614ce001abSDave Airlie 
7624ce001abSDave Airlie 	radeon_wait_pll_lock(encoder, 200, 800, 135);
7634ce001abSDave Airlie 
7644ce001abSDave Airlie 	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_RESET);
7654ce001abSDave Airlie 
7664ce001abSDave Airlie 	radeon_wait_pll_lock(encoder, 300, 160, 27);
7674ce001abSDave Airlie 	radeon_wait_pll_lock(encoder, 200, 800, 135);
7684ce001abSDave Airlie 
7694ce001abSDave Airlie 	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~0xf);
7704ce001abSDave Airlie 	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, RADEON_TVCLK_SRC_SEL_TVPLL, ~RADEON_TVCLK_SRC_SEL_TVPLL);
7714ce001abSDave Airlie 
7724ce001abSDave Airlie 	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, (1 << RADEON_TVPDC_SHIFT), ~RADEON_TVPDC_MASK);
7734ce001abSDave Airlie 	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_SLEEP);
7744ce001abSDave Airlie 
7754ce001abSDave Airlie 	/* TV HV */
7764ce001abSDave Airlie 	WREG32(RADEON_TV_RGB_CNTL, tv_rgb_cntl);
7774ce001abSDave Airlie 	WREG32(RADEON_TV_HTOTAL, const_ptr->hor_total - 1);
7784ce001abSDave Airlie 	WREG32(RADEON_TV_HDISP, const_ptr->hor_resolution - 1);
7794ce001abSDave Airlie 	WREG32(RADEON_TV_HSTART, const_ptr->hor_start);
7804ce001abSDave Airlie 
7814ce001abSDave Airlie 	WREG32(RADEON_TV_VTOTAL, const_ptr->ver_total - 1);
7824ce001abSDave Airlie 	WREG32(RADEON_TV_VDISP, const_ptr->ver_resolution - 1);
7834ce001abSDave Airlie 	WREG32(RADEON_TV_FTOTAL, tv_ftotal);
7844ce001abSDave Airlie 	WREG32(RADEON_TV_VSCALER_CNTL1, tv_vscaler_cntl1);
7854ce001abSDave Airlie 	WREG32(RADEON_TV_VSCALER_CNTL2, tv_vscaler_cntl2);
7864ce001abSDave Airlie 
7874ce001abSDave Airlie 	WREG32(RADEON_TV_Y_FALL_CNTL, tv_y_fall_cntl);
7884ce001abSDave Airlie 	WREG32(RADEON_TV_Y_RISE_CNTL, tv_y_rise_cntl);
7894ce001abSDave Airlie 	WREG32(RADEON_TV_Y_SAW_TOOTH_CNTL, tv_y_saw_tooth_cntl);
7904ce001abSDave Airlie 
7914ce001abSDave Airlie 	WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST |
7924ce001abSDave Airlie 				       RADEON_CRT_ASYNC_RST));
7934ce001abSDave Airlie 
7944ce001abSDave Airlie 	/* TV restarts */
7954ce001abSDave Airlie 	radeon_legacy_write_tv_restarts(radeon_encoder);
7964ce001abSDave Airlie 
7974ce001abSDave Airlie 	/* tv timings */
7984ce001abSDave Airlie 	radeon_restore_tv_timing_tables(radeon_encoder);
7994ce001abSDave Airlie 
8004ce001abSDave Airlie 	WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST));
8014ce001abSDave Airlie 
8024ce001abSDave Airlie 	/* tv std */
8034ce001abSDave Airlie 	WREG32(RADEON_TV_SYNC_CNTL, (RADEON_SYNC_PUB | RADEON_TV_SYNC_IO_DRIVE));
8044ce001abSDave Airlie 	WREG32(RADEON_TV_TIMING_CNTL, tv_dac->tv.timing_cntl);
8054ce001abSDave Airlie 	WREG32(RADEON_TV_MODULATOR_CNTL1, tv_modulator_cntl1);
8064ce001abSDave Airlie 	WREG32(RADEON_TV_MODULATOR_CNTL2, tv_modulator_cntl2);
8074ce001abSDave Airlie 	WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, (RADEON_Y_RED_EN |
8084ce001abSDave Airlie 					    RADEON_C_GRN_EN |
8094ce001abSDave Airlie 					    RADEON_CMP_BLU_EN |
8104ce001abSDave Airlie 					    RADEON_DAC_DITHER_EN));
8114ce001abSDave Airlie 
8124ce001abSDave Airlie 	WREG32(RADEON_TV_CRC_CNTL, 0);
8134ce001abSDave Airlie 
8144ce001abSDave Airlie 	WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
8154ce001abSDave Airlie 
8164ce001abSDave Airlie 	WREG32(RADEON_TV_GAIN_LIMIT_SETTINGS, ((0x17f << RADEON_UV_GAIN_LIMIT_SHIFT) |
8174ce001abSDave Airlie 					       (0x5ff << RADEON_Y_GAIN_LIMIT_SHIFT)));
8184ce001abSDave Airlie 	WREG32(RADEON_TV_LINEAR_GAIN_SETTINGS, ((0x100 << RADEON_UV_GAIN_SHIFT) |
8194ce001abSDave Airlie 						(0x100 << RADEON_Y_GAIN_SHIFT)));
8204ce001abSDave Airlie 
8214ce001abSDave Airlie 	WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
8224ce001abSDave Airlie 
8234ce001abSDave Airlie }
8244ce001abSDave Airlie 
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)8254ce001abSDave Airlie void radeon_legacy_tv_adjust_crtc_reg(struct drm_encoder *encoder,
8264ce001abSDave Airlie 				      uint32_t *h_total_disp, uint32_t *h_sync_strt_wid,
8274ce001abSDave Airlie 				      uint32_t *v_total_disp, uint32_t *v_sync_strt_wid)
8284ce001abSDave Airlie {
8294ce001abSDave Airlie 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
8304ce001abSDave Airlie 	const struct radeon_tv_mode_constants *const_ptr;
8314ce001abSDave Airlie 	uint32_t tmp;
8324ce001abSDave Airlie 
8334ce001abSDave Airlie 	const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
8344ce001abSDave Airlie 	if (!const_ptr)
8354ce001abSDave Airlie 		return;
8364ce001abSDave Airlie 
8374ce001abSDave Airlie 	*h_total_disp = (((const_ptr->hor_resolution / 8) - 1) << RADEON_CRTC_H_DISP_SHIFT) |
8384ce001abSDave Airlie 		(((const_ptr->hor_total / 8) - 1) << RADEON_CRTC_H_TOTAL_SHIFT);
8394ce001abSDave Airlie 
8404ce001abSDave Airlie 	tmp = *h_sync_strt_wid;
8414ce001abSDave Airlie 	tmp &= ~(RADEON_CRTC_H_SYNC_STRT_PIX | RADEON_CRTC_H_SYNC_STRT_CHAR);
8424ce001abSDave Airlie 	tmp |= (((const_ptr->hor_syncstart / 8) - 1) << RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) |
8434ce001abSDave Airlie 		(const_ptr->hor_syncstart & 7);
8444ce001abSDave Airlie 	*h_sync_strt_wid = tmp;
8454ce001abSDave Airlie 
8464ce001abSDave Airlie 	*v_total_disp = ((const_ptr->ver_resolution - 1) << RADEON_CRTC_V_DISP_SHIFT) |
8474ce001abSDave Airlie 		((const_ptr->ver_total - 1) << RADEON_CRTC_V_TOTAL_SHIFT);
8484ce001abSDave Airlie 
8494ce001abSDave Airlie 	tmp = *v_sync_strt_wid;
8504ce001abSDave Airlie 	tmp &= ~RADEON_CRTC_V_SYNC_STRT;
8514ce001abSDave Airlie 	tmp |= ((const_ptr->ver_syncstart - 1) << RADEON_CRTC_V_SYNC_STRT_SHIFT);
8524ce001abSDave Airlie 	*v_sync_strt_wid = tmp;
8534ce001abSDave Airlie }
8544ce001abSDave Airlie 
get_post_div(int value)855ce580fabSAndi Kleen static int get_post_div(int value)
8564ce001abSDave Airlie {
8574ce001abSDave Airlie 	int post_div;
8584ce001abSDave Airlie 	switch (value) {
8594ce001abSDave Airlie 	case 1: post_div = 0; break;
8604ce001abSDave Airlie 	case 2: post_div = 1; break;
8614ce001abSDave Airlie 	case 3: post_div = 4; break;
8624ce001abSDave Airlie 	case 4: post_div = 2; break;
8634ce001abSDave Airlie 	case 6: post_div = 6; break;
8644ce001abSDave Airlie 	case 8: post_div = 3; break;
8654ce001abSDave Airlie 	case 12: post_div = 7; break;
8664ce001abSDave Airlie 	case 16:
8674ce001abSDave Airlie 	default: post_div = 5; break;
8684ce001abSDave Airlie 	}
8694ce001abSDave Airlie 	return post_div;
8704ce001abSDave Airlie }
8714ce001abSDave Airlie 
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)8724ce001abSDave Airlie void radeon_legacy_tv_adjust_pll1(struct drm_encoder *encoder,
8734ce001abSDave Airlie 				  uint32_t *htotal_cntl, uint32_t *ppll_ref_div,
8744ce001abSDave Airlie 				  uint32_t *ppll_div_3, uint32_t *pixclks_cntl)
8754ce001abSDave Airlie {
8764ce001abSDave Airlie 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
8774ce001abSDave Airlie 	const struct radeon_tv_mode_constants *const_ptr;
8784ce001abSDave Airlie 
8794ce001abSDave Airlie 	const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
8804ce001abSDave Airlie 	if (!const_ptr)
8814ce001abSDave Airlie 		return;
8824ce001abSDave Airlie 
8834ce001abSDave Airlie 	*htotal_cntl = (const_ptr->hor_total & 0x7) | RADEON_HTOT_CNTL_VGA_EN;
8844ce001abSDave Airlie 
8854ce001abSDave Airlie 	*ppll_ref_div = const_ptr->crtcPLL_M;
8864ce001abSDave Airlie 
8874ce001abSDave Airlie 	*ppll_div_3 = (const_ptr->crtcPLL_N & 0x7ff) | (get_post_div(const_ptr->crtcPLL_post_div) << 16);
8884ce001abSDave Airlie 	*pixclks_cntl &= ~(RADEON_PIX2CLK_SRC_SEL_MASK | RADEON_PIXCLK_TV_SRC_SEL);
8894ce001abSDave Airlie 	*pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK;
8904ce001abSDave Airlie }
8914ce001abSDave Airlie 
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)8924ce001abSDave Airlie void radeon_legacy_tv_adjust_pll2(struct drm_encoder *encoder,
8934ce001abSDave Airlie 				  uint32_t *htotal2_cntl, uint32_t *p2pll_ref_div,
8944ce001abSDave Airlie 				  uint32_t *p2pll_div_0, uint32_t *pixclks_cntl)
8954ce001abSDave Airlie {
8964ce001abSDave Airlie 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
8974ce001abSDave Airlie 	const struct radeon_tv_mode_constants *const_ptr;
8984ce001abSDave Airlie 
8994ce001abSDave Airlie 	const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
9004ce001abSDave Airlie 	if (!const_ptr)
9014ce001abSDave Airlie 		return;
9024ce001abSDave Airlie 
9034ce001abSDave Airlie 	*htotal2_cntl = (const_ptr->hor_total & 0x7);
9044ce001abSDave Airlie 
9054ce001abSDave Airlie 	*p2pll_ref_div = const_ptr->crtcPLL_M;
9064ce001abSDave Airlie 
9074ce001abSDave Airlie 	*p2pll_div_0 = (const_ptr->crtcPLL_N & 0x7ff) | (get_post_div(const_ptr->crtcPLL_post_div) << 16);
9084ce001abSDave Airlie 	*pixclks_cntl &= ~RADEON_PIX2CLK_SRC_SEL_MASK;
9094ce001abSDave Airlie 	*pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK | RADEON_PIXCLK_TV_SRC_SEL;
9104ce001abSDave Airlie }
9114ce001abSDave Airlie 
912