Rev 1179 | Rev 2997 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1179 | serge | 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 |
||
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 | |||
1404 | serge | 80 | static const uint16_t hor_timing_NTSC[MAX_H_CODE_TIMING_LEN] = { |
1179 | serge | 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 | |||
99 | }; |
||
100 | |||
1404 | serge | 101 | static const uint16_t vert_timing_NTSC[MAX_V_CODE_TIMING_LEN] = { |
1179 | serge | 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 | |||
116 | }; |
||
117 | |||
1404 | serge | 118 | static const uint16_t hor_timing_PAL[MAX_H_CODE_TIMING_LEN] = { |
1179 | serge | 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 | |||
137 | }; |
||
138 | |||
1404 | serge | 139 | static const uint16_t vert_timing_PAL[MAX_V_CODE_TIMING_LEN] = { |
1179 | serge | 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 | |||
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 | |||
1404 | serge | 626 | if (flicker_removal < 2) |
627 | flicker_removal = 2; |
||
628 | for (i = 0; i < ARRAY_SIZE(SLOPE_limit); ++i) { |
||
1179 | serge | 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 |