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