aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/saa7115.c51
-rw-r--r--drivers/media/video/v4l2-common.c9
-rw-r--r--include/media/saa7115.h11
-rw-r--r--include/media/v4l2-common.h11
4 files changed, 72 insertions, 10 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;
diff --git a/include/media/saa7115.h b/include/media/saa7115.h
index 6b4836f3f057..9f0e2285a099 100644
--- a/include/media/saa7115.h
+++ b/include/media/saa7115.h
@@ -1,5 +1,5 @@
1/* 1/*
2 saa7115.h - definition for saa7113/4/5 inputs 2 saa7115.h - definition for saa7113/4/5 inputs and frequency flags
3 3
4 Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) 4 Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
5 5
@@ -33,5 +33,14 @@
33#define SAA7115_SVIDEO2 8 33#define SAA7115_SVIDEO2 8
34#define SAA7115_SVIDEO3 9 34#define SAA7115_SVIDEO3 9
35 35
36/* SAA7115 v4l2_crystal_freq frequency values */
37#define SAA7115_FREQ_32_11_MHZ 32110000 /* 32.11 MHz crystal, SAA7114/5 only */
38#define SAA7115_FREQ_24_576_MHZ 24576000 /* 24.576 MHz crystal */
39
40/* SAA7115 v4l2_crystal_freq audio clock control flags */
41#define SAA7115_FREQ_FL_UCGC (1 << 0) /* SA 3A[7], UCGC, SAA7115 only */
42#define SAA7115_FREQ_FL_CGCDIV (1 << 1) /* SA 3A[6], CGCDIV, SAA7115 only */
43#define SAA7115_FREQ_FL_APLL (1 << 2) /* SA 3A[3], APLL, SAA7114/5 only */
44
36#endif 45#endif
37 46
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index 642520acdfa7..827f7edcd665 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -211,4 +211,15 @@ struct v4l2_routing {
211#define VIDIOC_INT_S_VIDEO_ROUTING _IOW ('d', 111, struct v4l2_routing) 211#define VIDIOC_INT_S_VIDEO_ROUTING _IOW ('d', 111, struct v4l2_routing)
212#define VIDIOC_INT_G_VIDEO_ROUTING _IOR ('d', 112, struct v4l2_routing) 212#define VIDIOC_INT_G_VIDEO_ROUTING _IOR ('d', 112, struct v4l2_routing)
213 213
214struct v4l2_crystal_freq {
215 u32 freq; /* frequency in Hz of the crystal */
216 u32 flags; /* device specific flags */
217};
218
219/* Sets the frequency of the crystal used to generate the clocks.
220 An extra flags field allows device specific configuration regarding
221 clock frequency dividers, etc. If not used, then set flags to 0.
222 If the frequency is not supported, then -EINVAL is returned. */
223#define VIDIOC_INT_S_CRYSTAL_FREQ _IOW ('d', 113, struct v4l2_crystal_freq)
224
214#endif /* V4L2_COMMON_H_ */ 225#endif /* V4L2_COMMON_H_ */