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