Hi, vidiocstuner-patch fixes broken v4l2 tv sound selection. At least msp3400 dislikes any empty video_audio fields. audiohook-patch is work-in-progress. It is what I currently run, running with ~1 MHz i2c clock and i2c-algo-biths from CVS. It also moves btv->audio_hooks within btv_call_i2c_clients, renamed btv_call_clients now. Sometimes sound does not unmute after tune.. Let me know what you think, I'll clean it up once new i2c is stabilized. BTW: i2c CVS has gone out-of-sync with 2.5.x changes, hopefully we get this fixed within a week. -- Kyösti Mälkki kmalkki@xxxxxxxxx
Only in orig/bttv-0.9.3/: .bp.2.5.30_bttv-0.9.x Only in orig/bttv-0.9.3/: .bp.20_videobuf diff -ur orig/bttv-0.9.3/bttv-cards.c bttv-0.9.3/bttv-cards.c --- orig/bttv-0.9.3/bttv-cards.c Tue Dec 10 22:45:40 2002 +++ bttv-0.9.3/bttv-cards.c Sat Dec 28 21:05:48 2002 @@ -1809,7 +1809,7 @@ btv->tuner_type = 33; if (autoload) request_module("tda9887"); - bttv_call_i2c_clients(btv,AUDC_CONFIG_PINNACLE,&id); + bttv_call_clients(btv,AUDC_CONFIG_PINNACLE,&id); } } @@ -2022,7 +2022,7 @@ if (-1 != tuner[btv->nr]) btv->tuner_type = tuner[btv->nr]; if (btv->tuner_type != -1) - bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type); + bttv_call_clients(btv,TUNER_SET_TYPE,&btv->tuner_type); printk("bttv%d: using tuner=%d\n",btv->nr,btv->tuner_type); if (bttv_tvcards[btv->type].has_radio) @@ -2497,7 +2497,7 @@ } request_module("bt832"); - bttv_call_i2c_clients(btv, BT832_HEXDUMP, NULL); + bttv_call_clients(btv, BT832_HEXDUMP, NULL); printk("bttv%d: Reset Bt832 [line=0x%x]\n",btv->nr,resetbit); btwrite(0, BT848_GPIO_DATA); @@ -2514,7 +2514,7 @@ // bt832 on pixelview changes from i2c 0x8a to 0x88 after // being reset as above. So we must follow by this: - bttv_call_i2c_clients(btv, BT832_REATTACH, NULL); + bttv_call_clients(btv, BT832_REATTACH, NULL); } /* ----------------------------------------------------------------------- */ Binary files orig/bttv-0.9.3/bttv-cards.o and bttv-0.9.3/bttv-cards.o differ diff -ur orig/bttv-0.9.3/bttv-driver.c bttv-0.9.3/bttv-driver.c --- orig/bttv-0.9.3/bttv-driver.c Tue Dec 10 23:01:13 2002 +++ bttv-0.9.3/bttv-driver.c Fri Jan 10 23:25:13 2003 @@ -43,7 +43,7 @@ struct bttv bttvs[BTTV_MAX]; unsigned int bttv_debug = 0; -unsigned int bttv_verbose = 1; +unsigned int bttv_verbose = 0; unsigned int bttv_gpio = 0; /* config variables */ @@ -827,44 +827,45 @@ "audio: intern", "audio: off" }; -static int +int audio_mux(struct bttv *btv, int mode) { - int val,mux,i2c_mux,signal; + int val,mux; + btv->audio &= AUDIO_MUTE; + btv->audio |= mode; + + mux = (btv->audio & AUDIO_MUTE) ? AUDIO_OFF : btv->audio; + btaor(bttv_tvcards[btv->type].gpiomask, ~bttv_tvcards[btv->type].gpiomask,BT848_GPIO_OUT_EN); + val = bttv_tvcards[btv->type].audiomux[mux]; + btaor(val,~bttv_tvcards[btv->type].gpiomask, BT848_GPIO_DATA); + if (bttv_gpio) + bttv_gpio_tracking(btv,audio_modes[mux]); + + vprintk("bttv%d: amux: mode=%d audio=%d mux=%d\n", + btv->nr, mode, btv->audio, mux ); + + bttv_call_clients(btv,AUDC_SET_INPUT,&mux); + return 0; +} + +int +audio_mute(struct bttv *btv, int mute) +{ + int signal; + signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC; - switch (mode) { - case AUDIO_MUTE: + if ((mute) || (btv->opt_automute && !signal && !btv->radio_user)) { btv->audio |= AUDIO_MUTE; - break; - case AUDIO_UNMUTE: + } + else { btv->audio &= ~AUDIO_MUTE; - break; - case AUDIO_TUNER: - case AUDIO_RADIO: - case AUDIO_EXTERN: - case AUDIO_INTERN: - btv->audio &= AUDIO_MUTE; - btv->audio |= mode; - } - i2c_mux = mux = (btv->audio & AUDIO_MUTE) ? AUDIO_OFF : btv->audio; - if (btv->opt_automute && !signal && !btv->radio_user) - mux = AUDIO_OFF; -#if 0 - printk("bttv%d: amux: mode=%d audio=%d signal=%s mux=%d/%d irq=%s\n", - btv->nr, mode, btv->audio, signal ? "yes" : "no", - mux, i2c_mux, in_interrupt() ? "yes" : "no"); -#endif + } + audio_mux(btv, btv->audio); - val = bttv_tvcards[btv->type].audiomux[mux]; - btaor(val,~bttv_tvcards[btv->type].gpiomask, BT848_GPIO_DATA); - if (bttv_gpio) - bttv_gpio_tracking(btv,audio_modes[mux]); - if (!in_interrupt()) - bttv_call_i2c_clients(btv,AUDC_SET_INPUT,&(i2c_mux)); return 0; } @@ -876,9 +877,7 @@ memset(&c,0,sizeof(c)); c.norm = btv->tvnorm; c.channel = btv->input; - bttv_call_i2c_clients(btv,VIDIOCSCHAN,&c); - if (btv->type == BTTV_VOODOOTV_FM) - bttv_tda9880_setnorm(btv,c.norm); + bttv_call_clients(btv,VIDIOCSCHAN,&c); } static int @@ -988,9 +987,7 @@ return -EINVAL; if (i >= 4 && i <= 8) { memset(&va,0,sizeof(va)); - bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); - if (btv->audio_hook) - btv->audio_hook(btv,&va,0); + bttv_call_clients(btv, VIDIOCGAUDIO, &va); } switch (c->id) { case V4L2_CID_BRIGHTNESS: @@ -1055,9 +1052,7 @@ return -EINVAL; if (i >= 4 && i <= 8) { memset(&va,0,sizeof(va)); - bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); - if (btv->audio_hook) - btv->audio_hook(btv,&va,0); + bttv_call_clients(btv, VIDIOCGAUDIO, &va); } switch (c->id) { case V4L2_CID_BRIGHTNESS: @@ -1075,10 +1070,8 @@ case V4L2_CID_AUDIO_MUTE: if (c->value) { va.flags |= VIDEO_AUDIO_MUTE; - audio_mux(btv, AUDIO_MUTE); } else { va.flags &= ~VIDEO_AUDIO_MUTE; - audio_mux(btv, AUDIO_UNMUTE); } break; @@ -1126,9 +1119,7 @@ return -EINVAL; } if (i >= 4 && i <= 8) { - bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va); - if (btv->audio_hook) - btv->audio_hook(btv,&va,1); + bttv_call_clients(btv, VIDIOCSAUDIO, &va); } return 0; } @@ -1359,9 +1350,7 @@ unsigned long *freq = arg; down(&btv->lock); btv->freq=*freq; - bttv_call_i2c_clients(btv,VIDIOCSFREQ,freq); - if (btv->has_matchbox && btv->radio_user) - tea5757_set_freq(btv,*freq); + bttv_call_clients(btv,VIDIOCSFREQ,freq); up(&btv->lock); return 0; } @@ -1378,7 +1367,7 @@ v->flags = VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM; v->mode = btv->tvnorm; v->signal = (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) ? 0xFFFF : 0; - bttv_call_i2c_clients(btv,cmd,v); + bttv_call_clients(btv,cmd,v); return 0; } case VIDIOCSTUNER: @@ -1392,7 +1381,7 @@ down(&btv->lock); set_tvnorm(btv,v->mode); - bttv_call_i2c_clients(btv,cmd,v); + bttv_call_clients(btv,cmd,v); up(&btv->lock); return 0; } @@ -1453,12 +1442,7 @@ v->mode = VIDEO_SOUND_MONO; down(&btv->lock); - bttv_call_i2c_clients(btv,cmd,v); - - /* card specific hooks */ - if (btv->audio_hook) - btv->audio_hook(btv,v,0); - + bttv_call_clients(btv,cmd,v); up(&btv->lock); return 0; } @@ -1471,13 +1455,7 @@ return -EINVAL; down(&btv->lock); - audio_mux(btv, (v->flags&VIDEO_AUDIO_MUTE) ? AUDIO_MUTE : AUDIO_UNMUTE); - bttv_call_i2c_clients(btv,cmd,v); - - /* card specific hooks */ - if (btv->audio_hook) - btv->audio_hook(btv,v,1); - + bttv_call_clients(btv,cmd,v); up(&btv->lock); return 0; } @@ -1599,9 +1577,7 @@ /* Hmmm ... */ struct video_audio va; memset(&va, 0, sizeof(struct video_audio)); - bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); - if (btv->audio_hook) - btv->audio_hook(btv,&va,0); + bttv_call_clients(btv, VIDIOCGAUDIO, &va); if(va.mode & VIDEO_SOUND_STEREO) t->rxsubchans |= V4L2_TUNER_SUB_STEREO; if(va.mode & VIDEO_SOUND_LANG1) @@ -1625,6 +1601,7 @@ { struct video_audio va; memset(&va, 0, sizeof(struct video_audio)); + bttv_call_clients(btv, VIDIOCGAUDIO, &va); if (t->audmode == V4L2_TUNER_MODE_MONO) va.mode = VIDEO_SOUND_MONO; else if (t->audmode == V4L2_TUNER_MODE_STEREO) @@ -1633,9 +1610,7 @@ va.mode = VIDEO_SOUND_LANG1; else if (t->audmode == V4L2_TUNER_MODE_LANG2) va.mode = VIDEO_SOUND_LANG2; - bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va); - if (btv->audio_hook) - btv->audio_hook(btv,&va,1); + bttv_call_clients(btv, VIDIOCSAUDIO, &va); } up(&btv->lock); return 0; @@ -1660,9 +1635,7 @@ return -EINVAL; down(&btv->lock); btv->freq = f->frequency; - bttv_call_i2c_clients(btv,VIDIOCSFREQ,&btv->freq); - if (btv->has_matchbox && btv->radio_user) - tea5757_set_freq(btv,btv->freq); + bttv_call_clients(btv,VIDIOCSFREQ,&btv->freq); up(&btv->lock); return 0; } @@ -2523,9 +2496,7 @@ if (i >= 4 && i <= 8) { struct video_audio va; memset(&va,0,sizeof(va)); - bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); - if (btv->audio_hook) - btv->audio_hook(btv,&va,0); + bttv_call_clients(btv, VIDIOCGAUDIO, &va); switch (bttv_ctls[i].id) { case V4L2_CID_AUDIO_VOLUME: if (!(va.flags & VIDEO_AUDIO_VOLUME)) @@ -2835,9 +2806,8 @@ file->private_data = btv; i2c_vidiocschan(btv); - bttv_call_i2c_clients(btv,VIDIOCSFREQ,&v); - bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type); - audio_mux(btv,AUDIO_RADIO); + bttv_call_clients(btv,VIDIOCSFREQ,&v); + bttv_call_clients(btv,AUDC_SET_RADIO,&btv->tuner_type); up(&btv->lock); return 0; @@ -2882,7 +2852,7 @@ russia: 65.0 MHz - 108.0 MHz */ v->rangelow=(int)(65*16); v->rangehigh=(int)(108*16); - bttv_call_i2c_clients(btv,cmd,v); + bttv_call_clients(btv,cmd,v); return 0; } case VIDIOCSTUNER: @@ -3206,8 +3176,8 @@ if ((astat & BT848_INT_RISCI) && (stat & (1<<28))) bttv_irq_switch_fields(btv); - if ((astat & BT848_INT_HLOCK) && btv->opt_automute) - audio_mux(btv, -1); + //if ((astat & BT848_INT_HLOCK) && btv->opt_automute) + // audio_mux(btv, -1); if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) { printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->nr, @@ -3437,7 +3407,7 @@ bt848_contrast(btv,32768); bt848_hue(btv,32768); bt848_sat(btv,32768); - audio_mux(btv,AUDIO_MUTE); + audio_mute(btv,1); set_input(btv,0); /* everything is fine */ @@ -3475,7 +3445,7 @@ /* unregister i2c_bus */ if (0 == btv->i2c_rc) - i2c_bit_del_bus(&btv->i2c_adap); + i2c_biths_del_bus(&btv->i2c_adap); /* unregister video4linux */ if (btv->video_dev.minor!=-1) Only in bttv-0.9.3/: bttv-driver.c.orig Only in bttv-0.9.3/: bttv-driver.c~~ Binary files orig/bttv-0.9.3/bttv-driver.o and bttv-0.9.3/bttv-driver.o differ diff -ur orig/bttv-0.9.3/bttv-if.c bttv-0.9.3/bttv-if.c --- orig/bttv-0.9.3/bttv-if.c Tue Dec 10 22:45:40 2002 +++ bttv-0.9.3/bttv-if.c Sun Dec 29 15:52:38 2002 @@ -36,10 +36,11 @@ #include "bttvp.h" #include "tuner.h" -static struct i2c_algo_bit_data bttv_i2c_algo_template; +static struct i2c_algo_biths_data bttv_i2c_algo_template; static struct i2c_adapter bttv_i2c_adap_template; static struct i2c_client bttv_i2c_client_template; + EXPORT_SYMBOL(bttv_get_cardinfo); EXPORT_SYMBOL(bttv_get_pcidev); EXPORT_SYMBOL(bttv_get_id); @@ -152,48 +153,6 @@ /* ----------------------------------------------------------------------- */ /* I2C functions */ -void bttv_bit_setscl(void *data, int state) -{ - struct bttv *btv = (struct bttv*)data; - - if (state) - btv->i2c_state |= 0x02; - else - btv->i2c_state &= ~0x02; - btwrite(btv->i2c_state, BT848_I2C); - btread(BT848_I2C); -} - -void bttv_bit_setsda(void *data, int state) -{ - struct bttv *btv = (struct bttv*)data; - - if (state) - btv->i2c_state |= 0x01; - else - btv->i2c_state &= ~0x01; - btwrite(btv->i2c_state, BT848_I2C); - btread(BT848_I2C); -} - -static int bttv_bit_getscl(void *data) -{ - struct bttv *btv = (struct bttv*)data; - int state; - - state = btread(BT848_I2C) & 0x02 ? 1 : 0; - return state; -} - -static int bttv_bit_getsda(void *data) -{ - struct bttv *btv = (struct bttv*)data; - int state; - - state = btread(BT848_I2C) & 0x01; - return state; -} - static void bttv_inc_use(struct i2c_adapter *adap) { MOD_INC_USE_COUNT; @@ -216,7 +175,7 @@ } } if (btv->tuner_type != -1) - bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type); + bttv_call_clients(btv,TUNER_SET_TYPE,&btv->tuner_type); if (bttv_verbose) printk("bttv%d: i2c attach [client=%s,%s]\n",btv->nr, client->name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed"); @@ -240,7 +199,7 @@ return 0; } -void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg) +void bttv_call_clients(struct bttv *btv, unsigned int cmd, void *arg) { int i; @@ -252,23 +211,83 @@ btv->i2c_clients[i]->driver->command( btv->i2c_clients[i],cmd,arg); } + + switch (cmd) { + case VIDIOCGAUDIO: + if (btv->audio_hook) + btv->audio_hook(btv, arg, 0); + break; + case VIDIOCSAUDIO: + { + struct video_audio *v = arg; + + audio_mute(btv, (v->flags & VIDEO_AUDIO_MUTE) ? 1 : 0); + if (btv->audio_hook) + btv->audio_hook(btv, arg, 1); + break; + } + case VIDIOCSFREQ: + if (btv->has_matchbox && btv->radio_user) { + unsigned long *freq = arg; + tea5757_set_freq(btv, *freq); + } + break; + case VIDIOCSCHAN: + if (btv->type == BTTV_VOODOOTV_FM) { + struct video_channel *c = arg; + bttv_tda9880_setnorm(btv,c->norm); + } + break; + case AUDC_SET_RADIO: + audio_mux(btv,AUDIO_RADIO); + break; + } } void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg) { if (card >= bttv_num) return; - bttv_call_i2c_clients(&bttvs[card], cmd, arg); + bttv_call_clients(&bttvs[card], cmd, arg); } -static struct i2c_algo_bit_data bttv_i2c_algo_template = { - .setsda = bttv_bit_setsda, - .setscl = bttv_bit_setscl, - .getsda = bttv_bit_getsda, - .getscl = bttv_bit_getscl, - .udelay = 16, - .mdelay = 10, - .timeout = 200, + +static _HS_ATTR_ void bttv_bit_setstate(struct i2c_algo_biths_data *adap) +{ + adap->hw_state &= ~(BT848_I2C_SCL | BT848_I2C_SDA); + if (adap->ctrl & _HS_SCL) + adap->hw_state |= BT848_I2C_SCL; + + if (adap->ctrl & _HS_SDA) + adap->hw_state |= BT848_I2C_SDA; +} + +static _HS_ATTR_ void bttv_bit_setscl(void *bt848_i2c, int hw_state) +{ + writel(hw_state, bt848_i2c); + readl(bt848_i2c); +} +#define bttv_bit_setsda bttv_bit_setscl + +static _HS_ATTR_ int bttv_bit_getscl(void *bt848_i2c) +{ + return (readl(bt848_i2c) & BT848_I2C_SCL); +} + +static _HS_ATTR_ int bttv_bit_getsda(void *bt848_i2c) +{ + return (readl(bt848_i2c) & BT848_I2C_SDA); +} + +#define xloop_kHz(x) (x * 0x10c6 / 4000) +static struct i2c_algo_biths_data bttv_i2c_algo_template = { + setstate: bttv_bit_setstate, + setsda: bttv_bit_setsda, + setscl: bttv_bit_setscl, + getsda: bttv_bit_getsda, + getscl: bttv_bit_getscl, + xloops: xloop_kHz(1000), + timeout: HZ/100, }; static struct i2c_adapter bttv_i2c_adap_template = { @@ -332,7 +351,6 @@ void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr) { int i; - if (bttv_I2CWrite(btv, addr, 0, -1, 0)<0) { printk(KERN_WARNING "bttv: readee error\n"); return; @@ -352,21 +370,21 @@ memcpy(&btv->i2c_adap, &bttv_i2c_adap_template, sizeof(struct i2c_adapter)); memcpy(&btv->i2c_algo, &bttv_i2c_algo_template, - sizeof(struct i2c_algo_bit_data)); + sizeof(struct i2c_algo_biths_data)); memcpy(&btv->i2c_client, &bttv_i2c_client_template, sizeof(struct i2c_client)); sprintf(btv->i2c_adap.name+strlen(btv->i2c_adap.name), " #%d", btv->nr); - btv->i2c_algo.data = btv; + + btv->i2c_algo.hw_data = btv->bt848_mmio + BT848_I2C; + btv->i2c_algo.hw_state = btread(BT848_I2C); + btv->i2c_adap.data = btv; btv->i2c_adap.algo_data = &btv->i2c_algo; btv->i2c_client.adapter = &btv->i2c_adap; - bttv_bit_setscl(btv,1); - bttv_bit_setsda(btv,1); - - btv->i2c_rc = i2c_bit_add_bus(&btv->i2c_adap); + btv->i2c_rc = i2c_biths_add_bus(&btv->i2c_adap); return btv->i2c_rc; } Binary files orig/bttv-0.9.3/bttv-if.o and bttv-0.9.3/bttv-if.o differ Binary files orig/bttv-0.9.3/bttv-risc.o and bttv-0.9.3/bttv-risc.o differ Binary files orig/bttv-0.9.3/bttv-vbi.o and bttv-0.9.3/bttv-vbi.o differ diff -ur orig/bttv-0.9.3/bttv.h bttv-0.9.3/bttv.h --- orig/bttv-0.9.3/bttv.h Tue Dec 10 22:45:40 2002 +++ bttv-0.9.3/bttv.h Sat Dec 28 18:26:00 2002 @@ -243,9 +243,7 @@ /* i2c */ #define I2C_CLIENTS_MAX 16 -extern void bttv_bit_setscl(void *data, int state); -extern void bttv_bit_setsda(void *data, int state); -extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg); +extern void bttv_call_clients(struct bttv *btv, unsigned int cmd, void *arg); extern int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for); extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, unsigned char b2, int both); Binary files orig/bttv-0.9.3/bttv.o and bttv-0.9.3/bttv.o differ diff -ur orig/bttv-0.9.3/bttvp.h bttv-0.9.3/bttvp.h --- orig/bttv-0.9.3/bttvp.h Tue Dec 10 22:57:21 2002 +++ bttv-0.9.3/bttvp.h Sat Dec 28 18:26:00 2002 @@ -29,7 +29,7 @@ #include <linux/types.h> #include <linux/wait.h> #include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> +#include <linux/i2c-algo-biths.h> #include <linux/videodev.h> #include <linux/pci.h> #include <asm/scatterlist.h> @@ -268,7 +268,7 @@ /* i2c layer */ struct i2c_adapter i2c_adap; - struct i2c_algo_bit_data i2c_algo; + struct i2c_algo_biths_data i2c_algo; struct i2c_client i2c_client; int i2c_state, i2c_rc; struct i2c_client *i2c_clients[I2C_CLIENTS_MAX]; Only in orig/bttv-0.9.3/: log Binary files orig/bttv-0.9.3/video-buf.o and bttv-0.9.3/video-buf.o differ
--- bttv-driver.c.orig Fri Jan 10 23:24:04 2003 +++ bttv-driver.c Fri Jan 10 23:25:13 2003 @@ -1601,6 +1601,7 @@ { struct video_audio va; memset(&va, 0, sizeof(struct video_audio)); + bttv_call_clients(btv, VIDIOCGAUDIO, &va); if (t->audmode == V4L2_TUNER_MODE_MONO) va.mode = VIDEO_SOUND_MONO; else if (t->audmode == V4L2_TUNER_MODE_STEREO)