aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18/cx18-firmware.c
diff options
context:
space:
mode:
authorAndy Walls <awalls@radix.net>2008-12-20 21:48:57 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-12-30 06:39:24 -0500
commit55d81aa5c11f9da510a72cc48fd59689b3e91e3a (patch)
tree346221769914f99581eff5cdb5afe068acacd77b /drivers/media/video/cx18/cx18-firmware.c
parent57e24b629a5282bee24aaff44977270a3e462041 (diff)
V4L/DVB (9937): cx18: Use a consistent crystal value for computing all PLL parameters
Use a consistent crystal value of 28.636360 MHz for computing all PLL parameters so clocks don't have relative error due to assumed crystal value mismatches. Also aimed to have all PLLs run their VOCs at close to 400 MHz to minimze the error of these PLLs as frequency synthesizers. Also set the VDCLK and AIMCLK PLLs to sane values before the APU and CPU firmware are loaded. Also fixed I2S Master clock dividers. Many thanks to Mike Bradley and Jeff Campbell for reporting this problem and suggesting the solution, researching and experimenting, and performing extensive testing to support their suggested solution. Reported-by: Jeff Campbell <jac1dlists@gmail.com> Reported-by: Mike Bradley <mike.bradley@incanetworks.com> Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx18/cx18-firmware.c')
-rw-r--r--drivers/media/video/cx18/cx18-firmware.c69
1 files changed, 64 insertions, 5 deletions
diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c
index e74f76d47df5..1fa95da1575e 100644
--- a/drivers/media/video/cx18/cx18-firmware.c
+++ b/drivers/media/video/cx18/cx18-firmware.c
@@ -26,6 +26,7 @@
26#include "cx18-irq.h" 26#include "cx18-irq.h"
27#include "cx18-firmware.h" 27#include "cx18-firmware.h"
28#include "cx18-cards.h" 28#include "cx18-cards.h"
29#include "cx18-av-core.h"
29#include <linux/firmware.h> 30#include <linux/firmware.h>
30 31
31#define CX18_PROC_SOFT_RESET 0xc70010 32#define CX18_PROC_SOFT_RESET 0xc70010
@@ -224,7 +225,45 @@ void cx18_init_power(struct cx18 *cx, int lowpwr)
224 cx18_write_reg_expect(cx, 0x00020000, CX18_ADEC_CONTROL, 225 cx18_write_reg_expect(cx, 0x00020000, CX18_ADEC_CONTROL,
225 0x00000000, 0x00020002); 226 0x00000000, 0x00020002);
226 227
227 /* The fast clock is at 200/245 MHz */ 228 /*
229 * The PLL parameters are based on the external crystal frequency that
230 * would ideally be:
231 *
232 * NTSC Color subcarrier freq * 8 =
233 * 4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz
234 *
235 * The accidents of history and rationale that explain from where this
236 * combination of magic numbers originate can be found in:
237 *
238 * [1] Abrahams, I. C., "Choice of Chrominance Subcarrier Frequency in
239 * the NTSC Standards", Proceedings of the I-R-E, January 1954, pp 79-80
240 *
241 * [2] Abrahams, I. C., "The 'Frequency Interleaving' Principle in the
242 * NTSC Standards", Proceedings of the I-R-E, January 1954, pp 81-83
243 *
244 * As Mike Bradley has rightly pointed out, it's not the exact crystal
245 * frequency that matters, only that all parts of the driver and
246 * firmware are using the same value (close to the ideal value).
247 *
248 * Since I have a strong suspicion that, if the firmware ever assumes a
249 * crystal value at all, it will assume 28.636360 MHz, the crystal
250 * freq used in calculations in this driver will be:
251 *
252 * xtal_freq = 28.636360 MHz
253 *
254 * an error of less than 0.13 ppm which is way, way better than any off
255 * the shelf crystal will have for accuracy anyway.
256 *
257 * Below I aim to run the PLLs' VCOs near 400 MHz to minimze errors.
258 *
259 * Many thanks to Jeff Campbell and Mike Bradley for their extensive
260 * investigation, experimentation, testing, and suggested solutions of
261 * of audio/video sync problems with SVideo and CVBS captures.
262 */
263
264 /* the fast clock is at 200/245 MHz */
265 /* 1 * xtal_freq * 0x0d.f7df9b8 / 2 = 200 MHz: 400 MHz pre post-divide*/
266 /* 1 * xtal_freq * 0x11.1c71eb8 / 2 = 245 MHz: 490 MHz pre post-divide*/
228 cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT); 267 cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);
229 cx18_write_reg(cx, lowpwr ? 0x1EFBF37 : 0x038E3D7, 268 cx18_write_reg(cx, lowpwr ? 0x1EFBF37 : 0x038E3D7,
230 CX18_FAST_CLOCK_PLL_FRAC); 269 CX18_FAST_CLOCK_PLL_FRAC);
@@ -234,16 +273,36 @@ void cx18_init_power(struct cx18 *cx, int lowpwr)
234 cx18_write_reg(cx, 4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH); 273 cx18_write_reg(cx, 4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH);
235 274
236 /* set slow clock to 125/120 MHz */ 275 /* set slow clock to 125/120 MHz */
237 cx18_write_reg(cx, lowpwr ? 0x11 : 0x10, CX18_SLOW_CLOCK_PLL_INT); 276 /* xtal_freq * 0x0d.1861a20 / 3 = 125 MHz: 375 MHz before post-divide */
238 cx18_write_reg(cx, lowpwr ? 0xEBAF05 : 0x18618A8, 277 /* xtal_freq * 0x0c.92493f8 / 3 = 120 MHz: 360 MHz before post-divide */
278 cx18_write_reg(cx, lowpwr ? 0xD : 0xC, CX18_SLOW_CLOCK_PLL_INT);
279 cx18_write_reg(cx, lowpwr ? 0x30C344 : 0x124927F,
239 CX18_SLOW_CLOCK_PLL_FRAC); 280 CX18_SLOW_CLOCK_PLL_FRAC);
240 cx18_write_reg(cx, 4, CX18_SLOW_CLOCK_PLL_POST); 281 cx18_write_reg(cx, 3, CX18_SLOW_CLOCK_PLL_POST);
241 282
242 /* mpeg clock pll 54MHz */ 283 /* mpeg clock pll 54MHz */
284 /* xtal_freq * 0xf.15f17f0 / 8 = 54 MHz: 432 MHz before post-divide */
243 cx18_write_reg(cx, 0xF, CX18_MPEG_CLOCK_PLL_INT); 285 cx18_write_reg(cx, 0xF, CX18_MPEG_CLOCK_PLL_INT);
244 cx18_write_reg(cx, 0x2BCFEF, CX18_MPEG_CLOCK_PLL_FRAC); 286 cx18_write_reg(cx, 0x2BE2FE, CX18_MPEG_CLOCK_PLL_FRAC);
245 cx18_write_reg(cx, 8, CX18_MPEG_CLOCK_PLL_POST); 287 cx18_write_reg(cx, 8, CX18_MPEG_CLOCK_PLL_POST);
246 288
289 /*
290 * VDCLK Integer = 0x0f, Post Divider = 0x04
291 * AIMCLK Integer = 0x0e, Post Divider = 0x16
292 */
293 cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f);
294
295 /* VDCLK Fraction = 0x2be2fe */
296 /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */
297 cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe);
298
299 /* AIMCLK Fraction = 0x05227ad */
300 /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz before post-divide */
301 cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad);
302
303 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */
304 cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56);
305
247 /* Defaults */ 306 /* Defaults */
248 /* APU = SC or SC/2 = 125/62.5 */ 307 /* APU = SC or SC/2 = 125/62.5 */
249 /* EPU = SC = 125 */ 308 /* EPU = SC = 125 */