From 56fc08ca375491b965cb76fad65bfb98973e80d8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 23 Jun 2005 22:05:07 -0700 Subject: [PATCH] v4l: update for tuner cards and some V4L chips Tuner improvements and additions. TEA5767 FM tuner added. Several small fixes. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Nickolay V Shmyrev Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bt832.c | 50 +++++---- drivers/media/video/bt832.h | 36 +++---- drivers/media/video/msp3400.c | 13 +-- drivers/media/video/msp3400.h | 4 + drivers/media/video/tda7432.c | 1 + drivers/media/video/tda9875.c | 1 + drivers/media/video/tda9887.c | 41 ++++++- drivers/media/video/tuner-core.c | 212 +++++++++++++++++++++++++------------ drivers/media/video/tuner-simple.c | 52 +++++---- drivers/media/video/tvaudio.c | 2 +- drivers/media/video/tvmixer.c | 4 + 11 files changed, 278 insertions(+), 138 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c index 07f72f64c5f7..3bb347d93b9b 100644 --- a/drivers/media/video/bt832.c +++ b/drivers/media/video/bt832.c @@ -6,7 +6,7 @@ It outputs an 8-bit 4:2:2 YUV or YCrCb video signal which can be directly connected to bt848/bt878 GPIO pins on this purpose. (see: VLSI Vision Ltd. www.vvl.co.uk for camera datasheets) - + Supported Cards: - Pixelview Rev.4E: 0x8a GPIO 0x400000 toggles Bt832 RESET, and the chip changes to i2c 0x88 ! @@ -31,16 +31,16 @@ #include #include -#include "id.h" -#include "audiochip.h" +#include +#include #include "bttv.h" #include "bt832.h" MODULE_LICENSE("GPL"); /* Addresses to scan */ -static unsigned short normal_i2c[] = { I2C_BT832_ALT1>>1, I2C_BT832_ALT2>>1, - I2C_CLIENT_END }; +static unsigned short normal_i2c[] = {I2C_CLIENT_END}; +static unsigned short normal_i2c_range[] = {I2C_BT832_ALT1>>1,I2C_BT832_ALT2>>1,I2C_CLIENT_END}; I2C_CLIENT_INSMOD; /* ---------------------------------------------------------------------- */ @@ -95,7 +95,7 @@ int bt832_init(struct i2c_client *i2c_client_s) buf=kmalloc(65,GFP_KERNEL); bt832_hexdump(i2c_client_s,buf); - + if(buf[0x40] != 0x31) { printk("bt832: this i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]); kfree(buf); @@ -135,7 +135,7 @@ int bt832_init(struct i2c_client *i2c_client_s) buf[1]= 0x27 & (~0x01); // Default | !skip if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) printk("bt832: i2c i/o error EO: rc == %d (should be 2)\n",rc); - + bt832_hexdump(i2c_client_s,buf); #if 0 @@ -168,8 +168,7 @@ int bt832_init(struct i2c_client *i2c_client_s) -static int bt832_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind) +static int bt832_attach(struct i2c_adapter *adap, int addr, int kind) { struct bt832 *t; @@ -184,27 +183,32 @@ static int bt832_attach(struct i2c_adapter *adap, int addr, return -ENOMEM; memset(t,0,sizeof(*t)); t->client = client_template; - t->client.data = t; + i2c_set_clientdata(&t->client, t); i2c_attach_client(&t->client); if(! bt832_init(&t->client)) { bt832_detach(&t->client); return -1; } - + return 0; } static int bt832_probe(struct i2c_adapter *adap) { +#ifdef I2C_CLASS_TV_ANALOG if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, bt832_attach); +#else + if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) + return i2c_probe(adap, &addr_data, bt832_attach); +#endif return 0; } static int bt832_detach(struct i2c_client *client) { - struct bt832 *t = (struct bt832*)client->data; + struct bt832 *t = i2c_get_clientdata(client); printk("bt832: detach.\n"); i2c_detach_client(client); @@ -215,7 +219,7 @@ static int bt832_detach(struct i2c_client *client) static int bt832_command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct bt832 *t = (struct bt832*)client->data; + struct bt832 *t = i2c_get_clientdata(client); printk("bt832: command %x\n",cmd); @@ -249,19 +253,18 @@ static struct i2c_driver driver = { }; static struct i2c_client client_template = { - .name = "bt832", - .flags = I2C_CLIENT_ALLOW_USE, - .driver = &driver, + I2C_DEVNAME("bt832"), + .flags = I2C_CLIENT_ALLOW_USE, + .driver = &driver, }; -int bt832_init_module(void) +static int __init bt832_init_module(void) { - i2c_add_driver(&driver); - return 0; + return i2c_add_driver(&driver); } -static void bt832_cleanup_module(void) +static void __exit bt832_cleanup_module(void) { i2c_del_driver(&driver); } @@ -269,3 +272,10 @@ static void bt832_cleanup_module(void) module_init(bt832_init_module); module_exit(bt832_cleanup_module); +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/video/bt832.h b/drivers/media/video/bt832.h index 7a98c06e0e34..9b6a8d2c96b5 100644 --- a/drivers/media/video/bt832.h +++ b/drivers/media/video/bt832.h @@ -1,6 +1,6 @@ /* Bt832 CMOS Camera Video Processor (VP) - The Bt832 CMOS Camera Video Processor chip connects a Quartsight CMOS + The Bt832 CMOS Camera Video Processor chip connects a Quartsight CMOS color digital camera directly to video capture devices via an 8-bit, 4:2:2 YUV or YCrCb video interface. @@ -85,7 +85,7 @@ #define BT832_DEVICE_ID 63 # define BT832_DEVICE_ID__31 0x31 // Bt832 has ID 0x31 -/* STMicroelectronivcs VV5404 camera module +/* STMicroelectronivcs VV5404 camera module i2c: 0x20: sensor address i2c: 0xa0: eeprom for ccd defect map */ @@ -256,26 +256,26 @@ For the CCIR-601 standards, the sampling is based on a static orthogonal samplin //=========================================================================== // Timing generator SRAM table values for CCIR601 720x480 NTSC //=========================================================================== -// For NTSC CCIR656 +// For NTSC CCIR656 BYTE BtCard::SRAMTable_NTSC[] = { // SRAM Timing Table for NTSC - 0x0c, 0xc0, 0x00, - 0x00, 0x90, 0xc2, - 0x03, 0x10, 0x03, - 0x06, 0x10, 0x34, - 0x12, 0x12, 0x65, - 0x02, 0x13, 0x24, - 0x19, 0x00, 0x24, - 0x39, 0x00, 0x96, - 0x59, 0x08, 0x93, + 0x0c, 0xc0, 0x00, + 0x00, 0x90, 0xc2, + 0x03, 0x10, 0x03, + 0x06, 0x10, 0x34, + 0x12, 0x12, 0x65, + 0x02, 0x13, 0x24, + 0x19, 0x00, 0x24, + 0x39, 0x00, 0x96, + 0x59, 0x08, 0x93, 0x83, 0x08, 0x97, - 0x03, 0x50, 0x30, - 0xc0, 0x40, 0x30, - 0x86, 0x01, 0x01, - 0xa6, 0x0d, 0x62, - 0x03, 0x11, 0x61, - 0x05, 0x37, 0x30, + 0x03, 0x50, 0x30, + 0xc0, 0x40, 0x30, + 0x86, 0x01, 0x01, + 0xa6, 0x0d, 0x62, + 0x03, 0x11, 0x61, + 0x05, 0x37, 0x30, 0xac, 0x21, 0x50 }; diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index 09464d624a6b..05b83faa9a02 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -147,6 +147,7 @@ static unsigned short normal_i2c[] = { I2C_MSP3400C_ALT >> 1, I2C_CLIENT_END }; +static unsigned short normal_i2c_range[] = {I2C_CLIENT_END,I2C_CLIENT_END}; I2C_CLIENT_INSMOD; /* ----------------------------------------------------------------------- */ @@ -735,7 +736,6 @@ static int msp34xx_sleep(struct msp3400c *msp, int timeout) { DECLARE_WAITQUEUE(wait, current); -again: add_wait_queue(&msp->wq, &wait); if (!kthread_should_stop()) { if (timeout < 0) { @@ -751,12 +751,9 @@ again: #endif } } - + if (current->flags & PF_FREEZE) + refrigerator(PF_FREEZE); remove_wait_queue(&msp->wq, &wait); - - if (try_to_freeze(PF_FREEZE)) - goto again; - return msp->restart; } @@ -1436,7 +1433,7 @@ static int msp_detach(struct i2c_client *client); static int msp_probe(struct i2c_adapter *adap); static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg); -static int msp_suspend(struct device * dev, pm_message_t state, u32 level); +static int msp_suspend(struct device * dev, u32 state, u32 level); static int msp_resume(struct device * dev, u32 level); static void msp_wake_thread(struct i2c_client *client); @@ -1841,7 +1838,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } -static int msp_suspend(struct device * dev, pm_message_t state, u32 level) +static int msp_suspend(struct device * dev, u32 state, u32 level) { struct i2c_client *c = container_of(dev, struct i2c_client, dev); diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h index d70a954e13aa..023f33056a4f 100644 --- a/drivers/media/video/msp3400.h +++ b/drivers/media/video/msp3400.h @@ -1,3 +1,7 @@ +/* + * $Id: msp3400.h,v 1.3 2005/06/12 04:19:19 mchehab Exp $ + */ + #ifndef MSP3400_H #define MSP3400_H diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c index 07ba6d3ed08c..376a4a439e9b 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/video/tda7432.c @@ -74,6 +74,7 @@ static unsigned short normal_i2c[] = { I2C_TDA7432 >> 1, I2C_CLIENT_END, }; +static unsigned short normal_i2c_range[] = { I2C_CLIENT_END, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; /* Structure of address and subaddresses for the tda7432 */ diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index 97b113e070f3..4f1114c033a1 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c @@ -44,6 +44,7 @@ static unsigned short normal_i2c[] = { I2C_TDA9875 >> 1, I2C_CLIENT_END }; +static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; I2C_CLIENT_INSMOD; /* This is a superset of the TDA9875 */ diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 7e6e6dd966a2..33d6ee6cde48 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -33,6 +33,7 @@ static unsigned short normal_i2c[] = { 0x96 >>1, I2C_CLIENT_END, }; +static unsigned short normal_i2c_range[] = {I2C_CLIENT_END,I2C_CLIENT_END}; I2C_CLIENT_INSMOD; /* insmod options */ @@ -53,6 +54,7 @@ struct tda9887 { unsigned int config; unsigned int pinnacle_id; unsigned int using_v4l2; + unsigned int radio_mode; }; struct tvnorm { @@ -212,12 +214,22 @@ static struct tvnorm tvnorms[] = { } }; -static struct tvnorm radio = { - .name = "radio", +static struct tvnorm radio_stereo = { + .name = "Radio Stereo", + .b = ( cFmRadio | + cQSS ), + .c = ( cDeemphasisOFF | + cAudioGain6 ), + .e = ( cAudioIF_5_5 | + cRadioIF_38_90 ), +}; + +static struct tvnorm radio_mono = { + .name = "Radio Mono", .b = ( cFmRadio | cQSS ), .c = ( cDeemphasisON | - cDeemphasis50 ), + cDeemphasis50), .e = ( cAudioIF_5_5 | cRadioIF_38_90 ), }; @@ -354,7 +366,10 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf) int i; if (t->radio) { - norm = &radio; + if (t->radio_mode == V4L2_TUNER_MODE_MONO) + norm = &radio_mono; + else + norm = &radio_stereo; } else { for (i = 0; i < ARRAY_SIZE(tvnorms); i++) { if (tvnorms[i].std & t->std) { @@ -545,11 +560,14 @@ static int tda9887_configure(struct tda9887 *t) memset(buf,0,sizeof(buf)); tda9887_set_tvnorm(t,buf); + buf[1] |= cOutputPort1Inactive; buf[1] |= cOutputPort2Inactive; + if (UNSET != t->pinnacle_id) { tda9887_set_pinnacle(t,buf); } + tda9887_set_config(t,buf); tda9887_set_insmod(t,buf); @@ -592,9 +610,12 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind) if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) return -ENOMEM; memset(t,0,sizeof(*t)); + t->client = client_template; t->std = 0; t->pinnacle_id = UNSET; + t->radio_mode = V4L2_TUNER_MODE_STEREO; + i2c_set_clientdata(&t->client, t); i2c_attach_client(&t->client); @@ -733,6 +754,16 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) } break; } + case VIDIOC_S_TUNER: + { + struct v4l2_tuner* tuner = arg; + + if (t->radio) { + t->radio_mode = tuner->audmode; + tda9887_configure (t); + } + break; + } default: /* nothing */ break; @@ -740,7 +771,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } -static int tda9887_suspend(struct device * dev, pm_message_t state, u32 level) +static int tda9887_suspend(struct device * dev, u32 state, u32 level) { dprintk("tda9887: suspend\n"); return 0; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 71423ae3b4dd..ba13bfadb523 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -1,5 +1,5 @@ /* - * $Id: tuner-core.c,v 1.7 2005/05/30 02:02:47 mchehab Exp $ + * $Id: tuner-core.c,v 1.15 2005/06/12 01:36:14 mchehab Exp $ * * i2c tv tuner chip device driver * core core, i.e. kernel interfaces, registering and so on @@ -26,15 +26,17 @@ /* * comment line bellow to return to old behavor, where only one I2C device is supported */ -/* #define CONFIG_TUNER_MULTI_I2C */ +#define CONFIG_TUNER_MULTI_I2C /**/ #define UNSET (-1U) /* standard i2c insmod options */ static unsigned short normal_i2c[] = { 0x4b, /* tda8290 */ - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + I2C_CLIENT_END +}; +static unsigned short normal_i2c_range[] = { + 0x60, 0x6f, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; @@ -59,7 +61,7 @@ MODULE_LICENSE("GPL"); static int this_adap; #ifdef CONFIG_TUNER_MULTI_I2C -static unsigned short tv_tuner, radio_tuner; +static unsigned short first_tuner, tv_tuner, radio_tuner; #endif static struct i2c_driver driver; @@ -67,7 +69,7 @@ static struct i2c_client client_template; /* ---------------------------------------------------------------------- */ -// Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz +/* Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz */ static void set_tv_freq(struct i2c_client *c, unsigned int freq) { struct tuner *t = i2c_get_clientdata(c); @@ -81,14 +83,26 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) return; } if (freq < tv_range[0]*16 || freq > tv_range[1]*16) { - /* FIXME: better do that chip-specific, but - right now we don't have that in the config - struct and this way is still better than no - check at all */ - tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n", - freq/16,freq%16*100/16,tv_range[0],tv_range[1]); - return; + + if (freq >= tv_range[0]*16364 && freq <= tv_range[1]*16384) { + /* V4L2_TUNER_CAP_LOW frequency */ + + tuner_dbg("V4L2_TUNER_CAP_LOW freq selected for TV. Tuners yet doesn't support converting it to valid freq.\n"); + + t->tv_freq(c,freq>>10); + + return; + } else { + /* FIXME: better do that chip-specific, but + right now we don't have that in the config + struct and this way is still better than no + check at all */ + tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n", + freq/16,freq%16*100/16,tv_range[0],tv_range[1]); + return; + } } + tuner_dbg("62.5 Khz freq step selected for TV.\n"); t->tv_freq(c,freq); } @@ -105,11 +119,29 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq) return; } if (freq < radio_range[0]*16 || freq > radio_range[1]*16) { - tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n", + if (freq >= tv_range[0]*16364 && freq <= tv_range[1]*16384) { + /* V4L2_TUNER_CAP_LOW frequency */ + if (t->type == TUNER_TEA5767) { + tuner_info("radio freq step 62.5Hz (%d.%06d)\n",(freq>>14),freq%(1<<14)*10000); + t->radio_freq(c,freq>>10); + return; + } + + tuner_dbg("V4L2_TUNER_CAP_LOW freq selected for Radio. Tuners yet doesn't support converting it to valid freq.\n"); + + tuner_info("radio freq (%d.%06d)\n",(freq>>14),freq%(1<<14)*10000); + + t->radio_freq(c,freq>>10); + return; + + } else { + tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n", freq/16,freq%16*100/16, - radio_range[0],radio_range[1]); - return; + radio_range[0],radio_range[1]); + return; + } } + tuner_dbg("62.5 Khz freq step selected for Radio.\n"); t->radio_freq(c,freq); } @@ -133,34 +165,13 @@ static void set_freq(struct i2c_client *c, unsigned long freq) t->freq = freq; } -#ifdef CONFIG_TUNER_MULTI_I2C -static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr) -{ - struct tuner *t = i2c_get_clientdata(c); - - switch (tun_addr->type) { - case V4L2_TUNER_RADIO: - radio_tuner=tun_addr->addr; - tuner_dbg("radio tuner set to I2C address 0x%02x\n",radio_tuner<<1); - - break; - default: - tv_tuner=tun_addr->addr; - tuner_dbg("TV tuner set to I2C address 0x%02x\n",tv_tuner<<1); - break; - } -} -#else -#define set_addr(c,tun_addr) \ - tuner_warn("It is recommended to enable CONFIG_TUNER_MULTI_I2C for this card.\n"); -#endif - static void set_type(struct i2c_client *c, unsigned int type) { struct tuner *t = i2c_get_clientdata(c); + tuner_dbg ("I2C addr 0x%02x with type %d\n",c->addr<<1,type); /* sanity check */ - if (type == UNSET || type == TUNER_ABSENT) + if (type == UNSET || type == TUNER_ABSENT) return; if (type >= tuner_count) return; @@ -175,6 +186,7 @@ static void set_type(struct i2c_client *c, unsigned int type) return; t->initialized = 1; + t->type = type; switch (t->type) { case TUNER_MT2032: @@ -189,6 +201,53 @@ static void set_type(struct i2c_client *c, unsigned int type) } } +#ifdef CONFIG_TUNER_MULTI_I2C +#define CHECK_ADDR(tp,cmd,tun) if (client->addr!=tp) { \ + return 0; } else \ + tuner_info ("Cmd %s accepted to "tun"\n",cmd); +#define CHECK_MODE(cmd) if (t->mode == V4L2_TUNER_RADIO) { \ + CHECK_ADDR(radio_tuner,cmd,"radio") } else \ + { CHECK_ADDR(tv_tuner,cmd,"TV"); } +#else +#define CHECK_ADDR(tp,cmd,tun) tuner_info ("Cmd %s accepted to "tun"\n",cmd); +#define CHECK_MODE(cmd) tuner_info ("Cmd %s accepted\n",cmd); +#endif + +#ifdef CONFIG_TUNER_MULTI_I2C + +static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr) +{ + /* ADDR_UNSET defaults to first available tuner */ + if ( tun_addr->addr == ADDR_UNSET ) { + if (first_tuner != c->addr) + return; + switch (tun_addr->v4l2_tuner) { + case V4L2_TUNER_RADIO: + radio_tuner=c->addr; + break; + default: + tv_tuner=c->addr; + break; + } + } else { + /* Sets tuner to its configured value */ + switch (tun_addr->v4l2_tuner) { + case V4L2_TUNER_RADIO: + radio_tuner=tun_addr->addr; + if ( tun_addr->addr == c->addr ) set_type(c,tun_addr->type); + return; + default: + tv_tuner=tun_addr->addr; + if ( tun_addr->addr == c->addr ) set_type(c,tun_addr->type); + return; + } + } + set_type(c,tun_addr->type); +} +#else +#define set_addr(c,tun_addr) set_type(c,(tun_addr)->type) +#endif + static char pal[] = "-"; module_param_string(pal, pal, sizeof(pal), 0644); @@ -233,6 +292,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) #else /* by default, first I2C card is both tv and radio tuner */ if (this_adap == 0) { + first_tuner = addr; tv_tuner = addr; radio_tuner = addr; } @@ -249,11 +309,12 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) memcpy(&t->i2c,&client_template,sizeof(struct i2c_client)); i2c_set_clientdata(&t->i2c, t); t->type = UNSET; - t->radio_if2 = 10700*1000; // 10.7MHz - FM radio + t->radio_if2 = 10700*1000; /* 10.7MHz - FM radio */ i2c_attach_client(&t->i2c); tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name); + set_type(&t->i2c, t->type); return 0; } @@ -261,12 +322,14 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) static int tuner_probe(struct i2c_adapter *adap) { if (0 != addr) { - normal_i2c[0] = addr; - normal_i2c[1] = I2C_CLIENT_END; + normal_i2c[0] = addr; + normal_i2c_range[0] = addr; + normal_i2c_range[1] = addr; } this_adap = 0; #ifdef CONFIG_TUNER_MULTI_I2C + first_tuner = 0; tv_tuner = 0; radio_tuner = 0; #endif @@ -298,17 +361,6 @@ static int tuner_detach(struct i2c_client *client) tuner_info("ignore v4l1 call\n"); \ return 0; } -#ifdef CONFIG_TUNER_MULTI_I2C -#define CHECK_ADDR(tp,cmd) if (client->addr!=tp) { \ - tuner_info ("Cmd %s to addr 0x%02x rejected.\n",cmd,client->addr<<1); \ - return 0; } -#define CHECK_MODE(cmd) if (t->mode == V4L2_TUNER_RADIO) { \ - CHECK_ADDR(radio_tuner,cmd) } else { CHECK_ADDR(tv_tuner,cmd); } -#else -#define CHECK_ADDR(tp,cmd) -#define CHECK_MODE(cmd) -#endif - static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { @@ -320,19 +372,19 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) case TUNER_SET_TYPE: set_type(client,*iarg); break; - case TUNER_SET_ADDR: + case TUNER_SET_TYPE_ADDR: set_addr(client,(struct tuner_addr *)arg); break; case AUDC_SET_RADIO: - CHECK_ADDR(radio_tuner,"AUDC_SET_RADIO"); + t->mode = V4L2_TUNER_RADIO; + CHECK_ADDR(tv_tuner,"AUDC_SET_RADIO","TV"); if (V4L2_TUNER_RADIO != t->mode) { set_tv_freq(client,400 * 16); - t->mode = V4L2_TUNER_RADIO; } break; case AUDC_CONFIG_PINNACLE: - CHECK_ADDR(tv_tuner,"AUDC_CONFIG_PINNACLE"); + CHECK_ADDR(tv_tuner,"AUDC_CONFIG_PINNACLE","TV"); switch (*iarg) { case 2: tuner_dbg("pinnacle pal\n"); @@ -360,9 +412,10 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) }; struct video_channel *vc = arg; - CHECK_ADDR(tv_tuner,"VIDIOCSCHAN"); CHECK_V4L2; t->mode = V4L2_TUNER_ANALOG_TV; + CHECK_ADDR(tv_tuner,"VIDIOCSCHAN","TV"); + if (vc->norm < ARRAY_SIZE(map)) t->std = map[vc->norm]; tuner_fixup_std(t); @@ -383,17 +436,27 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct video_tuner *vt = arg; - CHECK_ADDR(radio_tuner,"VIDIOCGTUNER:"); + CHECK_ADDR(radio_tuner,"VIDIOCGTUNER","radio"); CHECK_V4L2; - if (V4L2_TUNER_RADIO == t->mode && t->has_signal) - vt->signal = t->has_signal(client); + if (V4L2_TUNER_RADIO == t->mode) { + if (t->has_signal) + vt->signal = t->has_signal(client); + if (t->is_stereo) { + if (t->is_stereo(client)) + vt-> flags |= VIDEO_TUNER_STEREO_ON; + else + vt-> flags &= 0xffff ^ VIDEO_TUNER_STEREO_ON; + } + vt->flags |= V4L2_TUNER_CAP_LOW; /* Allow freqs at 62.5 Hz */ + } + return 0; } case VIDIOCGAUDIO: { struct video_audio *va = arg; - CHECK_ADDR(radio_tuner,"VIDIOCGAUDIO"); + CHECK_ADDR(radio_tuner,"VIDIOCGAUDIO","radio"); CHECK_V4L2; if (V4L2_TUNER_RADIO == t->mode && t->is_stereo) va->mode = t->is_stereo(client) @@ -406,9 +469,10 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { v4l2_std_id *id = arg; - CHECK_ADDR(tv_tuner,"VIDIOC_S_STD"); SWITCH_V4L2; t->mode = V4L2_TUNER_ANALOG_TV; + CHECK_ADDR(tv_tuner,"VIDIOC_S_STD","TV"); + t->std = *id; tuner_fixup_std(t); if (t->freq) @@ -444,13 +508,27 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) CHECK_MODE("VIDIOC_G_TUNER"); SWITCH_V4L2; - if (V4L2_TUNER_RADIO == t->mode && t->has_signal) - tuner->signal = t->has_signal(client); + if (V4L2_TUNER_RADIO == t->mode) { + if (t->has_signal) + tuner -> signal = t->has_signal(client); + if (t->is_stereo) { + if (t->is_stereo(client)) { + tuner -> capability |= V4L2_TUNER_CAP_STEREO; + tuner -> rxsubchans |= V4L2_TUNER_SUB_STEREO; + } else { + tuner -> rxsubchans &= 0xffff ^ V4L2_TUNER_SUB_STEREO; + } + } + } + /* Wow to deal with V4L2_TUNER_CAP_LOW ? For now, it accepts from low at 62.5KHz step to high at 62.5 Hz */ tuner->rangelow = tv_range[0] * 16; - tuner->rangehigh = tv_range[1] * 16; +// tuner->rangehigh = tv_range[1] * 16; +// tuner->rangelow = tv_range[0] * 16384; + tuner->rangehigh = tv_range[1] * 16384; break; } default: + tuner_dbg ("Unimplemented IOCTL 0x%08x called to tuner.\n", cmd); /* nothing */ break; } @@ -458,7 +536,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } -static int tuner_suspend(struct device * dev, pm_message_t state, u32 level) +static int tuner_suspend(struct device * dev, u32 state, u32 level) { struct i2c_client *c = container_of(dev, struct i2c_client, dev); struct tuner *t = i2c_get_clientdata(c); diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 866f18dc5b58..539f30557317 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -1,5 +1,5 @@ /* - * $Id: tuner-simple.c,v 1.14 2005/05/30 02:02:47 mchehab Exp $ + * $Id: tuner-simple.c,v 1.21 2005/06/10 19:53:26 nsh Exp $ * * i2c tv tuner chip device driver * controls all those simple 4-control-bytes style tuners. @@ -220,7 +220,17 @@ static struct tunertype tuners[] = { { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC, 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732}, + { "Tena TNF9533-D/IF", LGINNOTEK, PAL, + 16*160.25, 16*464.25, 0x01,0x02,0x08,0x8e,623}, + + /* + * This entry is for TEA5767 FM radio only chip used on several boards + * w/TV tuner + */ + { TEA5767_TUNER_NAME, Philips, RADIO, + -1, -1, 0, 0, 0, TEA5767_LOW_LO_32768,0}, }; + unsigned const int tuner_count = ARRAY_SIZE(tuners); /* ---------------------------------------------------------------------- */ @@ -231,6 +241,7 @@ static int tuner_getstatus(struct i2c_client *c) if (1 != i2c_master_recv(c,&byte,1)) return 0; + return byte; } @@ -239,17 +250,33 @@ static int tuner_getstatus(struct i2c_client *c) #define TUNER_MODE 0x38 #define TUNER_AFC 0x07 -#define TUNER_STEREO 0x10 /* radio mode */ -#define TUNER_SIGNAL 0x07 /* radio mode */ +#define TUNER_STEREO 0x10 /* radio mode */ +#define TUNER_STEREO_MK3 0x04 /* radio mode */ +#define TUNER_SIGNAL 0x07 /* radio mode */ static int tuner_signal(struct i2c_client *c) { - return (tuner_getstatus(c) & TUNER_SIGNAL)<<13; + return (tuner_getstatus(c) & TUNER_SIGNAL) << 13; } static int tuner_stereo(struct i2c_client *c) { - return (tuner_getstatus (c) & TUNER_STEREO); + int stereo, status; + struct tuner *t = i2c_get_clientdata(c); + + status = tuner_getstatus (c); + + switch (t->type) { + case TUNER_PHILIPS_FM1216ME_MK3: + case TUNER_PHILIPS_FM1236_MK3: + case TUNER_PHILIPS_FM1256_IH3: + stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); + break; + default: + stereo = status & TUNER_STEREO; + } + + return stereo; } #if 0 /* unused */ @@ -432,6 +459,7 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) buffer[2] = tun->config; switch (t->type) { + case TUNER_TENA_9533_DI: case TUNER_YMEC_TVF_5533MF: /*These values are empirically determinated */ @@ -473,20 +501,6 @@ int default_tuner_init(struct i2c_client *c) t->type, tuners[t->type].name); strlcpy(c->name, tuners[t->type].name, sizeof(c->name)); - switch (t->type) { - case TUNER_YMEC_TVF_5533MF: - { - struct tuner_addr tun_addr = { V4L2_TUNER_ANALOG_TV, 0xc2>>1 }; - - if (c->driver->command) { - c->driver->command(c, TUNER_SET_ADDR, &tun_addr); - } else { - tuner_warn("Couldn't set TV tuner I2C address to 0x%02x\n",tun_addr.addr<<1); - } - break; - } - } - t->tv_freq = default_set_tv_freq; t->radio_freq = default_set_radio_freq; t->has_signal = tuner_signal; diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 41b635e0d3c6..6f5828a9b80c 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -148,6 +148,7 @@ static unsigned short normal_i2c[] = { I2C_TDA9874 >> 1, I2C_PIC16C54 >> 1, I2C_CLIENT_END }; +static unsigned short normal_i2c_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; static struct i2c_driver driver; @@ -285,7 +286,6 @@ static int chip_thread(void *data) schedule(); } remove_wait_queue(&chip->wq, &wait); - try_to_freeze(PF_FREEZE); if (chip->done || signal_pending(current)) break; dprintk("%s: thread wakeup\n", i2c_clientname(&chip->c)); diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c index eafd7061b310..51b99cdbf29e 100644 --- a/drivers/media/video/tvmixer.c +++ b/drivers/media/video/tvmixer.c @@ -1,3 +1,7 @@ +/* + * $Id: tvmixer.c,v 1.8 2005/06/12 04:19:19 mchehab Exp $ + */ + #include #include #include -- cgit v1.2.2