diff options
author | Mauro Carvalho Chehab <devnull@localhost> | 2005-06-30 09:45:18 +0000 |
---|---|---|
committer | Mauro Carvalho Chehab <devnull@localhost> | 2005-06-30 09:45:18 +0000 |
commit | 29c59c47dfb646d340182b3500486b144ae7c1b7 (patch) | |
tree | 6a942bf8f56144d90f133d13f1b48ef0777b3620 /linux/drivers | |
parent | 8aac71d744339eeaba3b0c83d35ac1cbcddddb4f (diff) | |
download | mediapointer-dvb-s2-29c59c47dfb646d340182b3500486b144ae7c1b7.tar.gz mediapointer-dvb-s2-29c59c47dfb646d340182b3500486b144ae7c1b7.tar.bz2 |
minor changes:
- Idented according with Linux standards
- less verbose when tuner_debug = 0
fixes:
- check_mode debug msg fixed
- out of range debug messages fixed
- bug when changing mode in a multituner environment
new features:
- standby mode support implemented. It is used to disable
a non used tuner. Currenlty implemented on tea5767.
- new macro: set_type disables other tuner when changing mode.
Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
Diffstat (limited to 'linux/drivers')
-rw-r--r-- | linux/drivers/media/video/tea5767.c | 139 | ||||
-rw-r--r-- | linux/drivers/media/video/tuner-core.c | 517 |
2 files changed, 358 insertions, 298 deletions
diff --git a/linux/drivers/media/video/tea5767.c b/linux/drivers/media/video/tea5767.c index 4f28fead0..e4a46ffc2 100644 --- a/linux/drivers/media/video/tea5767.c +++ b/linux/drivers/media/video/tea5767.c @@ -2,7 +2,7 @@ * For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview * I2C address is allways 0xC0. * - * $Id: tea5767.c,v 1.12 2005/06/28 23:41:47 mkrufky Exp $ + * $Id: tea5767.c,v 1.13 2005/06/30 09:45:18 mchehab Exp $ * * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br) * This code is placed under the terms of the GNU General Public License @@ -43,8 +43,8 @@ extern unsigned int tuner_debug; ******************************/ /* First register */ -#define TEA5767_MUTE 0x80 /* Mutes output */ -#define TEA5767_SEARCH 0x40 /* Activates station search */ +#define TEA5767_MUTE 0x80 /* Mutes output */ +#define TEA5767_SEARCH 0x40 /* Activates station search */ /* Bits 0-5 for divider MSB */ /* Second register */ @@ -158,103 +158,120 @@ static void tea5767_status_dump(unsigned char *buffer) else printk(PREFIX "Tuner not at band limit\n"); - div=((buffer[0]&0x3f)<<8) | buffer[1]; + div = ((buffer[0] & 0x3f) << 8) | buffer[1]; switch (TEA5767_HIGH_LO_32768) { case TEA5767_HIGH_LO_13MHz: - frq = 1000*(div*50-700-225)/4; /* Freq in KHz */ + frq = 1000 * (div * 50 - 700 - 225) / 4; /* Freq in KHz */ break; case TEA5767_LOW_LO_13MHz: - frq = 1000*(div*50+700+225)/4; /* Freq in KHz */ + frq = 1000 * (div * 50 + 700 + 225) / 4; /* Freq in KHz */ break; case TEA5767_LOW_LO_32768: - frq = 1000*(div*32768/1000+700+225)/4; /* Freq in KHz */ + frq = 1000 * (div * 32768 / 1000 + 700 + 225) / 4; /* Freq in KHz */ break; case TEA5767_HIGH_LO_32768: default: - frq = 1000*(div*32768/1000-700-225)/4; /* Freq in KHz */ + frq = 1000 * (div * 32768 / 1000 - 700 - 225) / 4; /* Freq in KHz */ break; } - buffer[0] = (div>>8) & 0x3f; - buffer[1] = div & 0xff; + buffer[0] = (div >> 8) & 0x3f; + buffer[1] = div & 0xff; printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n", - frq/1000,frq%1000,div); + frq / 1000, frq % 1000, div); if (TEA5767_STEREO_MASK & buffer[2]) printk(PREFIX "Stereo\n"); else printk(PREFIX "Mono\n"); - printk(PREFIX "IF Counter = %d\n",buffer[2] & TEA5767_IF_CNTR_MASK); + printk(PREFIX "IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK); - printk(PREFIX "ADC Level = %d\n",(buffer[3] & TEA5767_ADC_LEVEL_MASK)>>4); + printk(PREFIX "ADC Level = %d\n", + (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4); - printk(PREFIX "Chip ID = %d\n",(buffer[3] & TEA5767_CHIP_ID_MASK)); + printk(PREFIX "Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK)); - printk(PREFIX "Reserved = 0x%02x\n",(buffer[4] & TEA5767_RESERVED_MASK)); + printk(PREFIX "Reserved = 0x%02x\n", + (buffer[4] & TEA5767_RESERVED_MASK)); } /* Freq should be specifyed at 62.5 Hz */ static void set_radio_freq(struct i2c_client *c, unsigned int frq) { struct tuner *t = i2c_get_clientdata(c); - unsigned char buffer[5]; + unsigned char buffer[5]; unsigned div; int rc; - if ( tuner_debug ) - printk(PREFIX "radio freq counter %d\n",frq); + if (tuner_debug) + printk(PREFIX "radio freq counter %d\n", frq); /* Rounds freq to next decimal value - for 62.5 KHz step */ /* frq = 20*(frq/16)+radio_frq[frq%16]; */ buffer[2] = TEA5767_PORT1_HIGH; - buffer[3] = TEA5767_PORT2_HIGH | TEA5767_HIGH_CUT_CTRL | TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND; - buffer[4]=0; + buffer[3] = TEA5767_PORT2_HIGH | TEA5767_HIGH_CUT_CTRL | + TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND; + buffer[4] = 0; + + if (t->mode & T_STANDBY) { + if (tuner_debug) + tuner_dbg("TEA5767 set to standby mode\n"); + buffer[3] |= TEA5767_STDBY; + } if (t->audmode == V4L2_TUNER_MODE_MONO) { - tuner_dbg("TEA5767 set to mono\n"); + if (tuner_debug) + tuner_dbg("TEA5767 set to mono\n"); buffer[2] |= TEA5767_MONO; - } else - tuner_dbg("TEA5767 set to stereo\n"); + } else { + if (tuner_debug) + tuner_dbg("TEA5767 set to stereo\n"); + } - switch (t->type) { + /* Should be replaced */ + switch (TEA5767_HIGH_LO_32768) { case TEA5767_HIGH_LO_13MHz: - tuner_dbg("TEA5767 radio HIGH LO inject xtal @ 13 MHz\n"); + if (tuner_debug) + tuner_dbg ("TEA5767 radio HIGH LO inject xtal @ 13 MHz\n"); buffer[2] |= TEA5767_HIGH_LO_INJECT; buffer[4] |= TEA5767_PLLREF_ENABLE; - div = (frq*4/16+700+225+25)/50; + div = (frq * 4 / 16 + 700 + 225 + 25) / 50; break; case TEA5767_LOW_LO_13MHz: - tuner_dbg("TEA5767 radio LOW LO inject xtal @ 13 MHz\n"); + if (tuner_debug) + tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 13 MHz\n"); buffer[4] |= TEA5767_PLLREF_ENABLE; - div = (frq*4/16-700-225+25)/50; + div = (frq * 4 / 16 - 700 - 225 + 25) / 50; break; case TEA5767_LOW_LO_32768: - tuner_dbg("TEA5767 radio LOW LO inject xtal @ 32,768 MHz\n"); + if (tuner_debug) + tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 32,768 MHz\n"); buffer[3] |= TEA5767_XTAL_32768; /* const 700=4000*175 Khz - to adjust freq to right value */ - div = (1000*(frq*4/16-700-225)+16384)>>15; + div = (1000 * (frq * 4 / 16 - 700 - 225) + 16384) >> 15; break; case TEA5767_HIGH_LO_32768: default: - tuner_dbg("TEA5767 radio HIGH LO inject xtal @ 32,768 MHz\n"); + if (tuner_debug) + tuner_dbg ("TEA5767 radio HIGH LO inject xtal @ 32,768 MHz\n"); buffer[2] |= TEA5767_HIGH_LO_INJECT; buffer[3] |= TEA5767_XTAL_32768; - div = (1000*(frq*4/16+700+225)+16384)>>15; + div = (1000 * (frq * 4 / 16 + 700 + 225) + 16384) >> 15; break; } - buffer[0] = (div>>8) & 0x3f; - buffer[1] = div & 0xff; + buffer[0] = (div >> 8) & 0x3f; + buffer[1] = div & 0xff; - if ( tuner_debug ) + if (tuner_debug) tea5767_status_dump(buffer); - if (5 != (rc = i2c_master_send(c,buffer,5))) - tuner_warn("i2c i/o error: rc == %d (should be 5)\n",rc); + if (5 != (rc = i2c_master_send(c, buffer, 5))) + tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); } static int tea5767_signal(struct i2c_client *c) @@ -263,11 +280,11 @@ static int tea5767_signal(struct i2c_client *c) int rc; struct tuner *t = i2c_get_clientdata(c); - memset(buffer,0,sizeof(buffer)); - if (5 != (rc = i2c_master_recv(c,buffer,5))) - tuner_warn ( "i2c i/o error: rc == %d (should be 5)\n",rc); + memset(buffer, 0, sizeof(buffer)); + if (5 != (rc = i2c_master_recv(c, buffer, 5))) + tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); - return ((buffer[3] & TEA5767_ADC_LEVEL_MASK) <<(13-4)); + return ((buffer[3] & TEA5767_ADC_LEVEL_MASK) << (13 - 4)); } static int tea5767_stereo(struct i2c_client *c) @@ -276,47 +293,47 @@ static int tea5767_stereo(struct i2c_client *c) int rc; struct tuner *t = i2c_get_clientdata(c); - memset(buffer,0,sizeof(buffer)); - if (5 != (rc = i2c_master_recv(c,buffer,5))) - tuner_warn ( "i2c i/o error: rc == %d (should be 5)\n",rc); + memset(buffer, 0, sizeof(buffer)); + if (5 != (rc = i2c_master_recv(c, buffer, 5))) + tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); rc = buffer[2] & TEA5767_STEREO_MASK; - if ( tuner_debug ) + if (tuner_debug) tuner_dbg("TEA5767 radio ST GET = %02x\n", rc); - return ( (buffer[2] & TEA5767_STEREO_MASK) ? V4L2_TUNER_SUB_STEREO: 0); + return ((buffer[2] & TEA5767_STEREO_MASK) ? V4L2_TUNER_SUB_STEREO : 0); } int tea_detection(struct i2c_client *c) { - unsigned char buffer[5]= { 0xff, 0xff, 0xff, 0xff, 0xff }; + unsigned char buffer[5] = { 0xff, 0xff, 0xff, 0xff, 0xff }; int rc; struct tuner *t = i2c_get_clientdata(c); - if (5 != (rc = i2c_master_recv(c,buffer,5))) { - tuner_warn ( "it is not a TEA5767. Received %i chars.\n",rc ); + if (5 != (rc = i2c_master_recv(c, buffer, 5))) { + tuner_warn("it is not a TEA5767. Received %i chars.\n", rc); return EINVAL; } /* If all bytes are the same then it's a TV tuner and not a tea5767 chip. */ - if (buffer[0] == buffer[1] && buffer[0] == buffer[2] && - buffer[0] == buffer[3] && buffer[0] == buffer[4]) { - tuner_warn ( "All bytes are equal. It is not a TEA5767\n" ); + if (buffer[0] == buffer[1] && buffer[0] == buffer[2] && + buffer[0] == buffer[3] && buffer[0] == buffer[4]) { + tuner_warn("All bytes are equal. It is not a TEA5767\n"); return EINVAL; } /* Status bytes: * Byte 4: bit 3:1 : CI (Chip Identification) == 0 - * bit 0 : internally set to 0 + * bit 0 : internally set to 0 * Byte 5: bit 7:0 : == 0 */ if (!((buffer[3] & 0x0f) == 0x00) && (buffer[4] == 0x00)) { - tuner_warn ( "Chip ID is not zero. It is not a TEA5767\n" ); + tuner_warn("Chip ID is not zero. It is not a TEA5767\n"); return EINVAL; } - tuner_warn ( "TEA5767 detected.\n" ); + tuner_warn("TEA5767 detected.\n"); return 0; } @@ -324,16 +341,16 @@ int tea5767_tuner_init(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); - if (tea_detection(c)==EINVAL) return EINVAL; + if (tea_detection(c) == EINVAL) + return EINVAL; - tuner_info("type set to %d (%s)\n", - t->type, TEA5767_TUNER_NAME); - strlcpy(c->name, TEA5767_TUNER_NAME, sizeof(c->name)); + tuner_info("type set to %d (%s)\n", t->type, TEA5767_TUNER_NAME); + strlcpy(c->name, TEA5767_TUNER_NAME, sizeof(c->name)); - t->tv_freq = set_tv_freq; + t->tv_freq = set_tv_freq; t->radio_freq = set_radio_freq; t->has_signal = tea5767_signal; - t->is_stereo = tea5767_stereo; + t->is_stereo = tea5767_stereo; return (0); } diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 78f2c336c..74f216dd6 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -1,5 +1,5 @@ /* - * $Id: tuner-core.c,v 1.31 2005/06/30 02:41:56 mchehab Exp $ + * $Id: tuner-core.c,v 1.32 2005/06/30 09:45:18 mchehab Exp $ * * i2c tv tuner chip device driver * core core, i.e. kernel interfaces, registering and so on @@ -32,33 +32,34 @@ /* standard i2c insmod options */ static unsigned short normal_i2c[] = { - 0x4b, /* tda8290 */ + 0x4b, /* tda8290 */ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, I2C_CLIENT_END }; + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; #endif I2C_CLIENT_INSMOD; /* insmod options used at init time => read/only */ -static unsigned int addr = 0; +static unsigned int addr = 0; module_param(addr, int, 0444); /* insmod options used at runtime => read/write */ -unsigned int tuner_debug = 0; -module_param(tuner_debug, int, 0644); +unsigned int tuner_debug = 0; +module_param(tuner_debug, int, 0644); -static unsigned int tv_range[2] = { 44, 958 }; +static unsigned int tv_range[2] = { 44, 958 }; static unsigned int radio_range[2] = { 65, 108 }; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) static unsigned int dummy; -module_param_array(tv_range, int, dummy, 0644); +module_param_array(tv_range, int, dummy, 0644); module_param_array(radio_range, int, dummy, 0644); #else -module_param_array(tv_range, int, NULL, 0644); +module_param_array(tv_range, int, NULL, 0644); module_param_array(radio_range, int, NULL, 0644); #endif @@ -84,11 +85,12 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) tuner_info("Huh? tv_set is NULL?\n"); return; } - if (freq < tv_range[0]*16 || freq > tv_range[1]*16) { - tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n", - freq/16,freq%16*100/16,tv_range[0],tv_range[1]); + if (freq < tv_range[0] * 16 || freq > tv_range[1] * 16) { + tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n", + freq / 16, freq % 16 * 100 / 16, tv_range[0], + tv_range[1]); } - t->tv_freq(c,freq); + t->tv_freq(c, freq); } static void set_radio_freq(struct i2c_client *c, unsigned int freq) @@ -103,15 +105,15 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq) tuner_info("no radio tuning for this one, sorry.\n"); return; } - if (freq >= radio_range[0]*16000 && freq <= radio_range[1]*16000) { + if (freq >= radio_range[0] * 16000 && freq <= radio_range[1] * 16000) { if (tuner_debug) tuner_info("radio freq step 62.5Hz (%d.%06d)\n", - freq/16000,freq%16000*1000/16); - t->radio_freq(c,freq); - } else { + freq / 16000, freq % 16000 * 1000 / 16); + t->radio_freq(c, freq); + } 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]); + freq / 16000, freq % 16000 * 100 / 16000, + radio_range[0], radio_range[1]); } return; @@ -124,20 +126,21 @@ static void set_freq(struct i2c_client *c, unsigned long freq) switch (t->mode) { case V4L2_TUNER_RADIO: tuner_dbg("radio freq set to %lu.%02lu\n", - freq/16,freq%16*100/16); - set_radio_freq(c,freq); + freq / 16000, freq % 16000 * 100 / 16000); + set_radio_freq(c, freq); break; case V4L2_TUNER_ANALOG_TV: case V4L2_TUNER_DIGITAL_TV: tuner_dbg("tv freq set to %lu.%02lu\n", - freq/16,freq%16*100/16); + freq / 16, freq % 16 * 100 / 16); set_tv_freq(c, freq); break; } t->freq = freq; } -static void set_type(struct i2c_client *c, unsigned int type, enum tuner_admin_state new_admin_status) +static void set_type(struct i2c_client *c, unsigned int type, + enum tuner_admin_state new_admin_status) { struct tuner *t = i2c_get_clientdata(c); unsigned char buffer[4]; @@ -165,7 +168,7 @@ static void set_type(struct i2c_client *c, unsigned int type, enum tuner_admin_s tda8290_init(c); break; case TUNER_TEA5767: - if (tea5767_tuner_init(c)==EINVAL) { + if (tea5767_tuner_init(c) == EINVAL) { t->type = TUNER_ABSENT; t->admin_status = T_UNINITIALIZED; return; @@ -177,11 +180,11 @@ static void set_type(struct i2c_client *c, unsigned int type, enum tuner_admin_s buffer[1] = 0xdc; buffer[2] = 0x9c; buffer[3] = 0x60; - i2c_master_send(c,buffer,4); + i2c_master_send(c, buffer, 4); mdelay(1); buffer[2] = 0x86; buffer[3] = 0x54; - i2c_master_send(c,buffer,4); + i2c_master_send(c, buffer, 4); default_tuner_init(c); break; default: @@ -191,8 +194,9 @@ static void set_type(struct i2c_client *c, unsigned int type, enum tuner_admin_s if (t->admin_status == T_UNINITIALIZED) t->admin_status = new_admin_status; - tuner_dbg ("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n", - c->adapter->name,c->driver->name,c->addr<<1,type,t->admin_status); + tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n", + c->adapter->name, c->driver->name, c->addr << 1, type, + t->admin_status); } static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr) @@ -201,32 +205,35 @@ static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr) enum tuner_admin_state new_admin_status; /* ADDR_UNSET defaults to first available tuner */ - if ( tun_addr->addr == ADDR_UNSET ) { + if (tun_addr->addr == ADDR_UNSET) { /* If no Address specifyed, accepts only if tuner is */ - if ( !(t->admin_status & tun_addr->v4l2_tuner) ) + if (!(t->admin_status & tun_addr->v4l2_tuner)) return; - set_type(c,tun_addr->type,tun_addr->v4l2_tuner); + set_type(c, tun_addr->type, tun_addr->v4l2_tuner); } else { new_admin_status = tun_addr->v4l2_tuner; /* Sets tuner to its configured value */ - if ( tun_addr->addr == c->addr ) set_type(c,tun_addr->type,new_admin_status); + if (tun_addr->addr == c->addr) + set_type(c, tun_addr->type, new_admin_status); } } -static inline int check_mode (struct tuner *t,char *cmd) +static inline int check_mode(struct tuner *t, char *cmd) { - if (1<<t->mode & t->admin_status) { + if (1 << t->mode & t->admin_status) { if (tuner_debug) { - switch (t->type) { + switch (t->mode) { case V4L2_TUNER_RADIO: - tuner_info ("Cmd %s accepted for radio\n",cmd); + tuner_dbg("Cmd %s accepted for radio\n", cmd); break; case V4L2_TUNER_ANALOG_TV: - tuner_info ("Cmd %s accepted for analog TV\n",cmd); + tuner_dbg("Cmd %s accepted for analog TV\n", + cmd); break; case V4L2_TUNER_DIGITAL_TV: - tuner_info ("Cmd %s accepted for digital TV\n",cmd); + tuner_dbg("Cmd %s accepted for digital TV\n", + cmd); break; } } @@ -286,30 +293,29 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) { struct tuner *t; - client_template.adapter = adap; - client_template.addr = addr; + client_template.adapter = adap; + client_template.addr = addr; - t = kmalloc(sizeof(struct tuner),GFP_KERNEL); - if (NULL == t) - return -ENOMEM; - memset(t,0,sizeof(struct tuner)); - memcpy(&t->i2c,&client_template,sizeof(struct i2c_client)); + t = kmalloc(sizeof(struct tuner), GFP_KERNEL); + if (NULL == t) + return -ENOMEM; + memset(t, 0, sizeof(struct tuner)); + 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->audmode = V4L2_TUNER_MODE_STEREO; + t->type = UNSET; + t->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */ + t->audmode = V4L2_TUNER_MODE_STEREO; t->admin_status = T_UNINITIALIZED; - i2c_attach_client(&t->i2c); - tuner_info("chip found @ 0x%x (%s)\n", - addr << 1, adap->name); + i2c_attach_client(&t->i2c); + tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name); /* TEA5767 autodetection code - only for addr = 0xc0 */ - if ( addr == 0x60) { - set_type(&t->i2c, TUNER_TEA5767 ,T_RADIO); - if (t->type==TUNER_TEA5767) { + if (addr == 0x60) { + set_type(&t->i2c, TUNER_TEA5767, T_RADIO); + if (t->type == TUNER_TEA5767) { t->type = TUNER_TEA5767; - t->admin_status = T_RADIO; + t->admin_status = T_RADIO|T_STANDBY; default_admin_status &= ~T_RADIO; return 0; } @@ -317,7 +323,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) /* Initializes only the first adapter found */ if (default_admin_status != T_UNINITIALIZED) { - tuner_dbg("admin to card = 0x%02x\n",default_admin_status); + tuner_dbg("admin to card = 0x%02x\n", default_admin_status); t->admin_status = default_admin_status; default_admin_status = T_UNINITIALIZED; } @@ -344,9 +350,10 @@ static int tuner_detach(struct i2c_client *client) struct tuner *t = i2c_get_clientdata(client); int err; - err=i2c_detach_client(&t->i2c); + err = i2c_detach_client(&t->i2c); if (err) { - tuner_warn ("Client deregistration failed, client not detached.\n"); + tuner_warn + ("Client deregistration failed, client not detached.\n"); return err; } @@ -354,45 +361,66 @@ static int tuner_detach(struct i2c_client *client) return 0; } +static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, char *cmd) +{ + int freq; + + if (mode != t->mode) { + t->mode = mode; + /* If TV/Radio tuners are separate, put the other tuner in standby mode*/ + if (check_mode(t, cmd) == EINVAL) { + t->admin_status |= T_STANDBY; + if (V4L2_TUNER_RADIO == mode) { + freq=400 * 16; /* Why 400 MHz? */ + set_tv_freq(client, freq); + } else { + freq=87.5 * 16000; /* Is it the better value? */ + set_radio_freq(client, freq); + } + + return EINVAL; + } else { + /* Disables standby mode */ + t->admin_status &= ~T_STANDBY; + set_freq (client, t->freq); + } + } + return 0; +} + #define switch_v4l2() if (!t->using_v4l2 && tuner_debug) \ tuner_info("switching to v4l2\n"); \ t->using_v4l2 = 1; -static inline int check_v4l2 (struct tuner *t) +static inline int check_v4l2(struct tuner *t) { if (t->using_v4l2) { if (tuner_debug) - tuner_info("ignore v4l1 call\n"); + tuner_info("ignore v4l1 call\n"); return EINVAL; } return 0; } -static int -tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) +static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct tuner *t = i2c_get_clientdata(client); - unsigned int *iarg = (int*)arg; + unsigned int *iarg = (int *)arg; - switch (cmd) { - /* --- configuration --- */ + switch (cmd) { + /* --- configuration --- */ case TUNER_SET_TYPE: - set_type(client, *iarg,T_RADIO|T_ANALOG_TV|T_DIGITAL_TV); + set_type(client, *iarg, T_RADIO | T_ANALOG_TV | T_DIGITAL_TV); break; case TUNER_SET_TYPE_ADDR: - set_addr(client,(struct tuner_addr *)arg); + set_addr(client, (struct tuner_addr *)arg); break; case AUDC_SET_RADIO: - /* if (check_mode(t,"AUDC_SET_RADIO")==EINVAL) return 0; */ - - if (V4L2_TUNER_RADIO != t->mode) { - set_tv_freq(client,400 * 16); - } - t->mode = V4L2_TUNER_RADIO; - + set_mode(client,t,V4L2_TUNER_RADIO, "AUDC_SET_RADIO"); break; case AUDC_CONFIG_PINNACLE: - if (check_mode(t,"AUDC_CONFIG_PINNACLE")==EINVAL) return 0; + if (check_mode(t, "AUDC_CONFIG_PINNACLE") == EINVAL) + return 0; switch (*iarg) { case 2: tuner_dbg("pinnacle pal\n"); @@ -404,178 +432,194 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } break; - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ + /* --- v4l ioctls --- */ + /* take care: bttv does userspace copying, we'll get a + kernel pointer here... */ case VIDIOCSCHAN: - { - static const v4l2_std_id map[] = { - [ VIDEO_MODE_PAL ] = V4L2_STD_PAL, - [ VIDEO_MODE_NTSC ] = V4L2_STD_NTSC_M, - [ VIDEO_MODE_SECAM ] = V4L2_STD_SECAM, - [ 4 /* bttv */ ] = V4L2_STD_PAL_M, - [ 5 /* bttv */ ] = V4L2_STD_PAL_N, - [ 6 /* bttv */ ] = V4L2_STD_NTSC_M_JP, - }; - struct video_channel *vc = arg; - - if (check_v4l2(t)==EINVAL) return 0; - - t->mode = V4L2_TUNER_ANALOG_TV; - if (check_mode(t,"VIDIOCSCHAN")==EINVAL) return 0; - - if (vc->norm < ARRAY_SIZE(map)) - t->std = map[vc->norm]; - tuner_fixup_std(t); - if (t->freq) - set_tv_freq(client,t->freq); - return 0; - } + { + static const v4l2_std_id map[] = { + [VIDEO_MODE_PAL] = V4L2_STD_PAL, + [VIDEO_MODE_NTSC] = V4L2_STD_NTSC_M, + [VIDEO_MODE_SECAM] = V4L2_STD_SECAM, + [4 /* bttv */ ] = V4L2_STD_PAL_M, + [5 /* bttv */ ] = V4L2_STD_PAL_N, + [6 /* bttv */ ] = V4L2_STD_NTSC_M_JP, + }; + struct video_channel *vc = arg; + + if (check_v4l2(t) == EINVAL) + return 0; + + if (set_mode(client,t,V4L2_TUNER_ANALOG_TV, "VIDIOCSCHAN")==EINVAL) + return 0; + + if (vc->norm < ARRAY_SIZE(map)) + t->std = map[vc->norm]; + tuner_fixup_std(t); + if (t->freq) + set_tv_freq(client, t->freq); + return 0; + } case VIDIOCSFREQ: - { - unsigned long *v = arg; + { + unsigned long *v = arg; - if (check_mode(t,"VIDIOCSFREQ")==EINVAL) return 0; - if (check_v4l2(t)==EINVAL) return 0; + if (check_mode(t, "VIDIOCSFREQ") == EINVAL) + return 0; + if (check_v4l2(t) == EINVAL) + return 0; - set_freq(client,*v); - return 0; - } + set_freq(client, *v); + return 0; + } case VIDIOCGTUNER: - { - struct video_tuner *vt = arg; - - if (check_mode(t,"VIDIOCGTUNER")==EINVAL) return 0; - if (check_v4l2(t)==EINVAL) return 0; - - 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 &= ~VIDEO_TUNER_STEREO_ON; - } - vt->flags |= V4L2_TUNER_CAP_LOW; /* Allow freqs at 62.5 Hz */ + { + struct video_tuner *vt = arg; + + if (check_mode(t, "VIDIOCGTUNER") == EINVAL) + return 0; + if (check_v4l2(t) == EINVAL) + return 0; + + 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 &= + ~VIDEO_TUNER_STEREO_ON; + } + vt->flags |= V4L2_TUNER_CAP_LOW; /* Allow freqs at 62.5 Hz */ - vt->rangelow = radio_range[0] * 16000; - vt->rangehigh = radio_range[1] * 16000; + vt->rangelow = radio_range[0] * 16000; + vt->rangehigh = radio_range[1] * 16000; - } else { - vt->rangelow = tv_range[0] * 16; - vt->rangehigh = tv_range[1] * 16; - } + } else { + vt->rangelow = tv_range[0] * 16; + vt->rangehigh = tv_range[1] * 16; + } - return 0; - } + return 0; + } case VIDIOCGAUDIO: - { - struct video_audio *va = arg; + { + struct video_audio *va = arg; - if (check_mode(t,"VIDIOCGAUDIO")==EINVAL) return 0; - if (check_v4l2(t)==EINVAL) return 0; + if (check_mode(t, "VIDIOCGAUDIO") == EINVAL) + return 0; + if (check_v4l2(t) == EINVAL) + return 0; - if (V4L2_TUNER_RADIO == t->mode && t->is_stereo) - va->mode = t->is_stereo(client) - ? VIDEO_SOUND_STEREO - : VIDEO_SOUND_MONO; - return 0; - } + if (V4L2_TUNER_RADIO == t->mode && t->is_stereo) + va->mode = t->is_stereo(client) + ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; + return 0; + } case VIDIOC_S_STD: - { - v4l2_std_id *id = arg; + { + v4l2_std_id *id = arg; - t->mode = V4L2_TUNER_ANALOG_TV; - if (check_mode(t,"VIDIOC_S_STD")==EINVAL) return 0; + if (set_mode(client,t,V4L2_TUNER_ANALOG_TV, "VIDIOC_S_STD")==EINVAL) + return 0; - switch_v4l2(); + switch_v4l2(); - t->std = *id; - tuner_fixup_std(t); - if (t->freq) - set_freq(client,t->freq); - break; - } + t->std = *id; + tuner_fixup_std(t); + if (t->freq) + set_freq(client, t->freq); + break; + } case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *f = arg; - - if (check_mode(t,"VIDIOC_S_FREQUENCY")==EINVAL) return 0; + { + struct v4l2_frequency *f = arg; + + t->freq = f->frequency; + switch_v4l2(); + if (V4L2_TUNER_RADIO == f->type && + V4L2_TUNER_RADIO != t->mode) { + if (set_mode(client,t,f->type,"VIDIOC_S_FREQUENCY") == EINVAL) + return 0; + } + set_freq(client,t->freq); - switch_v4l2(); - if (V4L2_TUNER_RADIO == f->type && - V4L2_TUNER_RADIO != t->mode) - set_tv_freq(client,400*16); - t->mode = f->type; - set_freq(client,f->frequency); - break; - } + break; + } case VIDIOC_G_FREQUENCY: - { - struct v4l2_frequency *f = arg; - - if (check_mode(t,"VIDIOC_G_FREQUENCY")==EINVAL) return 0; - switch_v4l2(); - f->type = t->mode; - f->frequency = t->freq; - break; - } + { + struct v4l2_frequency *f = arg; + + if (check_mode(t, "VIDIOC_G_FREQUENCY") == EINVAL) + return 0; + switch_v4l2(); + f->type = t->mode; + f->frequency = t->freq; + break; + } case VIDIOC_G_TUNER: - { - struct v4l2_tuner *tuner = arg; - - if (check_mode(t,"VIDIOC_G_TUNER")==EINVAL) return 0; - switch_v4l2(); - 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 -> rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; - } else { - tuner -> rxsubchans = V4L2_TUNER_SUB_MONO; + { + struct v4l2_tuner *tuner = arg; + + if (check_mode(t, "VIDIOC_G_TUNER") == EINVAL) + return 0; + switch_v4l2(); + 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->rxsubchans = + V4L2_TUNER_SUB_STEREO | + V4L2_TUNER_SUB_MONO; + } else { + tuner->rxsubchans = + V4L2_TUNER_SUB_MONO; + } } + tuner->capability |= + V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; + tuner->audmode = t->audmode; + + tuner->rangelow = radio_range[0] * 16000; + tuner->rangehigh = radio_range[1] * 16000; + } else { + tuner->rangelow = tv_range[0] * 16; + tuner->rangehigh = tv_range[1] * 16; } - tuner->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; - tuner->audmode = t->audmode; - - tuner->rangelow = radio_range[0] * 16000; - tuner->rangehigh = radio_range[1] * 16000; - } else { - tuner->rangelow = tv_range[0] * 16; - tuner->rangehigh = tv_range[1] * 16; + break; } - break; - } - case VIDIOC_S_TUNER: /* Allow changing radio range and audio mode */ - { - struct v4l2_tuner *tuner = arg; - - if (check_mode(t,"VIDIOC_S_TUNER")==EINVAL) return 0; - switch_v4l2(); - - /* To switch the audio mode, applications initialize the - index and audmode fields and the reserved array and - call the VIDIOC_S_TUNER ioctl. */ - /* rxsubchannels: V4L2_TUNER_MODE_MONO, V4L2_TUNER_MODE_STEREO, - V4L2_TUNER_MODE_LANG1, V4L2_TUNER_MODE_LANG2, - V4L2_TUNER_MODE_SAP */ - if (V4L2_TUNER_RADIO == t->mode) { - if (tuner->audmode == V4L2_TUNER_MODE_MONO) - t->audmode = V4L2_TUNER_MODE_MONO; - else - t->audmode = V4L2_TUNER_MODE_STEREO; - - set_radio_freq(client, t->freq); + case VIDIOC_S_TUNER: /* Allow changing radio range and audio mode */ + { + struct v4l2_tuner *tuner = arg; + + if (check_mode(t, "VIDIOC_S_TUNER") == EINVAL) + return 0; + switch_v4l2(); + + /* To switch the audio mode, applications initialize the + index and audmode fields and the reserved array and + call the VIDIOC_S_TUNER ioctl. */ + /* rxsubchannels: V4L2_TUNER_MODE_MONO, V4L2_TUNER_MODE_STEREO, + V4L2_TUNER_MODE_LANG1, V4L2_TUNER_MODE_LANG2, + V4L2_TUNER_MODE_SAP */ + if (V4L2_TUNER_RADIO == t->mode) { + if (tuner->audmode == V4L2_TUNER_MODE_MONO) + t->audmode = V4L2_TUNER_MODE_MONO; + else + t->audmode = V4L2_TUNER_MODE_STEREO; + + set_radio_freq(client, t->freq); + } + break; } - break; - } - case TDA9887_SET_CONFIG: /* Nothing to do on tuner-core */ + case TDA9887_SET_CONFIG: /* Nothing to do on tuner-core */ break; default: - tuner_dbg ("Unimplemented IOCTL 0x%08x called to tuner.\n", cmd); + tuner_dbg("Unimplemented IOCTL 0x%08x called to tuner.\n", cmd); /* nothing */ break; } @@ -583,7 +627,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } -static int tuner_suspend(struct device * dev, u32 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); @@ -593,37 +637,36 @@ static int tuner_suspend(struct device * dev, u32 state, u32 level) return 0; } -static int tuner_resume(struct device * dev, u32 level) +static int tuner_resume(struct device *dev, u32 level) { struct i2c_client *c = container_of(dev, struct i2c_client, dev); struct tuner *t = i2c_get_clientdata(c); tuner_dbg("resume\n"); if (t->freq) - set_freq(c,t->freq); + set_freq(c, t->freq); return 0; } /* ----------------------------------------------------------------------- */ static struct i2c_driver driver = { - .owner = THIS_MODULE, - .name = "tuner", - .id = I2C_DRIVERID_TUNER, - .flags = I2C_DF_NOTIFY, - .attach_adapter = tuner_probe, - .detach_client = tuner_detach, - .command = tuner_command, + .owner = THIS_MODULE, + .name = "tuner", + .id = I2C_DRIVERID_TUNER, + .flags = I2C_DF_NOTIFY, + .attach_adapter = tuner_probe, + .detach_client = tuner_detach, + .command = tuner_command, .driver = { - .suspend = tuner_suspend, - .resume = tuner_resume, - }, + .suspend = tuner_suspend, + .resume = tuner_resume, + }, }; -static struct i2c_client client_template = -{ +static struct i2c_client client_template = { I2C_DEVNAME("(tuner unset)"), - .flags = I2C_CLIENT_ALLOW_USE, - .driver = &driver, + .flags = I2C_CLIENT_ALLOW_USE, + .driver = &driver, }; static int __init tuner_init_module(void) |