aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2006-04-02 11:50:42 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-06-25 00:57:36 -0400
commitb7f8292c96463810edfecff70dd4631d47e5a36b (patch)
tree02b1cfb3f753ea82c6fa51c901420074875be355 /drivers/media/video
parent2eb606db1134ce860cc0cbf8b533b6315d182e21 (diff)
V4L/DVB (3711): Add support for VIDIOC_INT_S_CRYSTAL_FREQ internal command.
Some saa7115-based cards use a different crystal frequency and a different audio clock generation. Add a new VIDIOC_INT_S_CRYSTAL_FREQ command to be able to set these values. Also change the default APLL setting to 0. It makes no sense to have the audio clock independent from the video clock, this can lead to audio/video synchronization problems. Setting this to 0 is also consistent with the old saa7114.c source and the way the Hauppauge Windows driver sets it. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/saa7115.c51
-rw-r--r--drivers/media/video/v4l2-common.c9
2 files changed, 51 insertions, 9 deletions
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index dceebc0b1250..edea9e3d2dca 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -72,6 +72,10 @@ struct saa7115_state {
72 int sat; 72 int sat;
73 enum v4l2_chip_ident ident; 73 enum v4l2_chip_ident ident;
74 u32 audclk_freq; 74 u32 audclk_freq;
75 u32 crystal_freq;
76 u8 ucgc;
77 u8 cgcdiv;
78 u8 apll;
75}; 79};
76 80
77/* ----------------------------------------------------------------------- */ 81/* ----------------------------------------------------------------------- */
@@ -375,10 +379,6 @@ static const unsigned char saa7113_init_auto_input[] = {
375}; 379};
376 380
377static const unsigned char saa7115_init_misc[] = { 381static const unsigned char saa7115_init_misc[] = {
378 0x38, 0x03, /* audio stuff */
379 0x39, 0x10,
380 0x3a, 0x08,
381
382 0x81, 0x01, /* reg 0x15,0x16 define blanking window */ 382 0x81, 0x01, /* reg 0x15,0x16 define blanking window */
383 0x82, 0x00, 383 0x82, 0x00,
384 0x83, 0x01, /* I port settings */ 384 0x83, 0x01, /* I port settings */
@@ -584,6 +584,7 @@ static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq)
584 u32 acni; 584 u32 acni;
585 u32 hz; 585 u32 hz;
586 u64 f; 586 u64 f;
587 u8 acc = 0; /* reg 0x3a, audio clock control */
587 588
588 v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq); 589 v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq);
589 590
@@ -591,18 +592,34 @@ static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq)
591 if (freq < 32000 || freq > 48000) 592 if (freq < 32000 || freq > 48000)
592 return -EINVAL; 593 return -EINVAL;
593 594
595 /* The saa7113 has no audio clock */
596 if (state->ident == V4L2_IDENT_SAA7113)
597 return 0;
598
594 /* hz is the refresh rate times 100 */ 599 /* hz is the refresh rate times 100 */
595 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000; 600 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
596 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */ 601 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
597 acpf = (25600 * freq) / hz; 602 acpf = (25600 * freq) / hz;
598 /* acni = (256 * freq * 2^23) / crystal_frequency = 603 /* acni = (256 * freq * 2^23) / crystal_frequency =
599 (freq * 2^(8+23)) / crystal_frequency = 604 (freq * 2^(8+23)) / crystal_frequency =
600 (freq << 31) / 32.11 MHz */ 605 (freq << 31) / crystal_frequency */
601 f = freq; 606 f = freq;
602 f = f << 31; 607 f = f << 31;
603 do_div(f, 32110000); 608 do_div(f, state->crystal_freq);
604 acni = f; 609 acni = f;
610 if (state->ucgc) {
611 acpf = acpf * state->cgcdiv / 16;
612 acni = acni * state->cgcdiv / 16;
613 acc = 0x80;
614 if (state->cgcdiv == 3)
615 acc |= 0x40;
616 }
617 if (state->apll)
618 acc |= 0x08;
605 619
620 saa7115_write(client, 0x38, 0x03);
621 saa7115_write(client, 0x39, 0x10);
622 saa7115_write(client, 0x3a, acc);
606 saa7115_write(client, 0x30, acpf & 0xff); 623 saa7115_write(client, 0x30, acpf & 0xff);
607 saa7115_write(client, 0x31, (acpf >> 8) & 0xff); 624 saa7115_write(client, 0x31, (acpf >> 8) & 0xff);
608 saa7115_write(client, 0x32, (acpf >> 16) & 0x03); 625 saa7115_write(client, 0x32, (acpf >> 16) & 0x03);
@@ -1260,6 +1277,21 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
1260 } 1277 }
1261 break; 1278 break;
1262 1279
1280 case VIDIOC_INT_S_CRYSTAL_FREQ:
1281 {
1282 struct v4l2_crystal_freq *freq = arg;
1283
1284 if (freq->freq != SAA7115_FREQ_32_11_MHZ &&
1285 freq->freq != SAA7115_FREQ_24_576_MHZ)
1286 return -EINVAL;
1287 state->crystal_freq = freq->freq;
1288 state->cgcdiv = (freq->flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
1289 state->ucgc = (freq->flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0;
1290 state->apll = (freq->flags & SAA7115_FREQ_FL_APLL) ? 1 : 0;
1291 saa7115_set_audio_clock_freq(client, state->audclk_freq);
1292 break;
1293 }
1294
1263 case VIDIOC_INT_DECODE_VBI_LINE: 1295 case VIDIOC_INT_DECODE_VBI_LINE:
1264 saa7115_decode_vbi_line(client, arg); 1296 saa7115_decode_vbi_line(client, arg);
1265 break; 1297 break;
@@ -1401,10 +1433,13 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
1401 v4l_dbg(1, debug, client, "writing init values\n"); 1433 v4l_dbg(1, debug, client, "writing init values\n");
1402 1434
1403 /* init to 60hz/48khz */ 1435 /* init to 60hz/48khz */
1404 if (state->ident == V4L2_IDENT_SAA7113) 1436 if (state->ident == V4L2_IDENT_SAA7113) {
1437 state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
1405 saa7115_writeregs(client, saa7113_init_auto_input); 1438 saa7115_writeregs(client, saa7113_init_auto_input);
1406 else 1439 } else {
1440 state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
1407 saa7115_writeregs(client, saa7115_init_auto_input); 1441 saa7115_writeregs(client, saa7115_init_auto_input);
1442 }
1408 saa7115_writeregs(client, saa7115_init_misc); 1443 saa7115_writeregs(client, saa7115_init_misc);
1409 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); 1444 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
1410 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); 1445 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index d330fa985bcc..ad92e07e74f7 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -331,7 +331,8 @@ static const char *v4l2_int_ioctls[] = {
331 [_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)] = "VIDIOC_INT_S_AUDIO_ROUTING", 331 [_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)] = "VIDIOC_INT_S_AUDIO_ROUTING",
332 [_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)] = "VIDIOC_INT_G_AUDIO_ROUTING", 332 [_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)] = "VIDIOC_INT_G_AUDIO_ROUTING",
333 [_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)] = "VIDIOC_INT_S_VIDEO_ROUTING", 333 [_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)] = "VIDIOC_INT_S_VIDEO_ROUTING",
334 [_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)] = "VIDIOC_INT_G_VIDEO_ROUTING" 334 [_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)] = "VIDIOC_INT_G_VIDEO_ROUTING",
335 [_IOC_NR(VIDIOC_INT_S_CRYSTAL_FREQ)] = "VIDIOC_INT_S_CRYSTAL_FREQ"
335}; 336};
336#define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls) 337#define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls)
337 338
@@ -667,6 +668,12 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
667 printk ("%s: input=0x%x, output=0x%x\n", s, p->input, p->output); 668 printk ("%s: input=0x%x, output=0x%x\n", s, p->input, p->output);
668 break; 669 break;
669 } 670 }
671 case VIDIOC_INT_S_CRYSTAL_FREQ:
672 {
673 struct v4l2_crystal_freq *p=arg;
674 printk ("%s: freq=%u, flags=0x%x\n", s, p->freq, p->flags);
675 break;
676 }
670 case VIDIOC_G_SLICED_VBI_CAP: 677 case VIDIOC_G_SLICED_VBI_CAP:
671 { 678 {
672 struct v4l2_sliced_vbi_cap *p=arg; 679 struct v4l2_sliced_vbi_cap *p=arg;