aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/saa7115.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/saa7115.c')
-rw-r--r--drivers/media/video/saa7115.c51
1 files changed, 43 insertions, 8 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);