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