diff options
-rw-r--r-- | drivers/media/video/saa7115.c | 51 | ||||
-rw-r--r-- | drivers/media/video/v4l2-common.c | 9 | ||||
-rw-r--r-- | include/media/saa7115.h | 11 | ||||
-rw-r--r-- | include/media/v4l2-common.h | 11 |
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 | ||
377 | static const unsigned char saa7115_init_misc[] = { | 381 | static 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 | ||
214 | struct 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_ */ |