aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/saa7115.c
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2006-01-09 12:25:41 -0500
committerMauro Carvalho Chehab <mchehab@brturbo.com.br>2006-01-09 12:25:41 -0500
commit3578d3dd0b1e468a44a76a83efe90476a854625d (patch)
tree2cd544f2aae9844821afdf90308048a800e961a1 /drivers/media/video/saa7115.c
parent21fa715e67fe57e404d7f5f39b7f18016db9e4b6 (diff)
V4L/DVB (3214): Calculate the saa7115 AMCLK regs instead of using fixed values
- Calculate the audio master clock registers from the actual frequencies. This simplifies the code and it also prepares for adding CGC2 support. - VIDIOC_INT_AUDIO_CLOCK_FREQ now receives an u32 instead of an enum. It is more generic and actually easier to implement. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
Diffstat (limited to 'drivers/media/video/saa7115.c')
-rw-r--r--drivers/media/video/saa7115.c155
1 files changed, 36 insertions, 119 deletions
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index b175389d9f43..3e4e5584c5d0 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -39,6 +39,7 @@
39#include <linux/i2c.h> 39#include <linux/i2c.h>
40#include <linux/videodev2.h> 40#include <linux/videodev2.h>
41#include <media/v4l2-common.h> 41#include <media/v4l2-common.h>
42#include <asm/div64.h>
42 43
43MODULE_DESCRIPTION("Philips SAA7114/SAA7115 video decoder driver"); 44MODULE_DESCRIPTION("Philips SAA7114/SAA7115 video decoder driver");
44MODULE_AUTHOR("Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, Hans Verkuil"); 45MODULE_AUTHOR("Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, Hans Verkuil");
@@ -78,7 +79,7 @@ struct saa7115_state {
78 int hue; 79 int hue;
79 int sat; 80 int sat;
80 enum v4l2_chip_ident ident; 81 enum v4l2_chip_ident ident;
81 enum v4l2_audio_clock_freq audclk_freq; 82 u32 audclk_freq;
82}; 83};
83 84
84/* ----------------------------------------------------------------------- */ 85/* ----------------------------------------------------------------------- */
@@ -469,80 +470,6 @@ static const unsigned char saa7115_init_misc[] = {
469 0x00, 0x00 470 0x00, 0x00
470}; 471};
471 472
472/* ============== SAA7715 AUDIO settings ============= */
473
474/* 48.0 kHz */
475static const unsigned char saa7115_cfg_48_audio[] = {
476 0x34, 0xce,
477 0x35, 0xfb,
478 0x36, 0x30,
479 0x00, 0x00
480};
481
482/* 44.1 kHz */
483static const unsigned char saa7115_cfg_441_audio[] = {
484 0x34, 0xf2,
485 0x35, 0x00,
486 0x36, 0x2d,
487 0x00, 0x00
488};
489
490/* 32.0 kHz */
491static const unsigned char saa7115_cfg_32_audio[] = {
492 0x34, 0xdf,
493 0x35, 0xa7,
494 0x36, 0x20,
495 0x00, 0x00
496};
497
498/* 48.0 kHz 60hz */
499static const unsigned char saa7115_cfg_60hz_48_audio[] = {
500 0x30, 0xcd,
501 0x31, 0x20,
502 0x32, 0x03,
503 0x00, 0x00
504};
505
506/* 48.0 kHz 50hz */
507static const unsigned char saa7115_cfg_50hz_48_audio[] = {
508 0x30, 0x00,
509 0x31, 0xc0,
510 0x32, 0x03,
511 0x00, 0x00
512};
513
514/* 44.1 kHz 60hz */
515static const unsigned char saa7115_cfg_60hz_441_audio[] = {
516 0x30, 0xbc,
517 0x31, 0xdf,
518 0x32, 0x02,
519 0x00, 0x00
520};
521
522/* 44.1 kHz 50hz */
523static const unsigned char saa7115_cfg_50hz_441_audio[] = {
524 0x30, 0x00,
525 0x31, 0x72,
526 0x32, 0x03,
527 0x00, 0x00
528};
529
530/* 32.0 kHz 60hz */
531static const unsigned char saa7115_cfg_60hz_32_audio[] = {
532 0x30, 0xde,
533 0x31, 0x15,
534 0x32, 0x02,
535 0x00, 0x00
536};
537
538/* 32.0 kHz 50hz */
539static const unsigned char saa7115_cfg_50hz_32_audio[] = {
540 0x30, 0x00,
541 0x31, 0x80,
542 0x32, 0x02,
543 0x00, 0x00
544};
545
546static int saa7115_odd_parity(u8 c) 473static int saa7115_odd_parity(u8 c)
547{ 474{
548 c ^= (c >> 4); 475 c ^= (c >> 4);
@@ -627,40 +554,38 @@ static int saa7115_decode_wss(u8 * p)
627} 554}
628 555
629 556
630static int saa7115_set_audio_clock_freq(struct i2c_client *client, enum v4l2_audio_clock_freq freq) 557static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq)
631{ 558{
632 struct saa7115_state *state = i2c_get_clientdata(client); 559 struct saa7115_state *state = i2c_get_clientdata(client);
560 u32 acpf;
561 u32 acni;
562 u32 hz;
563 u64 f;
633 564
634 saa7115_dbg("set audio clock freq: %d\n", freq); 565 saa7115_dbg("set audio clock freq: %d\n", freq);
635 switch (freq) { 566
636 case V4L2_AUDCLK_32_KHZ: 567 /* sanity check */
637 saa7115_writeregs(client, saa7115_cfg_32_audio); 568 if (freq < 32000 || freq > 48000)
638 if (state->std & V4L2_STD_525_60) { 569 return -EINVAL;
639 saa7115_writeregs(client, saa7115_cfg_60hz_32_audio); 570
640 } else { 571 /* hz is the refresh rate times 100 */
641 saa7115_writeregs(client, saa7115_cfg_50hz_32_audio); 572 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
642 } 573 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
643 break; 574 acpf = (25600 * freq) / hz;
644 case V4L2_AUDCLK_441_KHZ: 575 /* acni = (256 * freq * 2^23) / crystal_frequency =
645 saa7115_writeregs(client, saa7115_cfg_441_audio); 576 (freq * 2^(8+23)) / crystal_frequency =
646 if (state->std & V4L2_STD_525_60) { 577 (freq << 31) / 32.11 MHz */
647 saa7115_writeregs(client, saa7115_cfg_60hz_441_audio); 578 f = freq;
648 } else { 579 f = f << 31;
649 saa7115_writeregs(client, saa7115_cfg_50hz_441_audio); 580 do_div(f, 32110000);
650 } 581 acni = f;
651 break; 582
652 case V4L2_AUDCLK_48_KHZ: 583 saa7115_write(client, 0x30, acpf & 0xff);
653 saa7115_writeregs(client, saa7115_cfg_48_audio); 584 saa7115_write(client, 0x31, (acpf >> 8) & 0xff);
654 if (state->std & V4L2_STD_525_60) { 585 saa7115_write(client, 0x32, (acpf >> 16) & 0x03);
655 saa7115_writeregs(client, saa7115_cfg_60hz_48_audio); 586 saa7115_write(client, 0x34, acni & 0xff);
656 } else { 587 saa7115_write(client, 0x35, (acni >> 8) & 0xff);
657 saa7115_writeregs(client, saa7115_cfg_50hz_48_audio); 588 saa7115_write(client, 0x36, (acni >> 16) & 0x3f);
658 }
659 break;
660 default:
661 saa7115_dbg("invalid audio setting %d\n", freq);
662 return -EINVAL;
663 }
664 state->audclk_freq = freq; 589 state->audclk_freq = freq;
665 return 0; 590 return 0;
666} 591}
@@ -773,24 +698,17 @@ static v4l2_std_id saa7115_get_v4lstd(struct i2c_client *client)
773static void saa7115_log_status(struct i2c_client *client) 698static void saa7115_log_status(struct i2c_client *client)
774{ 699{
775 struct saa7115_state *state = i2c_get_clientdata(client); 700 struct saa7115_state *state = i2c_get_clientdata(client);
776 char *audfreq = "undefined";
777 int reg1e, reg1f; 701 int reg1e, reg1f;
778 int signalOk; 702 int signalOk;
779 int vcr; 703 int vcr;
780 704
781 switch (state->audclk_freq) { 705 saa7115_info("Audio frequency: %d Hz\n", state->audclk_freq);
782 case V4L2_AUDCLK_32_KHZ: audfreq = "32 kHz"; break;
783 case V4L2_AUDCLK_441_KHZ: audfreq = "44.1 kHz"; break;
784 case V4L2_AUDCLK_48_KHZ: audfreq = "48 kHz"; break;
785 }
786
787 saa7115_info("Audio frequency: %s\n", audfreq);
788 if (client->name[6] == '4') { 706 if (client->name[6] == '4') {
789 /* status for the saa7114 */ 707 /* status for the saa7114 */
790 reg1f = saa7115_read(client, 0x1f); 708 reg1f = saa7115_read(client, 0x1f);
791 signalOk = (reg1f & 0xc1) == 0x81; 709 signalOk = (reg1f & 0xc1) == 0x81;
792 saa7115_info("Video signal: %s\n", signalOk ? "ok" : "bad"); 710 saa7115_info("Video signal: %s\n", signalOk ? "ok" : "bad");
793 saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz"); 711 saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
794 return; 712 return;
795 } 713 }
796 714
@@ -807,7 +725,7 @@ static void saa7115_log_status(struct i2c_client *client)
807 saa7115_info("Input: Composite %d\n", state->input); 725 saa7115_info("Input: Composite %d\n", state->input);
808 } 726 }
809 saa7115_info("Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad"); 727 saa7115_info("Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
810 saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz"); 728 saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
811 729
812 switch (reg1e & 0x03) { 730 switch (reg1e & 0x03) {
813 case 1: 731 case 1:
@@ -1108,7 +1026,7 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
1108 return saa7115_get_v4lfmt(client, (struct v4l2_format *)arg); 1026 return saa7115_get_v4lfmt(client, (struct v4l2_format *)arg);
1109 1027
1110 case VIDIOC_INT_AUDIO_CLOCK_FREQ: 1028 case VIDIOC_INT_AUDIO_CLOCK_FREQ:
1111 return saa7115_set_audio_clock_freq(client, *(enum v4l2_audio_clock_freq *)arg); 1029 return saa7115_set_audio_clock_freq(client, *(u32 *)arg);
1112 1030
1113 case VIDIOC_G_TUNER: 1031 case VIDIOC_G_TUNER:
1114 { 1032 {
@@ -1307,7 +1225,7 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
1307 state->hue = 0; 1225 state->hue = 0;
1308 state->sat = 64; 1226 state->sat = 64;
1309 state->ident = (chip_id == 4) ? V4L2_IDENT_SAA7114 : V4L2_IDENT_SAA7115; 1227 state->ident = (chip_id == 4) ? V4L2_IDENT_SAA7114 : V4L2_IDENT_SAA7115;
1310 state->audclk_freq = V4L2_AUDCLK_48_KHZ; 1228 state->audclk_freq = 48000;
1311 1229
1312 saa7115_dbg("writing init values\n"); 1230 saa7115_dbg("writing init values\n");
1313 1231
@@ -1317,8 +1235,7 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
1317 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); 1235 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
1318 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); 1236 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);
1319 saa7115_writeregs(client, saa7115_cfg_60hz_video); 1237 saa7115_writeregs(client, saa7115_cfg_60hz_video);
1320 saa7115_writeregs(client, saa7115_cfg_48_audio); 1238 saa7115_set_audio_clock_freq(client, state->audclk_freq);
1321 saa7115_writeregs(client, saa7115_cfg_60hz_48_audio);
1322 saa7115_writeregs(client, saa7115_cfg_reset_scaler); 1239 saa7115_writeregs(client, saa7115_cfg_reset_scaler);
1323 1240
1324 i2c_attach_client(client); 1241 i2c_attach_client(client);