1254885Sdumbbell#include <sys/cdefs.h> 2254885Sdumbbell__FBSDID("$FreeBSD$"); 3254885Sdumbbell 4254885Sdumbbell#include <dev/drm2/drmP.h> 5254885Sdumbbell#include <dev/drm2/drm_crtc_helper.h> 6254885Sdumbbell#include "radeon.h" 7254885Sdumbbell 8254885Sdumbbell/* 9254885Sdumbbell * Integrated TV out support based on the GATOS code by 10254885Sdumbbell * Federico Ulivi <fulivi@lycos.com> 11254885Sdumbbell */ 12254885Sdumbbell 13254885Sdumbbell 14254885Sdumbbell/* 15254885Sdumbbell * Limits of h/v positions (hPos & vPos) 16254885Sdumbbell */ 17254885Sdumbbell#define MAX_H_POSITION 5 /* Range: [-5..5], negative is on the left, 0 is default, positive is on the right */ 18254885Sdumbbell#define MAX_V_POSITION 5 /* Range: [-5..5], negative is up, 0 is default, positive is down */ 19254885Sdumbbell 20254885Sdumbbell/* 21254885Sdumbbell * Unit for hPos (in TV clock periods) 22254885Sdumbbell */ 23254885Sdumbbell#define H_POS_UNIT 10 24254885Sdumbbell 25254885Sdumbbell/* 26254885Sdumbbell * Indexes in h. code timing table for horizontal line position adjustment 27254885Sdumbbell */ 28254885Sdumbbell#define H_TABLE_POS1 6 29254885Sdumbbell#define H_TABLE_POS2 8 30254885Sdumbbell 31254885Sdumbbell/* 32254885Sdumbbell * Limits of hor. size (hSize) 33254885Sdumbbell */ 34254885Sdumbbell#define MAX_H_SIZE 5 /* Range: [-5..5], negative is smaller, positive is larger */ 35254885Sdumbbell 36254885Sdumbbell/* tv standard constants */ 37254885Sdumbbell#define NTSC_TV_CLOCK_T 233 38254885Sdumbbell#define NTSC_TV_VFTOTAL 1 39254885Sdumbbell#define NTSC_TV_LINES_PER_FRAME 525 40254885Sdumbbell#define NTSC_TV_ZERO_H_SIZE 479166 41254885Sdumbbell#define NTSC_TV_H_SIZE_UNIT 9478 42254885Sdumbbell 43254885Sdumbbell#define PAL_TV_CLOCK_T 188 44254885Sdumbbell#define PAL_TV_VFTOTAL 3 45254885Sdumbbell#define PAL_TV_LINES_PER_FRAME 625 46254885Sdumbbell#define PAL_TV_ZERO_H_SIZE 473200 47254885Sdumbbell#define PAL_TV_H_SIZE_UNIT 9360 48254885Sdumbbell 49254885Sdumbbell/* tv pll setting for 27 mhz ref clk */ 50254885Sdumbbell#define NTSC_TV_PLL_M_27 22 51254885Sdumbbell#define NTSC_TV_PLL_N_27 175 52254885Sdumbbell#define NTSC_TV_PLL_P_27 5 53254885Sdumbbell 54254885Sdumbbell#define PAL_TV_PLL_M_27 113 55254885Sdumbbell#define PAL_TV_PLL_N_27 668 56254885Sdumbbell#define PAL_TV_PLL_P_27 3 57254885Sdumbbell 58254885Sdumbbell/* tv pll setting for 14 mhz ref clk */ 59254885Sdumbbell#define NTSC_TV_PLL_M_14 33 60254885Sdumbbell#define NTSC_TV_PLL_N_14 693 61254885Sdumbbell#define NTSC_TV_PLL_P_14 7 62254885Sdumbbell 63254885Sdumbbell#define PAL_TV_PLL_M_14 19 64254885Sdumbbell#define PAL_TV_PLL_N_14 353 65254885Sdumbbell#define PAL_TV_PLL_P_14 5 66254885Sdumbbell 67254885Sdumbbell#define VERT_LEAD_IN_LINES 2 68254885Sdumbbell#define FRAC_BITS 0xe 69254885Sdumbbell#define FRAC_MASK 0x3fff 70254885Sdumbbell 71254885Sdumbbellstruct radeon_tv_mode_constants { 72254885Sdumbbell uint16_t hor_resolution; 73254885Sdumbbell uint16_t ver_resolution; 74254885Sdumbbell enum radeon_tv_std standard; 75254885Sdumbbell uint16_t hor_total; 76254885Sdumbbell uint16_t ver_total; 77254885Sdumbbell uint16_t hor_start; 78254885Sdumbbell uint16_t hor_syncstart; 79254885Sdumbbell uint16_t ver_syncstart; 80254885Sdumbbell unsigned def_restart; 81254885Sdumbbell uint16_t crtcPLL_N; 82254885Sdumbbell uint8_t crtcPLL_M; 83254885Sdumbbell uint8_t crtcPLL_post_div; 84254885Sdumbbell unsigned pix_to_tv; 85254885Sdumbbell}; 86254885Sdumbbell 87254885Sdumbbellstatic const uint16_t hor_timing_NTSC[MAX_H_CODE_TIMING_LEN] = { 88254885Sdumbbell 0x0007, 89254885Sdumbbell 0x003f, 90254885Sdumbbell 0x0263, 91254885Sdumbbell 0x0a24, 92254885Sdumbbell 0x2a6b, 93254885Sdumbbell 0x0a36, 94254885Sdumbbell 0x126d, /* H_TABLE_POS1 */ 95254885Sdumbbell 0x1bfe, 96254885Sdumbbell 0x1a8f, /* H_TABLE_POS2 */ 97254885Sdumbbell 0x1ec7, 98254885Sdumbbell 0x3863, 99254885Sdumbbell 0x1bfe, 100254885Sdumbbell 0x1bfe, 101254885Sdumbbell 0x1a2a, 102254885Sdumbbell 0x1e95, 103254885Sdumbbell 0x0e31, 104254885Sdumbbell 0x201b, 105254885Sdumbbell 0 106254885Sdumbbell}; 107254885Sdumbbell 108254885Sdumbbellstatic const uint16_t vert_timing_NTSC[MAX_V_CODE_TIMING_LEN] = { 109254885Sdumbbell 0x2001, 110254885Sdumbbell 0x200d, 111254885Sdumbbell 0x1006, 112254885Sdumbbell 0x0c06, 113254885Sdumbbell 0x1006, 114254885Sdumbbell 0x1818, 115254885Sdumbbell 0x21e3, 116254885Sdumbbell 0x1006, 117254885Sdumbbell 0x0c06, 118254885Sdumbbell 0x1006, 119254885Sdumbbell 0x1817, 120254885Sdumbbell 0x21d4, 121254885Sdumbbell 0x0002, 122254885Sdumbbell 0 123254885Sdumbbell}; 124254885Sdumbbell 125254885Sdumbbellstatic const uint16_t hor_timing_PAL[MAX_H_CODE_TIMING_LEN] = { 126254885Sdumbbell 0x0007, 127254885Sdumbbell 0x0058, 128254885Sdumbbell 0x027c, 129254885Sdumbbell 0x0a31, 130254885Sdumbbell 0x2a77, 131254885Sdumbbell 0x0a95, 132254885Sdumbbell 0x124f, /* H_TABLE_POS1 */ 133254885Sdumbbell 0x1bfe, 134254885Sdumbbell 0x1b22, /* H_TABLE_POS2 */ 135254885Sdumbbell 0x1ef9, 136254885Sdumbbell 0x387c, 137254885Sdumbbell 0x1bfe, 138254885Sdumbbell 0x1bfe, 139254885Sdumbbell 0x1b31, 140254885Sdumbbell 0x1eb5, 141254885Sdumbbell 0x0e43, 142254885Sdumbbell 0x201b, 143254885Sdumbbell 0 144254885Sdumbbell}; 145254885Sdumbbell 146254885Sdumbbellstatic const uint16_t vert_timing_PAL[MAX_V_CODE_TIMING_LEN] = { 147254885Sdumbbell 0x2001, 148254885Sdumbbell 0x200c, 149254885Sdumbbell 0x1005, 150254885Sdumbbell 0x0c05, 151254885Sdumbbell 0x1005, 152254885Sdumbbell 0x1401, 153254885Sdumbbell 0x1821, 154254885Sdumbbell 0x2240, 155254885Sdumbbell 0x1005, 156254885Sdumbbell 0x0c05, 157254885Sdumbbell 0x1005, 158254885Sdumbbell 0x1401, 159254885Sdumbbell 0x1822, 160254885Sdumbbell 0x2230, 161254885Sdumbbell 0x0002, 162254885Sdumbbell 0 163254885Sdumbbell}; 164254885Sdumbbell 165254885Sdumbbell/********************************************************************** 166254885Sdumbbell * 167254885Sdumbbell * availableModes 168254885Sdumbbell * 169254885Sdumbbell * Table of all allowed modes for tv output 170254885Sdumbbell * 171254885Sdumbbell **********************************************************************/ 172254885Sdumbbellstatic const struct radeon_tv_mode_constants available_tv_modes[] = { 173254885Sdumbbell { /* NTSC timing for 27 Mhz ref clk */ 174254885Sdumbbell 800, /* horResolution */ 175254885Sdumbbell 600, /* verResolution */ 176254885Sdumbbell TV_STD_NTSC, /* standard */ 177254885Sdumbbell 990, /* horTotal */ 178254885Sdumbbell 740, /* verTotal */ 179254885Sdumbbell 813, /* horStart */ 180254885Sdumbbell 824, /* horSyncStart */ 181254885Sdumbbell 632, /* verSyncStart */ 182254885Sdumbbell 625592, /* defRestart */ 183254885Sdumbbell 592, /* crtcPLL_N */ 184254885Sdumbbell 91, /* crtcPLL_M */ 185254885Sdumbbell 4, /* crtcPLL_postDiv */ 186254885Sdumbbell 1022, /* pixToTV */ 187254885Sdumbbell }, 188254885Sdumbbell { /* PAL timing for 27 Mhz ref clk */ 189254885Sdumbbell 800, /* horResolution */ 190254885Sdumbbell 600, /* verResolution */ 191254885Sdumbbell TV_STD_PAL, /* standard */ 192254885Sdumbbell 1144, /* horTotal */ 193254885Sdumbbell 706, /* verTotal */ 194254885Sdumbbell 812, /* horStart */ 195254885Sdumbbell 824, /* horSyncStart */ 196254885Sdumbbell 669, /* verSyncStart */ 197254885Sdumbbell 696700, /* defRestart */ 198254885Sdumbbell 1382, /* crtcPLL_N */ 199254885Sdumbbell 231, /* crtcPLL_M */ 200254885Sdumbbell 4, /* crtcPLL_postDiv */ 201254885Sdumbbell 759, /* pixToTV */ 202254885Sdumbbell }, 203254885Sdumbbell { /* NTSC timing for 14 Mhz ref clk */ 204254885Sdumbbell 800, /* horResolution */ 205254885Sdumbbell 600, /* verResolution */ 206254885Sdumbbell TV_STD_NTSC, /* standard */ 207254885Sdumbbell 1018, /* horTotal */ 208254885Sdumbbell 727, /* verTotal */ 209254885Sdumbbell 813, /* horStart */ 210254885Sdumbbell 840, /* horSyncStart */ 211254885Sdumbbell 633, /* verSyncStart */ 212254885Sdumbbell 630627, /* defRestart */ 213254885Sdumbbell 347, /* crtcPLL_N */ 214254885Sdumbbell 14, /* crtcPLL_M */ 215254885Sdumbbell 8, /* crtcPLL_postDiv */ 216254885Sdumbbell 1022, /* pixToTV */ 217254885Sdumbbell }, 218254885Sdumbbell { /* PAL timing for 14 Mhz ref clk */ 219254885Sdumbbell 800, /* horResolution */ 220254885Sdumbbell 600, /* verResolution */ 221254885Sdumbbell TV_STD_PAL, /* standard */ 222254885Sdumbbell 1131, /* horTotal */ 223254885Sdumbbell 742, /* verTotal */ 224254885Sdumbbell 813, /* horStart */ 225254885Sdumbbell 840, /* horSyncStart */ 226254885Sdumbbell 633, /* verSyncStart */ 227254885Sdumbbell 708369, /* defRestart */ 228254885Sdumbbell 211, /* crtcPLL_N */ 229254885Sdumbbell 9, /* crtcPLL_M */ 230254885Sdumbbell 8, /* crtcPLL_postDiv */ 231254885Sdumbbell 759, /* pixToTV */ 232254885Sdumbbell }, 233254885Sdumbbell}; 234254885Sdumbbell 235254885Sdumbbell#define N_AVAILABLE_MODES DRM_ARRAY_SIZE(available_tv_modes) 236254885Sdumbbell 237254885Sdumbbellstatic const struct radeon_tv_mode_constants *radeon_legacy_tv_get_std_mode(struct radeon_encoder *radeon_encoder, 238254885Sdumbbell uint16_t *pll_ref_freq) 239254885Sdumbbell{ 240254885Sdumbbell struct drm_device *dev = radeon_encoder->base.dev; 241254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 242254885Sdumbbell struct radeon_crtc *radeon_crtc; 243254885Sdumbbell struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; 244254885Sdumbbell const struct radeon_tv_mode_constants *const_ptr; 245254885Sdumbbell struct radeon_pll *pll; 246254885Sdumbbell 247254885Sdumbbell radeon_crtc = to_radeon_crtc(radeon_encoder->base.crtc); 248254885Sdumbbell if (radeon_crtc->crtc_id == 1) 249254885Sdumbbell pll = &rdev->clock.p2pll; 250254885Sdumbbell else 251254885Sdumbbell pll = &rdev->clock.p1pll; 252254885Sdumbbell 253254885Sdumbbell if (pll_ref_freq) 254254885Sdumbbell *pll_ref_freq = pll->reference_freq; 255254885Sdumbbell 256254885Sdumbbell if (tv_dac->tv_std == TV_STD_NTSC || 257254885Sdumbbell tv_dac->tv_std == TV_STD_NTSC_J || 258254885Sdumbbell tv_dac->tv_std == TV_STD_PAL_M) { 259254885Sdumbbell if (pll->reference_freq == 2700) 260254885Sdumbbell const_ptr = &available_tv_modes[0]; 261254885Sdumbbell else 262254885Sdumbbell const_ptr = &available_tv_modes[2]; 263254885Sdumbbell } else { 264254885Sdumbbell if (pll->reference_freq == 2700) 265254885Sdumbbell const_ptr = &available_tv_modes[1]; 266254885Sdumbbell else 267254885Sdumbbell const_ptr = &available_tv_modes[3]; 268254885Sdumbbell } 269254885Sdumbbell return const_ptr; 270254885Sdumbbell} 271254885Sdumbbell 272254885Sdumbbellstatic long YCOEF_value[5] = { 2, 2, 0, 4, 0 }; 273254885Sdumbbellstatic long YCOEF_EN_value[5] = { 1, 1, 0, 1, 0 }; 274254885Sdumbbellstatic long SLOPE_value[5] = { 1, 2, 2, 4, 8 }; 275254885Sdumbbellstatic long SLOPE_limit[5] = { 6, 5, 4, 3, 2 }; 276254885Sdumbbell 277254885Sdumbbellstatic void radeon_wait_pll_lock(struct drm_encoder *encoder, unsigned n_tests, 278254885Sdumbbell unsigned n_wait_loops, unsigned cnt_threshold) 279254885Sdumbbell{ 280254885Sdumbbell struct drm_device *dev = encoder->dev; 281254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 282254885Sdumbbell uint32_t save_pll_test; 283254885Sdumbbell unsigned int i, j; 284254885Sdumbbell 285254885Sdumbbell WREG32(RADEON_TEST_DEBUG_MUX, (RREG32(RADEON_TEST_DEBUG_MUX) & 0xffff60ff) | 0x100); 286254885Sdumbbell save_pll_test = RREG32_PLL(RADEON_PLL_TEST_CNTL); 287254885Sdumbbell WREG32_PLL(RADEON_PLL_TEST_CNTL, save_pll_test & ~RADEON_PLL_MASK_READ_B); 288254885Sdumbbell 289254885Sdumbbell WREG8(RADEON_CLOCK_CNTL_INDEX, RADEON_PLL_TEST_CNTL); 290254885Sdumbbell for (i = 0; i < n_tests; i++) { 291254885Sdumbbell WREG8(RADEON_CLOCK_CNTL_DATA + 3, 0); 292254885Sdumbbell for (j = 0; j < n_wait_loops; j++) 293254885Sdumbbell if (RREG8(RADEON_CLOCK_CNTL_DATA + 3) >= cnt_threshold) 294254885Sdumbbell break; 295254885Sdumbbell } 296254885Sdumbbell WREG32_PLL(RADEON_PLL_TEST_CNTL, save_pll_test); 297254885Sdumbbell WREG32(RADEON_TEST_DEBUG_MUX, RREG32(RADEON_TEST_DEBUG_MUX) & 0xffffe0ff); 298254885Sdumbbell} 299254885Sdumbbell 300254885Sdumbbell 301254885Sdumbbellstatic void radeon_legacy_tv_write_fifo(struct radeon_encoder *radeon_encoder, 302254885Sdumbbell uint16_t addr, uint32_t value) 303254885Sdumbbell{ 304254885Sdumbbell struct drm_device *dev = radeon_encoder->base.dev; 305254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 306254885Sdumbbell uint32_t tmp; 307254885Sdumbbell int i = 0; 308254885Sdumbbell 309254885Sdumbbell WREG32(RADEON_TV_HOST_WRITE_DATA, value); 310254885Sdumbbell 311254885Sdumbbell WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr); 312254885Sdumbbell WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_WT); 313254885Sdumbbell 314254885Sdumbbell do { 315254885Sdumbbell tmp = RREG32(RADEON_TV_HOST_RD_WT_CNTL); 316254885Sdumbbell if ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0) 317254885Sdumbbell break; 318254885Sdumbbell i++; 319254885Sdumbbell } while (i < 10000); 320254885Sdumbbell WREG32(RADEON_TV_HOST_RD_WT_CNTL, 0); 321254885Sdumbbell} 322254885Sdumbbell 323254885Sdumbbell#if 0 /* included for completeness */ 324254885Sdumbbellstatic uint32_t radeon_legacy_tv_read_fifo(struct radeon_encoder *radeon_encoder, uint16_t addr) 325254885Sdumbbell{ 326254885Sdumbbell struct drm_device *dev = radeon_encoder->base.dev; 327254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 328254885Sdumbbell uint32_t tmp; 329254885Sdumbbell int i = 0; 330254885Sdumbbell 331254885Sdumbbell WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr); 332254885Sdumbbell WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_RD); 333254885Sdumbbell 334254885Sdumbbell do { 335254885Sdumbbell tmp = RREG32(RADEON_TV_HOST_RD_WT_CNTL); 336254885Sdumbbell if ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0) 337254885Sdumbbell break; 338254885Sdumbbell i++; 339254885Sdumbbell } while (i < 10000); 340254885Sdumbbell WREG32(RADEON_TV_HOST_RD_WT_CNTL, 0); 341254885Sdumbbell return RREG32(RADEON_TV_HOST_READ_DATA); 342254885Sdumbbell} 343254885Sdumbbell#endif 344254885Sdumbbell 345254885Sdumbbellstatic uint16_t radeon_get_htiming_tables_addr(uint32_t tv_uv_adr) 346254885Sdumbbell{ 347254885Sdumbbell uint16_t h_table; 348254885Sdumbbell 349254885Sdumbbell switch ((tv_uv_adr & RADEON_HCODE_TABLE_SEL_MASK) >> RADEON_HCODE_TABLE_SEL_SHIFT) { 350254885Sdumbbell case 0: 351254885Sdumbbell h_table = RADEON_TV_MAX_FIFO_ADDR_INTERNAL; 352254885Sdumbbell break; 353254885Sdumbbell case 1: 354254885Sdumbbell h_table = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2; 355254885Sdumbbell break; 356254885Sdumbbell case 2: 357254885Sdumbbell h_table = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2; 358254885Sdumbbell break; 359254885Sdumbbell default: 360254885Sdumbbell h_table = 0; 361254885Sdumbbell break; 362254885Sdumbbell } 363254885Sdumbbell return h_table; 364254885Sdumbbell} 365254885Sdumbbell 366254885Sdumbbellstatic uint16_t radeon_get_vtiming_tables_addr(uint32_t tv_uv_adr) 367254885Sdumbbell{ 368254885Sdumbbell uint16_t v_table; 369254885Sdumbbell 370254885Sdumbbell switch ((tv_uv_adr & RADEON_VCODE_TABLE_SEL_MASK) >> RADEON_VCODE_TABLE_SEL_SHIFT) { 371254885Sdumbbell case 0: 372254885Sdumbbell v_table = ((tv_uv_adr & RADEON_MAX_UV_ADR_MASK) >> RADEON_MAX_UV_ADR_SHIFT) * 2 + 1; 373254885Sdumbbell break; 374254885Sdumbbell case 1: 375254885Sdumbbell v_table = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2 + 1; 376254885Sdumbbell break; 377254885Sdumbbell case 2: 378254885Sdumbbell v_table = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2 + 1; 379254885Sdumbbell break; 380254885Sdumbbell default: 381254885Sdumbbell v_table = 0; 382254885Sdumbbell break; 383254885Sdumbbell } 384254885Sdumbbell return v_table; 385254885Sdumbbell} 386254885Sdumbbell 387254885Sdumbbellstatic void radeon_restore_tv_timing_tables(struct radeon_encoder *radeon_encoder) 388254885Sdumbbell{ 389254885Sdumbbell struct drm_device *dev = radeon_encoder->base.dev; 390254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 391254885Sdumbbell struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; 392254885Sdumbbell uint16_t h_table, v_table; 393254885Sdumbbell uint32_t tmp; 394254885Sdumbbell int i; 395254885Sdumbbell 396254885Sdumbbell WREG32(RADEON_TV_UV_ADR, tv_dac->tv.tv_uv_adr); 397254885Sdumbbell h_table = radeon_get_htiming_tables_addr(tv_dac->tv.tv_uv_adr); 398254885Sdumbbell v_table = radeon_get_vtiming_tables_addr(tv_dac->tv.tv_uv_adr); 399254885Sdumbbell 400254885Sdumbbell for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2, h_table--) { 401254885Sdumbbell tmp = ((uint32_t)tv_dac->tv.h_code_timing[i] << 14) | ((uint32_t)tv_dac->tv.h_code_timing[i+1]); 402254885Sdumbbell radeon_legacy_tv_write_fifo(radeon_encoder, h_table, tmp); 403254885Sdumbbell if (tv_dac->tv.h_code_timing[i] == 0 || tv_dac->tv.h_code_timing[i + 1] == 0) 404254885Sdumbbell break; 405254885Sdumbbell } 406254885Sdumbbell for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2, v_table++) { 407254885Sdumbbell tmp = ((uint32_t)tv_dac->tv.v_code_timing[i+1] << 14) | ((uint32_t)tv_dac->tv.v_code_timing[i]); 408254885Sdumbbell radeon_legacy_tv_write_fifo(radeon_encoder, v_table, tmp); 409254885Sdumbbell if (tv_dac->tv.v_code_timing[i] == 0 || tv_dac->tv.v_code_timing[i + 1] == 0) 410254885Sdumbbell break; 411254885Sdumbbell } 412254885Sdumbbell} 413254885Sdumbbell 414254885Sdumbbellstatic void radeon_legacy_write_tv_restarts(struct radeon_encoder *radeon_encoder) 415254885Sdumbbell{ 416254885Sdumbbell struct drm_device *dev = radeon_encoder->base.dev; 417254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 418254885Sdumbbell struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; 419254885Sdumbbell WREG32(RADEON_TV_FRESTART, tv_dac->tv.frestart); 420254885Sdumbbell WREG32(RADEON_TV_HRESTART, tv_dac->tv.hrestart); 421254885Sdumbbell WREG32(RADEON_TV_VRESTART, tv_dac->tv.vrestart); 422254885Sdumbbell} 423254885Sdumbbell 424254885Sdumbbellstatic bool radeon_legacy_tv_init_restarts(struct drm_encoder *encoder) 425254885Sdumbbell{ 426254885Sdumbbell struct drm_device *dev = encoder->dev; 427254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 428254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 429254885Sdumbbell struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; 430254885Sdumbbell struct radeon_crtc *radeon_crtc; 431254885Sdumbbell int restart; 432254885Sdumbbell unsigned int h_total, v_total, f_total; 433254885Sdumbbell int v_offset, h_offset; 434254885Sdumbbell u16 p1, p2, h_inc; 435254885Sdumbbell bool h_changed; 436254885Sdumbbell const struct radeon_tv_mode_constants *const_ptr; 437254885Sdumbbell struct radeon_pll *pll; 438254885Sdumbbell 439254885Sdumbbell radeon_crtc = to_radeon_crtc(radeon_encoder->base.crtc); 440254885Sdumbbell if (radeon_crtc->crtc_id == 1) 441254885Sdumbbell pll = &rdev->clock.p2pll; 442254885Sdumbbell else 443254885Sdumbbell pll = &rdev->clock.p1pll; 444254885Sdumbbell 445254885Sdumbbell const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL); 446254885Sdumbbell if (!const_ptr) 447254885Sdumbbell return false; 448254885Sdumbbell 449254885Sdumbbell h_total = const_ptr->hor_total; 450254885Sdumbbell v_total = const_ptr->ver_total; 451254885Sdumbbell 452254885Sdumbbell if (tv_dac->tv_std == TV_STD_NTSC || 453254885Sdumbbell tv_dac->tv_std == TV_STD_NTSC_J || 454254885Sdumbbell tv_dac->tv_std == TV_STD_PAL_M || 455254885Sdumbbell tv_dac->tv_std == TV_STD_PAL_60) 456254885Sdumbbell f_total = NTSC_TV_VFTOTAL + 1; 457254885Sdumbbell else 458254885Sdumbbell f_total = PAL_TV_VFTOTAL + 1; 459254885Sdumbbell 460254885Sdumbbell /* adjust positions 1&2 in hor. cod timing table */ 461254885Sdumbbell h_offset = tv_dac->h_pos * H_POS_UNIT; 462254885Sdumbbell 463254885Sdumbbell if (tv_dac->tv_std == TV_STD_NTSC || 464254885Sdumbbell tv_dac->tv_std == TV_STD_NTSC_J || 465254885Sdumbbell tv_dac->tv_std == TV_STD_PAL_M) { 466254885Sdumbbell h_offset -= 50; 467254885Sdumbbell p1 = hor_timing_NTSC[H_TABLE_POS1]; 468254885Sdumbbell p2 = hor_timing_NTSC[H_TABLE_POS2]; 469254885Sdumbbell } else { 470254885Sdumbbell p1 = hor_timing_PAL[H_TABLE_POS1]; 471254885Sdumbbell p2 = hor_timing_PAL[H_TABLE_POS2]; 472254885Sdumbbell } 473254885Sdumbbell 474254885Sdumbbell p1 = (u16)((int)p1 + h_offset); 475254885Sdumbbell p2 = (u16)((int)p2 - h_offset); 476254885Sdumbbell 477254885Sdumbbell h_changed = (p1 != tv_dac->tv.h_code_timing[H_TABLE_POS1] || 478254885Sdumbbell p2 != tv_dac->tv.h_code_timing[H_TABLE_POS2]); 479254885Sdumbbell 480254885Sdumbbell tv_dac->tv.h_code_timing[H_TABLE_POS1] = p1; 481254885Sdumbbell tv_dac->tv.h_code_timing[H_TABLE_POS2] = p2; 482254885Sdumbbell 483254885Sdumbbell /* Convert hOffset from n. of TV clock periods to n. of CRTC clock periods (CRTC pixels) */ 484254885Sdumbbell h_offset = (h_offset * (int)(const_ptr->pix_to_tv)) / 1000; 485254885Sdumbbell 486254885Sdumbbell /* adjust restart */ 487254885Sdumbbell restart = const_ptr->def_restart; 488254885Sdumbbell 489254885Sdumbbell /* 490254885Sdumbbell * convert v_pos TV lines to n. of CRTC pixels 491254885Sdumbbell */ 492254885Sdumbbell if (tv_dac->tv_std == TV_STD_NTSC || 493254885Sdumbbell tv_dac->tv_std == TV_STD_NTSC_J || 494254885Sdumbbell tv_dac->tv_std == TV_STD_PAL_M || 495254885Sdumbbell tv_dac->tv_std == TV_STD_PAL_60) 496254885Sdumbbell v_offset = ((int)(v_total * h_total) * 2 * tv_dac->v_pos) / (int)(NTSC_TV_LINES_PER_FRAME); 497254885Sdumbbell else 498254885Sdumbbell v_offset = ((int)(v_total * h_total) * 2 * tv_dac->v_pos) / (int)(PAL_TV_LINES_PER_FRAME); 499254885Sdumbbell 500254885Sdumbbell restart -= v_offset + h_offset; 501254885Sdumbbell 502254885Sdumbbell DRM_DEBUG_KMS("compute_restarts: def = %u h = %d v = %d, p1 = %04x, p2 = %04x, restart = %d\n", 503254885Sdumbbell const_ptr->def_restart, tv_dac->h_pos, tv_dac->v_pos, p1, p2, restart); 504254885Sdumbbell 505254885Sdumbbell tv_dac->tv.hrestart = restart % h_total; 506254885Sdumbbell restart /= h_total; 507254885Sdumbbell tv_dac->tv.vrestart = restart % v_total; 508254885Sdumbbell restart /= v_total; 509254885Sdumbbell tv_dac->tv.frestart = restart % f_total; 510254885Sdumbbell 511254885Sdumbbell DRM_DEBUG_KMS("compute_restart: F/H/V=%u,%u,%u\n", 512254885Sdumbbell (unsigned)tv_dac->tv.frestart, 513254885Sdumbbell (unsigned)tv_dac->tv.vrestart, 514254885Sdumbbell (unsigned)tv_dac->tv.hrestart); 515254885Sdumbbell 516254885Sdumbbell /* compute h_inc from hsize */ 517254885Sdumbbell if (tv_dac->tv_std == TV_STD_NTSC || 518254885Sdumbbell tv_dac->tv_std == TV_STD_NTSC_J || 519254885Sdumbbell tv_dac->tv_std == TV_STD_PAL_M) 520254885Sdumbbell h_inc = (u16)((int)(const_ptr->hor_resolution * 4096 * NTSC_TV_CLOCK_T) / 521254885Sdumbbell (tv_dac->h_size * (int)(NTSC_TV_H_SIZE_UNIT) + (int)(NTSC_TV_ZERO_H_SIZE))); 522254885Sdumbbell else 523254885Sdumbbell h_inc = (u16)((int)(const_ptr->hor_resolution * 4096 * PAL_TV_CLOCK_T) / 524254885Sdumbbell (tv_dac->h_size * (int)(PAL_TV_H_SIZE_UNIT) + (int)(PAL_TV_ZERO_H_SIZE))); 525254885Sdumbbell 526254885Sdumbbell tv_dac->tv.timing_cntl = (tv_dac->tv.timing_cntl & ~RADEON_H_INC_MASK) | 527254885Sdumbbell ((u32)h_inc << RADEON_H_INC_SHIFT); 528254885Sdumbbell 529254885Sdumbbell DRM_DEBUG_KMS("compute_restart: h_size = %d h_inc = %d\n", tv_dac->h_size, h_inc); 530254885Sdumbbell 531254885Sdumbbell return h_changed; 532254885Sdumbbell} 533254885Sdumbbell 534254885Sdumbbellvoid radeon_legacy_tv_mode_set(struct drm_encoder *encoder, 535254885Sdumbbell struct drm_display_mode *mode, 536254885Sdumbbell struct drm_display_mode *adjusted_mode) 537254885Sdumbbell{ 538254885Sdumbbell struct drm_device *dev = encoder->dev; 539254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 540254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 541254885Sdumbbell struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; 542254885Sdumbbell const struct radeon_tv_mode_constants *const_ptr; 543254885Sdumbbell struct radeon_crtc *radeon_crtc; 544254885Sdumbbell int i; 545254885Sdumbbell uint16_t pll_ref_freq; 546254885Sdumbbell uint32_t vert_space, flicker_removal, tmp; 547254885Sdumbbell uint32_t tv_master_cntl, tv_rgb_cntl, tv_dac_cntl; 548254885Sdumbbell uint32_t tv_modulator_cntl1, tv_modulator_cntl2; 549254885Sdumbbell uint32_t tv_vscaler_cntl1, tv_vscaler_cntl2; 550254885Sdumbbell uint32_t tv_pll_cntl, tv_pll_cntl1, tv_ftotal; 551254885Sdumbbell uint32_t tv_y_fall_cntl, tv_y_rise_cntl, tv_y_saw_tooth_cntl; 552254885Sdumbbell uint32_t m, n, p; 553254885Sdumbbell const uint16_t *hor_timing; 554254885Sdumbbell const uint16_t *vert_timing; 555254885Sdumbbell 556254885Sdumbbell const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, &pll_ref_freq); 557254885Sdumbbell if (!const_ptr) 558254885Sdumbbell return; 559254885Sdumbbell 560254885Sdumbbell radeon_crtc = to_radeon_crtc(encoder->crtc); 561254885Sdumbbell 562254885Sdumbbell tv_master_cntl = (RADEON_VIN_ASYNC_RST | 563254885Sdumbbell RADEON_CRT_FIFO_CE_EN | 564254885Sdumbbell RADEON_TV_FIFO_CE_EN | 565254885Sdumbbell RADEON_TV_ON); 566254885Sdumbbell 567254885Sdumbbell if (!ASIC_IS_R300(rdev)) 568254885Sdumbbell tv_master_cntl |= RADEON_TVCLK_ALWAYS_ONb; 569254885Sdumbbell 570254885Sdumbbell if (tv_dac->tv_std == TV_STD_NTSC || 571254885Sdumbbell tv_dac->tv_std == TV_STD_NTSC_J) 572254885Sdumbbell tv_master_cntl |= RADEON_RESTART_PHASE_FIX; 573254885Sdumbbell 574254885Sdumbbell tv_modulator_cntl1 = (RADEON_SLEW_RATE_LIMIT | 575254885Sdumbbell RADEON_SYNC_TIP_LEVEL | 576254885Sdumbbell RADEON_YFLT_EN | 577254885Sdumbbell RADEON_UVFLT_EN | 578254885Sdumbbell (6 << RADEON_CY_FILT_BLEND_SHIFT)); 579254885Sdumbbell 580254885Sdumbbell if (tv_dac->tv_std == TV_STD_NTSC || 581254885Sdumbbell tv_dac->tv_std == TV_STD_NTSC_J) { 582254885Sdumbbell tv_modulator_cntl1 |= (0x46 << RADEON_SET_UP_LEVEL_SHIFT) | 583254885Sdumbbell (0x3b << RADEON_BLANK_LEVEL_SHIFT); 584254885Sdumbbell tv_modulator_cntl2 = (-111 & RADEON_TV_U_BURST_LEVEL_MASK) | 585254885Sdumbbell ((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT); 586254885Sdumbbell } else if (tv_dac->tv_std == TV_STD_SCART_PAL) { 587254885Sdumbbell tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN; 588254885Sdumbbell tv_modulator_cntl2 = (0 & RADEON_TV_U_BURST_LEVEL_MASK) | 589254885Sdumbbell ((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT); 590254885Sdumbbell } else { 591254885Sdumbbell tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN | 592254885Sdumbbell (0x3b << RADEON_SET_UP_LEVEL_SHIFT) | 593254885Sdumbbell (0x3b << RADEON_BLANK_LEVEL_SHIFT); 594254885Sdumbbell tv_modulator_cntl2 = (-78 & RADEON_TV_U_BURST_LEVEL_MASK) | 595254885Sdumbbell ((62 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT); 596254885Sdumbbell } 597254885Sdumbbell 598254885Sdumbbell 599254885Sdumbbell tv_rgb_cntl = (RADEON_RGB_DITHER_EN 600254885Sdumbbell | RADEON_TVOUT_SCALE_EN 601254885Sdumbbell | (0x0b << RADEON_UVRAM_READ_MARGIN_SHIFT) 602254885Sdumbbell | (0x07 << RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT) 603254885Sdumbbell | RADEON_RGB_ATTEN_SEL(0x3) 604254885Sdumbbell | RADEON_RGB_ATTEN_VAL(0xc)); 605254885Sdumbbell 606254885Sdumbbell if (radeon_crtc->crtc_id == 1) 607254885Sdumbbell tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC2; 608254885Sdumbbell else { 609254885Sdumbbell if (radeon_crtc->rmx_type != RMX_OFF) 610254885Sdumbbell tv_rgb_cntl |= RADEON_RGB_SRC_SEL_RMX; 611254885Sdumbbell else 612254885Sdumbbell tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC1; 613254885Sdumbbell } 614254885Sdumbbell 615254885Sdumbbell if (tv_dac->tv_std == TV_STD_NTSC || 616254885Sdumbbell tv_dac->tv_std == TV_STD_NTSC_J || 617254885Sdumbbell tv_dac->tv_std == TV_STD_PAL_M || 618254885Sdumbbell tv_dac->tv_std == TV_STD_PAL_60) 619254885Sdumbbell vert_space = const_ptr->ver_total * 2 * 10000 / NTSC_TV_LINES_PER_FRAME; 620254885Sdumbbell else 621254885Sdumbbell vert_space = const_ptr->ver_total * 2 * 10000 / PAL_TV_LINES_PER_FRAME; 622254885Sdumbbell 623254885Sdumbbell tmp = RREG32(RADEON_TV_VSCALER_CNTL1); 624254885Sdumbbell tmp &= 0xe3ff0000; 625254885Sdumbbell tmp |= (vert_space * (1 << FRAC_BITS) / 10000); 626254885Sdumbbell tv_vscaler_cntl1 = tmp; 627254885Sdumbbell 628254885Sdumbbell if (pll_ref_freq == 2700) 629254885Sdumbbell tv_vscaler_cntl1 |= RADEON_RESTART_FIELD; 630254885Sdumbbell 631254885Sdumbbell if (const_ptr->hor_resolution == 1024) 632254885Sdumbbell tv_vscaler_cntl1 |= (4 << RADEON_Y_DEL_W_SIG_SHIFT); 633254885Sdumbbell else 634254885Sdumbbell tv_vscaler_cntl1 |= (2 << RADEON_Y_DEL_W_SIG_SHIFT); 635254885Sdumbbell 636254885Sdumbbell /* scale up for int divide */ 637254885Sdumbbell tmp = const_ptr->ver_total * 2 * 1000; 638254885Sdumbbell if (tv_dac->tv_std == TV_STD_NTSC || 639254885Sdumbbell tv_dac->tv_std == TV_STD_NTSC_J || 640254885Sdumbbell tv_dac->tv_std == TV_STD_PAL_M || 641254885Sdumbbell tv_dac->tv_std == TV_STD_PAL_60) { 642254885Sdumbbell tmp /= NTSC_TV_LINES_PER_FRAME; 643254885Sdumbbell } else { 644254885Sdumbbell tmp /= PAL_TV_LINES_PER_FRAME; 645254885Sdumbbell } 646254885Sdumbbell flicker_removal = (tmp + 500) / 1000; 647254885Sdumbbell 648254885Sdumbbell if (flicker_removal < 3) 649254885Sdumbbell flicker_removal = 3; 650254885Sdumbbell for (i = 0; i < DRM_ARRAY_SIZE(SLOPE_limit); ++i) { 651254885Sdumbbell if (flicker_removal == SLOPE_limit[i]) 652254885Sdumbbell break; 653254885Sdumbbell } 654254885Sdumbbell 655254885Sdumbbell tv_y_saw_tooth_cntl = (vert_space * SLOPE_value[i] * (1 << (FRAC_BITS - 1)) + 656254885Sdumbbell 5001) / 10000 / 8 | ((SLOPE_value[i] * 657254885Sdumbbell (1 << (FRAC_BITS - 1)) / 8) << 16); 658254885Sdumbbell tv_y_fall_cntl = 659254885Sdumbbell (YCOEF_EN_value[i] << 17) | ((YCOEF_value[i] * (1 << 8) / 8) << 24) | 660254885Sdumbbell RADEON_Y_FALL_PING_PONG | (272 * SLOPE_value[i] / 8) * (1 << (FRAC_BITS - 1)) / 661254885Sdumbbell 1024; 662254885Sdumbbell tv_y_rise_cntl = RADEON_Y_RISE_PING_PONG| 663254885Sdumbbell (flicker_removal * 1024 - 272) * SLOPE_value[i] / 8 * (1 << (FRAC_BITS - 1)) / 1024; 664254885Sdumbbell 665254885Sdumbbell tv_vscaler_cntl2 = RREG32(RADEON_TV_VSCALER_CNTL2) & 0x00fffff0; 666254885Sdumbbell tv_vscaler_cntl2 |= (0x10 << 24) | 667254885Sdumbbell RADEON_DITHER_MODE | 668254885Sdumbbell RADEON_Y_OUTPUT_DITHER_EN | 669254885Sdumbbell RADEON_UV_OUTPUT_DITHER_EN | 670254885Sdumbbell RADEON_UV_TO_BUF_DITHER_EN; 671254885Sdumbbell 672254885Sdumbbell tmp = (tv_vscaler_cntl1 >> RADEON_UV_INC_SHIFT) & RADEON_UV_INC_MASK; 673254885Sdumbbell tmp = ((16384 * 256 * 10) / tmp + 5) / 10; 674254885Sdumbbell tmp = (tmp << RADEON_UV_OUTPUT_POST_SCALE_SHIFT) | 0x000b0000; 675254885Sdumbbell tv_dac->tv.timing_cntl = tmp; 676254885Sdumbbell 677254885Sdumbbell if (tv_dac->tv_std == TV_STD_NTSC || 678254885Sdumbbell tv_dac->tv_std == TV_STD_NTSC_J || 679254885Sdumbbell tv_dac->tv_std == TV_STD_PAL_M || 680254885Sdumbbell tv_dac->tv_std == TV_STD_PAL_60) 681254885Sdumbbell tv_dac_cntl = tv_dac->ntsc_tvdac_adj; 682254885Sdumbbell else 683254885Sdumbbell tv_dac_cntl = tv_dac->pal_tvdac_adj; 684254885Sdumbbell 685254885Sdumbbell tv_dac_cntl |= RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD; 686254885Sdumbbell 687254885Sdumbbell if (tv_dac->tv_std == TV_STD_NTSC || 688254885Sdumbbell tv_dac->tv_std == TV_STD_NTSC_J) 689254885Sdumbbell tv_dac_cntl |= RADEON_TV_DAC_STD_NTSC; 690254885Sdumbbell else 691254885Sdumbbell tv_dac_cntl |= RADEON_TV_DAC_STD_PAL; 692254885Sdumbbell 693254885Sdumbbell if (tv_dac->tv_std == TV_STD_NTSC || 694254885Sdumbbell tv_dac->tv_std == TV_STD_NTSC_J) { 695254885Sdumbbell if (pll_ref_freq == 2700) { 696254885Sdumbbell m = NTSC_TV_PLL_M_27; 697254885Sdumbbell n = NTSC_TV_PLL_N_27; 698254885Sdumbbell p = NTSC_TV_PLL_P_27; 699254885Sdumbbell } else { 700254885Sdumbbell m = NTSC_TV_PLL_M_14; 701254885Sdumbbell n = NTSC_TV_PLL_N_14; 702254885Sdumbbell p = NTSC_TV_PLL_P_14; 703254885Sdumbbell } 704254885Sdumbbell } else { 705254885Sdumbbell if (pll_ref_freq == 2700) { 706254885Sdumbbell m = PAL_TV_PLL_M_27; 707254885Sdumbbell n = PAL_TV_PLL_N_27; 708254885Sdumbbell p = PAL_TV_PLL_P_27; 709254885Sdumbbell } else { 710254885Sdumbbell m = PAL_TV_PLL_M_14; 711254885Sdumbbell n = PAL_TV_PLL_N_14; 712254885Sdumbbell p = PAL_TV_PLL_P_14; 713254885Sdumbbell } 714254885Sdumbbell } 715254885Sdumbbell 716254885Sdumbbell tv_pll_cntl = (m & RADEON_TV_M0LO_MASK) | 717254885Sdumbbell (((m >> 8) & RADEON_TV_M0HI_MASK) << RADEON_TV_M0HI_SHIFT) | 718254885Sdumbbell ((n & RADEON_TV_N0LO_MASK) << RADEON_TV_N0LO_SHIFT) | 719254885Sdumbbell (((n >> 9) & RADEON_TV_N0HI_MASK) << RADEON_TV_N0HI_SHIFT) | 720254885Sdumbbell ((p & RADEON_TV_P_MASK) << RADEON_TV_P_SHIFT); 721254885Sdumbbell 722254885Sdumbbell tv_pll_cntl1 = (((4 & RADEON_TVPCP_MASK) << RADEON_TVPCP_SHIFT) | 723254885Sdumbbell ((4 & RADEON_TVPVG_MASK) << RADEON_TVPVG_SHIFT) | 724254885Sdumbbell ((1 & RADEON_TVPDC_MASK) << RADEON_TVPDC_SHIFT) | 725254885Sdumbbell RADEON_TVCLK_SRC_SEL_TVPLL | 726254885Sdumbbell RADEON_TVPLL_TEST_DIS); 727254885Sdumbbell 728254885Sdumbbell tv_dac->tv.tv_uv_adr = 0xc8; 729254885Sdumbbell 730254885Sdumbbell if (tv_dac->tv_std == TV_STD_NTSC || 731254885Sdumbbell tv_dac->tv_std == TV_STD_NTSC_J || 732254885Sdumbbell tv_dac->tv_std == TV_STD_PAL_M || 733254885Sdumbbell tv_dac->tv_std == TV_STD_PAL_60) { 734254885Sdumbbell tv_ftotal = NTSC_TV_VFTOTAL; 735254885Sdumbbell hor_timing = hor_timing_NTSC; 736254885Sdumbbell vert_timing = vert_timing_NTSC; 737254885Sdumbbell } else { 738254885Sdumbbell hor_timing = hor_timing_PAL; 739254885Sdumbbell vert_timing = vert_timing_PAL; 740254885Sdumbbell tv_ftotal = PAL_TV_VFTOTAL; 741254885Sdumbbell } 742254885Sdumbbell 743254885Sdumbbell for (i = 0; i < MAX_H_CODE_TIMING_LEN; i++) { 744254885Sdumbbell if ((tv_dac->tv.h_code_timing[i] = hor_timing[i]) == 0) 745254885Sdumbbell break; 746254885Sdumbbell } 747254885Sdumbbell 748254885Sdumbbell for (i = 0; i < MAX_V_CODE_TIMING_LEN; i++) { 749254885Sdumbbell if ((tv_dac->tv.v_code_timing[i] = vert_timing[i]) == 0) 750254885Sdumbbell break; 751254885Sdumbbell } 752254885Sdumbbell 753254885Sdumbbell radeon_legacy_tv_init_restarts(encoder); 754254885Sdumbbell 755254885Sdumbbell /* play with DAC_CNTL */ 756254885Sdumbbell /* play with GPIOPAD_A */ 757254885Sdumbbell /* DISP_OUTPUT_CNTL */ 758254885Sdumbbell /* use reference freq */ 759254885Sdumbbell 760254885Sdumbbell /* program the TV registers */ 761254885Sdumbbell WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST | 762254885Sdumbbell RADEON_CRT_ASYNC_RST | RADEON_TV_FIFO_ASYNC_RST)); 763254885Sdumbbell 764254885Sdumbbell tmp = RREG32(RADEON_TV_DAC_CNTL); 765254885Sdumbbell tmp &= ~RADEON_TV_DAC_NBLANK; 766254885Sdumbbell tmp |= RADEON_TV_DAC_BGSLEEP | 767254885Sdumbbell RADEON_TV_DAC_RDACPD | 768254885Sdumbbell RADEON_TV_DAC_GDACPD | 769254885Sdumbbell RADEON_TV_DAC_BDACPD; 770254885Sdumbbell WREG32(RADEON_TV_DAC_CNTL, tmp); 771254885Sdumbbell 772254885Sdumbbell /* TV PLL */ 773254885Sdumbbell WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVCLK_SRC_SEL_TVPLL); 774254885Sdumbbell WREG32_PLL(RADEON_TV_PLL_CNTL, tv_pll_cntl); 775254885Sdumbbell WREG32_PLL_P(RADEON_TV_PLL_CNTL1, RADEON_TVPLL_RESET, ~RADEON_TVPLL_RESET); 776254885Sdumbbell 777254885Sdumbbell radeon_wait_pll_lock(encoder, 200, 800, 135); 778254885Sdumbbell 779254885Sdumbbell WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_RESET); 780254885Sdumbbell 781254885Sdumbbell radeon_wait_pll_lock(encoder, 300, 160, 27); 782254885Sdumbbell radeon_wait_pll_lock(encoder, 200, 800, 135); 783254885Sdumbbell 784254885Sdumbbell WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~0xf); 785254885Sdumbbell WREG32_PLL_P(RADEON_TV_PLL_CNTL1, RADEON_TVCLK_SRC_SEL_TVPLL, ~RADEON_TVCLK_SRC_SEL_TVPLL); 786254885Sdumbbell 787254885Sdumbbell WREG32_PLL_P(RADEON_TV_PLL_CNTL1, (1 << RADEON_TVPDC_SHIFT), ~RADEON_TVPDC_MASK); 788254885Sdumbbell WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_SLEEP); 789254885Sdumbbell 790254885Sdumbbell /* TV HV */ 791254885Sdumbbell WREG32(RADEON_TV_RGB_CNTL, tv_rgb_cntl); 792254885Sdumbbell WREG32(RADEON_TV_HTOTAL, const_ptr->hor_total - 1); 793254885Sdumbbell WREG32(RADEON_TV_HDISP, const_ptr->hor_resolution - 1); 794254885Sdumbbell WREG32(RADEON_TV_HSTART, const_ptr->hor_start); 795254885Sdumbbell 796254885Sdumbbell WREG32(RADEON_TV_VTOTAL, const_ptr->ver_total - 1); 797254885Sdumbbell WREG32(RADEON_TV_VDISP, const_ptr->ver_resolution - 1); 798254885Sdumbbell WREG32(RADEON_TV_FTOTAL, tv_ftotal); 799254885Sdumbbell WREG32(RADEON_TV_VSCALER_CNTL1, tv_vscaler_cntl1); 800254885Sdumbbell WREG32(RADEON_TV_VSCALER_CNTL2, tv_vscaler_cntl2); 801254885Sdumbbell 802254885Sdumbbell WREG32(RADEON_TV_Y_FALL_CNTL, tv_y_fall_cntl); 803254885Sdumbbell WREG32(RADEON_TV_Y_RISE_CNTL, tv_y_rise_cntl); 804254885Sdumbbell WREG32(RADEON_TV_Y_SAW_TOOTH_CNTL, tv_y_saw_tooth_cntl); 805254885Sdumbbell 806254885Sdumbbell WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST | 807254885Sdumbbell RADEON_CRT_ASYNC_RST)); 808254885Sdumbbell 809254885Sdumbbell /* TV restarts */ 810254885Sdumbbell radeon_legacy_write_tv_restarts(radeon_encoder); 811254885Sdumbbell 812254885Sdumbbell /* tv timings */ 813254885Sdumbbell radeon_restore_tv_timing_tables(radeon_encoder); 814254885Sdumbbell 815254885Sdumbbell WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST)); 816254885Sdumbbell 817254885Sdumbbell /* tv std */ 818254885Sdumbbell WREG32(RADEON_TV_SYNC_CNTL, (RADEON_SYNC_PUB | RADEON_TV_SYNC_IO_DRIVE)); 819254885Sdumbbell WREG32(RADEON_TV_TIMING_CNTL, tv_dac->tv.timing_cntl); 820254885Sdumbbell WREG32(RADEON_TV_MODULATOR_CNTL1, tv_modulator_cntl1); 821254885Sdumbbell WREG32(RADEON_TV_MODULATOR_CNTL2, tv_modulator_cntl2); 822254885Sdumbbell WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, (RADEON_Y_RED_EN | 823254885Sdumbbell RADEON_C_GRN_EN | 824254885Sdumbbell RADEON_CMP_BLU_EN | 825254885Sdumbbell RADEON_DAC_DITHER_EN)); 826254885Sdumbbell 827254885Sdumbbell WREG32(RADEON_TV_CRC_CNTL, 0); 828254885Sdumbbell 829254885Sdumbbell WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); 830254885Sdumbbell 831254885Sdumbbell WREG32(RADEON_TV_GAIN_LIMIT_SETTINGS, ((0x17f << RADEON_UV_GAIN_LIMIT_SHIFT) | 832254885Sdumbbell (0x5ff << RADEON_Y_GAIN_LIMIT_SHIFT))); 833254885Sdumbbell WREG32(RADEON_TV_LINEAR_GAIN_SETTINGS, ((0x100 << RADEON_UV_GAIN_SHIFT) | 834254885Sdumbbell (0x100 << RADEON_Y_GAIN_SHIFT))); 835254885Sdumbbell 836254885Sdumbbell WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); 837254885Sdumbbell 838254885Sdumbbell} 839254885Sdumbbell 840254885Sdumbbellvoid radeon_legacy_tv_adjust_crtc_reg(struct drm_encoder *encoder, 841254885Sdumbbell uint32_t *h_total_disp, uint32_t *h_sync_strt_wid, 842254885Sdumbbell uint32_t *v_total_disp, uint32_t *v_sync_strt_wid) 843254885Sdumbbell{ 844254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 845254885Sdumbbell const struct radeon_tv_mode_constants *const_ptr; 846254885Sdumbbell uint32_t tmp; 847254885Sdumbbell 848254885Sdumbbell const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL); 849254885Sdumbbell if (!const_ptr) 850254885Sdumbbell return; 851254885Sdumbbell 852254885Sdumbbell *h_total_disp = (((const_ptr->hor_resolution / 8) - 1) << RADEON_CRTC_H_DISP_SHIFT) | 853254885Sdumbbell (((const_ptr->hor_total / 8) - 1) << RADEON_CRTC_H_TOTAL_SHIFT); 854254885Sdumbbell 855254885Sdumbbell tmp = *h_sync_strt_wid; 856254885Sdumbbell tmp &= ~(RADEON_CRTC_H_SYNC_STRT_PIX | RADEON_CRTC_H_SYNC_STRT_CHAR); 857254885Sdumbbell tmp |= (((const_ptr->hor_syncstart / 8) - 1) << RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) | 858254885Sdumbbell (const_ptr->hor_syncstart & 7); 859254885Sdumbbell *h_sync_strt_wid = tmp; 860254885Sdumbbell 861254885Sdumbbell *v_total_disp = ((const_ptr->ver_resolution - 1) << RADEON_CRTC_V_DISP_SHIFT) | 862254885Sdumbbell ((const_ptr->ver_total - 1) << RADEON_CRTC_V_TOTAL_SHIFT); 863254885Sdumbbell 864254885Sdumbbell tmp = *v_sync_strt_wid; 865254885Sdumbbell tmp &= ~RADEON_CRTC_V_SYNC_STRT; 866254885Sdumbbell tmp |= ((const_ptr->ver_syncstart - 1) << RADEON_CRTC_V_SYNC_STRT_SHIFT); 867254885Sdumbbell *v_sync_strt_wid = tmp; 868254885Sdumbbell} 869254885Sdumbbell 870254885Sdumbbellstatic int get_post_div(int value) 871254885Sdumbbell{ 872254885Sdumbbell int post_div; 873254885Sdumbbell switch (value) { 874254885Sdumbbell case 1: post_div = 0; break; 875254885Sdumbbell case 2: post_div = 1; break; 876254885Sdumbbell case 3: post_div = 4; break; 877254885Sdumbbell case 4: post_div = 2; break; 878254885Sdumbbell case 6: post_div = 6; break; 879254885Sdumbbell case 8: post_div = 3; break; 880254885Sdumbbell case 12: post_div = 7; break; 881254885Sdumbbell case 16: 882254885Sdumbbell default: post_div = 5; break; 883254885Sdumbbell } 884254885Sdumbbell return post_div; 885254885Sdumbbell} 886254885Sdumbbell 887254885Sdumbbellvoid radeon_legacy_tv_adjust_pll1(struct drm_encoder *encoder, 888254885Sdumbbell uint32_t *htotal_cntl, uint32_t *ppll_ref_div, 889254885Sdumbbell uint32_t *ppll_div_3, uint32_t *pixclks_cntl) 890254885Sdumbbell{ 891254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 892254885Sdumbbell const struct radeon_tv_mode_constants *const_ptr; 893254885Sdumbbell 894254885Sdumbbell const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL); 895254885Sdumbbell if (!const_ptr) 896254885Sdumbbell return; 897254885Sdumbbell 898254885Sdumbbell *htotal_cntl = (const_ptr->hor_total & 0x7) | RADEON_HTOT_CNTL_VGA_EN; 899254885Sdumbbell 900254885Sdumbbell *ppll_ref_div = const_ptr->crtcPLL_M; 901254885Sdumbbell 902254885Sdumbbell *ppll_div_3 = (const_ptr->crtcPLL_N & 0x7ff) | (get_post_div(const_ptr->crtcPLL_post_div) << 16); 903254885Sdumbbell *pixclks_cntl &= ~(RADEON_PIX2CLK_SRC_SEL_MASK | RADEON_PIXCLK_TV_SRC_SEL); 904254885Sdumbbell *pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK; 905254885Sdumbbell} 906254885Sdumbbell 907254885Sdumbbellvoid radeon_legacy_tv_adjust_pll2(struct drm_encoder *encoder, 908254885Sdumbbell uint32_t *htotal2_cntl, uint32_t *p2pll_ref_div, 909254885Sdumbbell uint32_t *p2pll_div_0, uint32_t *pixclks_cntl) 910254885Sdumbbell{ 911254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 912254885Sdumbbell const struct radeon_tv_mode_constants *const_ptr; 913254885Sdumbbell 914254885Sdumbbell const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL); 915254885Sdumbbell if (!const_ptr) 916254885Sdumbbell return; 917254885Sdumbbell 918254885Sdumbbell *htotal2_cntl = (const_ptr->hor_total & 0x7); 919254885Sdumbbell 920254885Sdumbbell *p2pll_ref_div = const_ptr->crtcPLL_M; 921254885Sdumbbell 922254885Sdumbbell *p2pll_div_0 = (const_ptr->crtcPLL_N & 0x7ff) | (get_post_div(const_ptr->crtcPLL_post_div) << 16); 923254885Sdumbbell *pixclks_cntl &= ~RADEON_PIX2CLK_SRC_SEL_MASK; 924254885Sdumbbell *pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK | RADEON_PIXCLK_TV_SRC_SEL; 925254885Sdumbbell} 926254885Sdumbbell 927