From 19388b4b929315e487572fdd1ed7bc071ac7bea9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Oct 2007 10:00:37 -0200 Subject: planb: fix obvious interrupt handling bugs From: Jeff Garzik irq handlers have returned a return value for years now... catch up with the times. Also, ditch unneeded prototype. Signed-off-by: Jeff Garzik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/planb.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/planb.c b/linux/drivers/media/video/planb.c index 5da38b139..358dc2996 100644 --- a/linux/drivers/media/video/planb.c +++ b/linux/drivers/media/video/planb.c @@ -92,11 +92,6 @@ static void planb_close(struct video_device *); static int planb_ioctl(struct video_device *, unsigned int, void *); static int planb_init_done(struct video_device *); static int planb_mmap(struct video_device *, const char *, unsigned long); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -static void planb_irq(int, void *, struct pt_regs *); -#else -static void planb_irq(int, void *); -#endif static void release_planb(void); int init_planbs(struct video_init *); @@ -1321,9 +1316,9 @@ cmd_tab_data_end: } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -static void planb_irq(int irq, void *dev_id, struct pt_regs * regs) +static irqreturn_t planb_irq(int irq, void *dev_id, struct pt_regs * regs) #else -static void planb_irq(int irq, void *dev_id) +static irqreturn_t planb_irq(int irq, void *dev_id) #endif { unsigned int stat, astat; @@ -1367,13 +1362,14 @@ static void planb_irq(int irq, void *dev_id) pb->frame_stat[fr] = GBUFFER_DONE; pb->grabbing--; wake_up_interruptible(&pb->capq); - return; + return IRQ_HANDLED; } /* incorrect interrupts? */ pb->intr_mask = PLANB_CLR_IRQ; out_le32(&pb->planb_base->intr_stat, PLANB_CLR_IRQ); printk(KERN_ERR "PlanB: IRQ lockup, cleared intrrupts" " unconditionally\n"); + return IRQ_HANDLED; } /******************************* @@ -2099,7 +2095,7 @@ static int init_planb(struct planb *pb) /* clear interrupt mask */ pb->intr_mask = PLANB_CLR_IRQ; - result = request_irq(pb->irq, planb_irq, 0, "PlanB", (void *)pb); + result = request_irq(pb->irq, planb_irq, 0, "PlanB", pb); if (result < 0) { if (result==-EINVAL) printk(KERN_ERR "PlanB: Bad irq number (%d) " -- cgit v1.2.3 From a85302f51c025ddce51d02af80e11649d0830a0a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 25 Aug 2006 16:52:54 -0300 Subject: Cleanup: Removed obsoleted code from bttv-cards From: Nickolay V. Shmyrev This is part of the old V4L1->V4L2 bttv patch, ported to current tree by Mauro Carvalho Chehab Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/bttv-cards.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) --- linux/drivers/media/video/bt8xx/bttv-cards.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index c697cb686..c45c0e9ae 100644 --- a/linux/drivers/media/video/bt8xx/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c @@ -4501,13 +4501,8 @@ gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set) { unsigned int val, con; -#if BTTV_VERSION_CODE > KERNEL_VERSION(0,8,0) if (btv->radio_user) return; -#else - if (btv->radio) - return; -#endif val = gpio_read(); if (set) { @@ -4696,13 +4691,8 @@ pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set) { unsigned int val = 0; -#if BTTV_VERSION_CODE > KERNEL_VERSION(0,8,0) if (btv->radio_user) return; -#else - if (btv->radio) - return; -#endif if (set) { if (v->mode & VIDEO_SOUND_MONO) { @@ -4733,13 +4723,9 @@ fv2000s_audio(struct bttv *btv, struct video_audio *v, int set) { unsigned int val = 0xffff; -#if BTTV_VERSION_CODE > KERNEL_VERSION(0,8,0) if (btv->radio_user) return; -#else - if (btv->radio) - return; -#endif + if (set) { if (v->mode & VIDEO_SOUND_MONO) { val = 0x0000; -- cgit v1.2.3 From f91895a0ab0593480380667891cf0be615c1cc85 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Oct 2007 11:53:21 -0200 Subject: Cleanup: removed i2c_vidiocschan From: Nickolay V. Shmyrev This is part of the old V4L1->V4L2 bttv patch, ported to current tree by Mauro Carvalho Chehab Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/bttv-driver.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) --- linux/drivers/media/video/bt8xx/bttv-driver.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index 37db47ecc..bddba58b2 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -1290,16 +1290,6 @@ audio_input(struct bttv *btv, int input) return audio_mux(btv, input, btv->mute); } -static void -i2c_vidiocschan(struct bttv *btv) -{ - v4l2_std_id std = bttv_tvnorms[btv->tvnorm].v4l2_id; - - bttv_call_i2c_clients(btv, VIDIOC_S_STD, &std); - if (btv->c.type == BTTV_BOARD_VOODOOTV_FM || btv->c.type == BTTV_BOARD_VOODOOTV_200) - bttv_tda9880_setnorm(btv,btv->tvnorm); -} - static void bttv_crop_calc_limits(struct bttv_crop *c) { @@ -1334,6 +1324,7 @@ static int set_tvnorm(struct bttv *btv, unsigned int norm) { const struct bttv_tvnorm *tvnorm; + v4l2_std_id id; if (norm < 0 || norm >= BTTV_TVNORMS) return -EINVAL; @@ -1375,6 +1366,9 @@ set_tvnorm(struct bttv *btv, unsigned int norm) break; #endif } + id = tvnorm->v4l2_id; + bttv_call_i2c_clients(btv, VIDIOC_S_STD, &id); + return 0; } @@ -1400,7 +1394,6 @@ set_input(struct bttv *btv, unsigned int input, unsigned int norm) audio_input(btv,(input == bttv_tvcards[btv->c.type].tuner ? TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN)); set_tvnorm(btv, norm); - i2c_vidiocschan(btv); } static void init_irqreg(struct bttv *btv) @@ -2136,7 +2129,6 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) mutex_lock(&btv->lock); set_tvnorm(btv,i); - i2c_vidiocschan(btv); mutex_unlock(&btv->lock); return 0; } @@ -3820,7 +3812,7 @@ static int bttv_open(struct inode *inode, struct file *file) V4L2_FIELD_SEQ_TB, sizeof(struct bttv_buffer), fh); - i2c_vidiocschan(btv); + set_tvnorm(btv,btv->tvnorm); btv->users++; -- cgit v1.2.3 From bbb2775af14dc145fe9434e8e34ebd4cf0c8499c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Oct 2007 12:01:08 -0200 Subject: Partial conversion from V4L1 to V4L2 From: Nickolay V. Shmyrev This is part of the old V4L1->V4L2 bttv patch, ported to current tree by Mauro Carvalho Chehab Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/Kconfig | 2 linux/drivers/media/video/bt8xx/bttv-driver.c | 663 +++++--------------------- linux/drivers/media/video/bt8xx/bttvp.h | 4 3 files changed, 131 insertions(+), 538 deletions(-) --- linux/drivers/media/video/bt8xx/Kconfig | 2 +- linux/drivers/media/video/bt8xx/bttv-driver.c | 663 +++++--------------------- linux/drivers/media/video/bt8xx/bttvp.h | 4 - 3 files changed, 131 insertions(+), 538 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/Kconfig b/linux/drivers/media/video/bt8xx/Kconfig index 2ca162b39..ce93312cf 100644 --- a/linux/drivers/media/video/bt8xx/Kconfig +++ b/linux/drivers/media/video/bt8xx/Kconfig @@ -1,6 +1,6 @@ config VIDEO_BT848 tristate "BT848 Video For Linux" - depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L1 + depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 select I2C_ALGOBIT select FW_LOADER select VIDEO_BTCX diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index bddba58b2..fce6c5324 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -9,6 +9,9 @@ some v4l2 code lines are taken from Justin's bttv2 driver which is (c) 2000 Justin Schoeman + V4L1 removal from: + (c) 2005-2006 Nickolay V. Shmyrev + Cropping and overscan support Copyright (C) 2005, 2006 Michael H. Schimek Sponsored by OPQ Systems AB @@ -1953,111 +1956,6 @@ static struct videobuf_queue_ops bttv_video_qops = { static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) { switch (cmd) { - case BTTV_VERSION: - return BTTV_VERSION_CODE; - - /* *** v4l1 *** ************************************************ */ - case VIDIOCGFREQ: - { - unsigned long *freq = arg; - *freq = btv->freq; - return 0; - } - case VIDIOCSFREQ: - { - struct v4l2_frequency freq; - - memset(&freq, 0, sizeof(freq)); - freq.frequency = *(unsigned long *)arg; - mutex_lock(&btv->lock); - freq.type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - btv->freq = *(unsigned long *)arg; - bttv_call_i2c_clients(btv,VIDIOC_S_FREQUENCY,&freq); - if (btv->has_matchbox && btv->radio_user) - tea5757_set_freq(btv,*(unsigned long *)arg); - mutex_unlock(&btv->lock); - return 0; - } - - case VIDIOCGTUNER: - { - struct video_tuner *v = arg; - - if (UNSET == bttv_tvcards[btv->c.type].tuner) - return -EINVAL; - if (v->tuner) /* Only tuner 0 */ - return -EINVAL; - strcpy(v->name, "Television"); - v->rangelow = 0; - v->rangehigh = 0x7FFFFFFF; - 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); - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner *v = arg; - - if (v->tuner) /* Only tuner 0 */ - return -EINVAL; - if (v->mode >= BTTV_TVNORMS) - return -EINVAL; - - mutex_lock(&btv->lock); - set_tvnorm(btv,v->mode); - bttv_call_i2c_clients(btv,cmd,v); - mutex_unlock(&btv->lock); - return 0; - } - - case VIDIOCGCHAN: - { - struct video_channel *v = arg; - unsigned int channel = v->channel; - - if (channel >= bttv_tvcards[btv->c.type].video_inputs) - return -EINVAL; - v->tuners=0; - v->flags = VIDEO_VC_AUDIO; - v->type = VIDEO_TYPE_CAMERA; - v->norm = btv->tvnorm; - if (channel == bttv_tvcards[btv->c.type].tuner) { - strcpy(v->name,"Television"); - v->flags|=VIDEO_VC_TUNER; - v->type=VIDEO_TYPE_TV; - v->tuners=1; - } else if (channel == btv->svhs) { - strcpy(v->name,"S-Video"); - } else { - sprintf(v->name,"Composite%d",channel); - } - return 0; - } - case VIDIOCSCHAN: - { - struct video_channel *v = arg; - unsigned int channel = v->channel; - - if (channel >= bttv_tvcards[btv->c.type].video_inputs) - return -EINVAL; - if (v->norm >= BTTV_TVNORMS) - return -EINVAL; - - mutex_lock(&btv->lock); - if (channel == btv->input && - v->norm == btv->tvnorm) { - /* nothing to do */ - mutex_unlock(&btv->lock); - return 0; - } - - set_input(btv, v->channel, v->norm); - mutex_unlock(&btv->lock); - return 0; - } - case VIDIOCGAUDIO: { struct video_audio *v = arg; @@ -2193,45 +2091,6 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) return 0; } - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *t = arg; - - if (UNSET == bttv_tvcards[btv->c.type].tuner) - return -EINVAL; - if (0 != t->index) - return -EINVAL; - mutex_lock(&btv->lock); - memset(t,0,sizeof(*t)); - t->rxsubchans = V4L2_TUNER_SUB_MONO; - bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); - strcpy(t->name, "Television"); - t->capability = V4L2_TUNER_CAP_NORM; - t->type = V4L2_TUNER_ANALOG_TV; - if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) - t->signal = 0xffff; - - if (btv->audio_hook) { - /* Hmmm ... */ - struct video_audio va; - memset(&va, 0, sizeof(struct video_audio)); - btv->audio_hook(btv,&va,0); - t->audmode = V4L2_TUNER_MODE_MONO; - t->rxsubchans = V4L2_TUNER_SUB_MONO; - if(va.mode & VIDEO_SOUND_STEREO) { - t->audmode = V4L2_TUNER_MODE_STEREO; - t->rxsubchans = V4L2_TUNER_SUB_STEREO; - } - if(va.mode & VIDEO_SOUND_LANG2) { - t->audmode = V4L2_TUNER_MODE_LANG1; - t->rxsubchans = V4L2_TUNER_SUB_LANG1 - | V4L2_TUNER_SUB_LANG2; - } - } - /* FIXME: fill capability+audmode */ - mutex_unlock(&btv->lock); - return 0; - } case VIDIOC_S_TUNER: { struct v4l2_tuner *t = arg; @@ -2292,6 +2151,10 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) printk(KERN_INFO "bttv%d: ================== END STATUS CARD #%d ==================\n", btv->c.nr, btv->c.nr); return 0; } + case VIDIOC_G_CTRL: + return get_control(btv,arg); + case VIDIOC_S_CTRL: + return set_control(btv,arg); #ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_DBG_G_REGISTER: case VIDIOC_DBG_S_REGISTER: @@ -2836,7 +2699,6 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, { struct bttv_fh *fh = file->private_data; struct bttv *btv = fh->btv; - unsigned long flags; int retval = 0; if (bttv_debug > 1) @@ -2846,9 +2708,6 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, bttv_reinit_bt848(btv); switch (cmd) { - case VIDIOCSFREQ: - case VIDIOCSTUNER: - case VIDIOCSCHAN: case VIDIOC_S_CTRL: case VIDIOC_S_STD: case VIDIOC_S_INPUT: @@ -2860,237 +2719,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, }; switch (cmd) { - - /* *** v4l1 *** ************************************************ */ - case VIDIOCGCAP: - { - struct video_capability *cap = arg; - - memset(cap,0,sizeof(*cap)); - strcpy(cap->name,btv->video_dev->name); - if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { - /* vbi */ - cap->type = VID_TYPE_TUNER|VID_TYPE_TELETEXT; - } else { - /* others */ - cap->type = VID_TYPE_CAPTURE| - VID_TYPE_TUNER| - VID_TYPE_CLIPPING| - VID_TYPE_SCALES; - if (no_overlay <= 0) - cap->type |= VID_TYPE_OVERLAY; - - cap->maxwidth = bttv_tvnorms[btv->tvnorm].swidth; - cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight; - cap->minwidth = 48; - cap->minheight = 32; - } - cap->channels = bttv_tvcards[btv->c.type].video_inputs; - cap->audios = bttv_tvcards[btv->c.type].audio_inputs; - return 0; - } - - case VIDIOCGPICT: - { - struct video_picture *pic = arg; - - memset(pic,0,sizeof(*pic)); - pic->brightness = btv->bright; - pic->contrast = btv->contrast; - pic->hue = btv->hue; - pic->colour = btv->saturation; - if (fh->fmt) { - pic->depth = fh->fmt->depth; - pic->palette = fh->fmt->palette; - } - return 0; - } - case VIDIOCSPICT: - { - struct video_picture *pic = arg; - const struct bttv_format *fmt; - - fmt = format_by_palette(pic->palette); - if (NULL == fmt) - return -EINVAL; - mutex_lock(&fh->cap.lock); - if (fmt->flags & FORMAT_FLAGS_RAW) { - /* VIDIOCMCAPTURE uses gbufsize, not RAW_BPL * - RAW_LINES * 2. F1 is stored at offset 0, F2 - at buffer size / 2. */ - fh->width = RAW_BPL; - fh->height = gbufsize / RAW_BPL; - btv->init.width = RAW_BPL; - btv->init.height = gbufsize / RAW_BPL; - } - fh->ovfmt = fmt; - fh->fmt = fmt; - btv->init.ovfmt = fmt; - btv->init.fmt = fmt; - if (bigendian) { - /* dirty hack time: swap bytes for overlay if the - display adaptor is big endian (insmod option) */ - if (fmt->palette == VIDEO_PALETTE_RGB555 || - fmt->palette == VIDEO_PALETTE_RGB565 || - fmt->palette == VIDEO_PALETTE_RGB32) { - fh->ovfmt = fmt+1; - } - } - bt848_bright(btv,pic->brightness); - bt848_contrast(btv,pic->contrast); - bt848_hue(btv,pic->hue); - bt848_sat(btv,pic->colour); - mutex_unlock(&fh->cap.lock); - return 0; - } - - case VIDIOCGWIN: - { - struct video_window *win = arg; - - memset(win,0,sizeof(*win)); - win->x = fh->ov.w.left; - win->y = fh->ov.w.top; - win->width = fh->ov.w.width; - win->height = fh->ov.w.height; - return 0; - } - case VIDIOCSWIN: - { - struct video_window *win = arg; - struct v4l2_window w2; - - if (no_overlay > 0) { - printk ("VIDIOCSWIN: no_overlay\n"); - return -EINVAL; - } - - w2.field = V4L2_FIELD_ANY; - w2.w.left = win->x; - w2.w.top = win->y; - w2.w.width = win->width; - w2.w.height = win->height; - w2.clipcount = win->clipcount; - w2.clips = (struct v4l2_clip __user *)win->clips; - retval = setup_window(fh, btv, &w2, 0); - if (0 == retval) { - /* on v4l1 this ioctl affects the read() size too */ - fh->width = fh->ov.w.width; - fh->height = fh->ov.w.height; - btv->init.width = fh->ov.w.width; - btv->init.height = fh->ov.w.height; - } - return retval; - } - - case VIDIOCGFBUF: - { - struct video_buffer *fbuf = arg; - - fbuf->base = btv->fbuf.base; - fbuf->width = btv->fbuf.fmt.width; - fbuf->height = btv->fbuf.fmt.height; - fbuf->bytesperline = btv->fbuf.fmt.bytesperline; - if (fh->ovfmt) - fbuf->depth = fh->ovfmt->depth; - else { - if (fbuf->width) - fbuf->depth = ((fbuf->bytesperline<<3) - + (fbuf->width-1) ) - /fbuf->width; - else - fbuf->depth = 0; - } - return 0; - } - case VIDIOCSFBUF: - { - struct video_buffer *fbuf = arg; - const struct bttv_format *fmt; - unsigned long end; - - if(!capable(CAP_SYS_ADMIN) && - !capable(CAP_SYS_RAWIO)) - return -EPERM; - end = (unsigned long)fbuf->base + - fbuf->height * fbuf->bytesperline; - mutex_lock(&fh->cap.lock); - retval = -EINVAL; - - switch (fbuf->depth) { - case 8: - fmt = format_by_palette(VIDEO_PALETTE_HI240); - break; - case 16: - fmt = format_by_palette(VIDEO_PALETTE_RGB565); - break; - case 24: - fmt = format_by_palette(VIDEO_PALETTE_RGB24); - break; - case 32: - fmt = format_by_palette(VIDEO_PALETTE_RGB32); - break; - case 15: - fbuf->depth = 16; - fmt = format_by_palette(VIDEO_PALETTE_RGB555); - break; - default: - fmt = NULL; - break; - } - if (NULL == fmt) - goto fh_unlock_and_return; - - fh->ovfmt = fmt; - fh->fmt = fmt; - btv->init.ovfmt = fmt; - btv->init.fmt = fmt; - btv->fbuf.base = fbuf->base; - btv->fbuf.fmt.width = fbuf->width; - btv->fbuf.fmt.height = fbuf->height; - if (fbuf->bytesperline) - btv->fbuf.fmt.bytesperline = fbuf->bytesperline; - else - btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fbuf->depth/8; - mutex_unlock(&fh->cap.lock); - return 0; - } - - case VIDIOCCAPTURE: - case VIDIOC_OVERLAY: - { - struct bttv_buffer *new; - int *on = arg; - - if (*on) { - /* verify args */ - if (NULL == btv->fbuf.base) - return -EINVAL; - if (!fh->ov.setup_ok) { - dprintk("bttv%d: overlay: !setup_ok\n",btv->c.nr); - return -EINVAL; - } - } - - if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY)) - return -EBUSY; - - mutex_lock(&fh->cap.lock); - if (*on) { - fh->ov.tvnorm = btv->tvnorm; - new = videobuf_pci_alloc(sizeof(*new)); - new->crop = btv->crop[!!fh->do_crop].rect; - bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); - } else { - new = NULL; - } - - /* switch over */ - retval = bttv_switch_overlay(btv,fh,new); - mutex_unlock(&fh->cap.lock); - return retval; - } - +#ifdef CONFIG_VIDEO_V4L1_COMPAT case VIDIOCGMBUF: { struct video_mbuf *mbuf = arg; @@ -3111,98 +2740,19 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, mutex_unlock(&fh->cap.lock); return 0; } - case VIDIOCMCAPTURE: - { - struct video_mmap *vm = arg; - struct bttv_buffer *buf; - enum v4l2_field field; - __s32 height2; - int res; - - if (vm->frame >= VIDEO_MAX_FRAME) - return -EINVAL; - - res = bttv_resource(fh); - if (!check_alloc_btres(btv, fh, res)) - return -EBUSY; - - mutex_lock(&fh->cap.lock); - retval = -EINVAL; - buf = (struct bttv_buffer *)fh->cap.bufs[vm->frame]; - if (NULL == buf) - goto fh_unlock_and_return; - if (0 == buf->vb.baddr) - goto fh_unlock_and_return; - if (buf->vb.state == STATE_QUEUED || - buf->vb.state == STATE_ACTIVE) - goto fh_unlock_and_return; - - height2 = btv->crop[!!fh->do_crop].rect.height >> 1; - field = (vm->height > height2) - ? V4L2_FIELD_INTERLACED - : V4L2_FIELD_BOTTOM; - retval = bttv_prepare_buffer(&fh->cap,btv,buf, - format_by_palette(vm->format), - vm->width,vm->height,field); - if (0 != retval) - goto fh_unlock_and_return; - btv->init.width = vm->width; - btv->init.height = vm->height; - spin_lock_irqsave(&btv->s_lock,flags); - buffer_queue(&fh->cap,&buf->vb); - spin_unlock_irqrestore(&btv->s_lock,flags); - mutex_unlock(&fh->cap.lock); - return 0; - } - case VIDIOCSYNC: - { - int *frame = arg; - struct bttv_buffer *buf; - - if (*frame >= VIDEO_MAX_FRAME) - return -EINVAL; - - mutex_lock(&fh->cap.lock); - retval = -EINVAL; - buf = (struct bttv_buffer *)fh->cap.bufs[*frame]; - if (NULL == buf) - goto fh_unlock_and_return; - retval = videobuf_waiton(&buf->vb,0,1); - if (0 != retval) - goto fh_unlock_and_return; - switch (buf->vb.state) { - case STATE_ERROR: - retval = -EIO; - /* fall through */ - case STATE_DONE: - { - struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); - videobuf_dma_sync(&fh->cap,dma); - bttv_dma_free(&fh->cap,btv,buf); - break; - } - default: - retval = -EINVAL; - break; - } - mutex_unlock(&fh->cap.lock); - return retval; - } - +#endif case VIDIOCGVBIFMT: - if (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) { - retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE); - if (0 != retval) - return retval; - } - - /* fall through */ - case VIDIOCSVBIFMT: - return v4l_compat_translate_ioctl(inode, file, cmd, - arg, bttv_do_ioctl); - - case BTTV_VERSION: + case VIDIOCSYNC: + case VIDIOCMCAPTURE: + case VIDIOCCAPTURE: + case VIDIOCGFBUF: + case VIDIOCSFBUF: + case VIDIOCGWIN: + case VIDIOCSWIN: + case VIDIOCGCAP: + case VIDIOCGPICT: + case VIDIOCSPICT: case VIDIOCGFREQ: case VIDIOCSFREQ: case VIDIOCGTUNER: @@ -3211,7 +2761,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, case VIDIOCSCHAN: case VIDIOCGAUDIO: case VIDIOCSAUDIO: - return bttv_common_ioctls(btv,cmd,arg); + return v4l_compat_translate_ioctl(inode,file,cmd,arg, + bttv_do_ioctl); /* *** v4l2 *** ************************************************ */ case VIDIOC_QUERYCAP: @@ -3239,7 +2790,6 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, cap->capabilities |= V4L2_CAP_TUNER; return 0; } - case VIDIOC_ENUM_FMT: { struct v4l2_fmtdesc *f = arg; @@ -3289,7 +2839,6 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, strlcpy(f->description,bttv_formats[i].name,sizeof(f->description)); return 0; } - case VIDIOC_TRY_FMT: { struct v4l2_format *f = arg; @@ -3316,6 +2865,38 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, fb->fmt.pixelformat = fh->ovfmt->fourcc; return 0; } + case VIDIOC_OVERLAY: + { + struct bttv_buffer *new; + int *on = arg; + + if (*on) { + /* verify args */ + if (NULL == btv->fbuf.base) + return -EINVAL; + if (!fh->ov.setup_ok) { + dprintk("bttv%d: overlay: !setup_ok\n",btv->c.nr); + return -EINVAL; + } + } + + if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY)) + return -EBUSY; + + mutex_lock(&fh->cap.lock); + if (*on) { + fh->ov.tvnorm = btv->tvnorm; + new = videobuf_pci_alloc(sizeof(*new)); + bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); + } else { + new = NULL; + } + + /* switch over */ + retval = bttv_switch_overlay(btv,fh,new); + mutex_unlock(&fh->cap.lock); + return retval; + } case VIDIOC_S_FBUF: { struct v4l2_framebuffer *fb = arg; @@ -3383,13 +2964,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, mutex_unlock(&fh->cap.lock); return retval; } - case VIDIOC_REQBUFS: return videobuf_reqbufs(bttv_queue(fh),arg); - case VIDIOC_QUERYBUF: return videobuf_querybuf(bttv_queue(fh),arg); - case VIDIOC_QBUF: { int res = bttv_resource(fh); @@ -3398,11 +2976,9 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, return -EBUSY; return videobuf_qbuf(bttv_queue(fh),arg); } - case VIDIOC_DQBUF: return videobuf_dqbuf(bttv_queue(fh),arg, file->f_flags & O_NONBLOCK); - case VIDIOC_STREAMON: { int res = bttv_resource(fh); @@ -3465,10 +3041,6 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, } return 0; } - case VIDIOC_G_CTRL: - return get_control(btv,arg); - case VIDIOC_S_CTRL: - return set_control(btv,arg); case VIDIOC_G_PARM: { struct v4l2_streamparm *parm = arg; @@ -3481,6 +3053,45 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, parm->parm.capture.timeperframe = s.frameperiod; return 0; } + case VIDIOC_G_TUNER: + { + struct v4l2_tuner *t = arg; + + if (UNSET == bttv_tvcards[btv->c.type].tuner) + return -EINVAL; + if (0 != t->index) + return -EINVAL; + mutex_lock(&btv->lock); + memset(t,0,sizeof(*t)); + t->rxsubchans = V4L2_TUNER_SUB_MONO; + bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); + strcpy(t->name, "Television"); + t->capability = V4L2_TUNER_CAP_NORM; + t->type = V4L2_TUNER_ANALOG_TV; + if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) + t->signal = 0xffff; + + if (btv->audio_hook) { + /* Hmmm ... */ + struct video_audio va; + memset(&va, 0, sizeof(struct video_audio)); + btv->audio_hook(btv,&va,0); + t->audmode = V4L2_TUNER_MODE_MONO; + t->rxsubchans = V4L2_TUNER_SUB_MONO; + if(va.mode & VIDEO_SOUND_STEREO) { + t->audmode = V4L2_TUNER_MODE_STEREO; + t->rxsubchans = V4L2_TUNER_SUB_STEREO; + } + if(va.mode & VIDEO_SOUND_LANG2) { + t->audmode = V4L2_TUNER_MODE_LANG1; + t->rxsubchans = V4L2_TUNER_SUB_LANG1 + | V4L2_TUNER_SUB_LANG2; + } + } + /* FIXME: fill capability+audmode */ + mutex_unlock(&btv->lock); + return 0; + } case VIDIOC_G_PRIORITY: { @@ -3618,15 +3229,15 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_ENUMINPUT: case VIDIOC_G_INPUT: case VIDIOC_S_INPUT: - case VIDIOC_G_TUNER: case VIDIOC_S_TUNER: case VIDIOC_G_FREQUENCY: case VIDIOC_S_FREQUENCY: case VIDIOC_LOG_STATUS: + case VIDIOC_G_CTRL: + case VIDIOC_S_CTRL: case VIDIOC_DBG_G_REGISTER: case VIDIOC_DBG_S_REGISTER: return bttv_common_ioctls(btv,cmd,arg); - default: return -ENOIOCTLCMD; } @@ -3644,33 +3255,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, static int bttv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - struct bttv_fh *fh = file->private_data; - - switch (cmd) { - case BTTV_VBISIZE: - { - const struct bttv_tvnorm *tvnorm; - - tvnorm = fh->vbi_fmt.tvnorm; - - if (fh->vbi_fmt.fmt.start[0] != tvnorm->vbistart[0] || - fh->vbi_fmt.fmt.start[1] != tvnorm->vbistart[1] || - fh->vbi_fmt.fmt.count[0] != fh->vbi_fmt.fmt.count[1]) { - /* BTTV_VBISIZE cannot express these parameters, - however open() resets the paramters to defaults - and apps shouldn't call BTTV_VBISIZE after - VIDIOC_S_FMT. */ - return -EINVAL; - } - - bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE); - return (fh->vbi_fmt.fmt.count[0] * 2 - * fh->vbi_fmt.fmt.samples_per_line); - } - - default: - return video_usercopy(inode, file, cmd, arg, bttv_do_ioctl); - } + return video_usercopy(inode, file, cmd, arg, bttv_do_ioctl); } static ssize_t bttv_read(struct file *file, char __user *data, @@ -3974,43 +3559,55 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, struct bttv *btv = file->private_data; switch (cmd) { - case VIDIOCGCAP: + case VIDIOC_QUERYCAP: { - struct video_capability *cap = arg; + struct v4l2_capability *cap = arg; memset(cap,0,sizeof(*cap)); - strcpy(cap->name,btv->radio_dev->name); - cap->type = VID_TYPE_TUNER; - cap->channels = 1; - cap->audios = 1; + strcpy(cap->driver, "bttv"); + strlcpy(cap->card, btv->radio_dev->name,sizeof(cap->card)); + sprintf(cap->bus_info,"PCI:%s",pci_name(btv->c.pci)); + cap->version = BTTV_VERSION_CODE; + cap->capabilities = V4L2_CAP_TUNER; return 0; } - - case VIDIOCGTUNER: + case VIDIOC_G_TUNER: { - struct video_tuner *v = arg; + struct v4l2_tuner *t = arg; - if(v->tuner) + if (UNSET == bttv_tvcards[btv->c.type].tuner) return -EINVAL; - memset(v,0,sizeof(*v)); - strcpy(v->name, "Radio"); - bttv_call_i2c_clients(btv,cmd,v); + if (0 != t->index) + return -EINVAL; + mutex_lock(&btv->lock); + memset(t,0,sizeof(*t)); + strcpy(t->name, "Radio"); + t->type = V4L2_TUNER_RADIO; + + bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); + + mutex_unlock(&btv->lock); + return 0; } - case VIDIOCSTUNER: - /* nothing to do */ - return 0; - - case BTTV_VERSION: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: + case VIDIOC_S_TUNER: + case VIDIOC_G_FREQUENCY: + case VIDIOC_S_FREQUENCY: + case VIDIOC_G_CTRL: + case VIDIOC_S_CTRL: case VIDIOC_LOG_STATUS: case VIDIOC_DBG_G_REGISTER: case VIDIOC_DBG_S_REGISTER: return bttv_common_ioctls(btv,cmd,arg); - + case VIDIOCGCAP: + case VIDIOCGFREQ: + case VIDIOCSFREQ: + case VIDIOCGTUNER: + case VIDIOCSTUNER: + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + return v4l_compat_translate_ioctl(inode,file,cmd,arg, + radio_do_ioctl); default: return -ENOIOCTLCMD; } diff --git a/linux/drivers/media/video/bt8xx/bttvp.h b/linux/drivers/media/video/bt8xx/bttvp.h index c337b267c..1f27e74a9 100644 --- a/linux/drivers/media/video/bt8xx/bttvp.h +++ b/linux/drivers/media/video/bt8xx/bttvp.h @@ -476,10 +476,6 @@ struct bttv { extern unsigned int bttv_num; extern struct bttv bttvs[BTTV_MAX]; -/* private ioctls */ -#define BTTV_VERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int) -#define BTTV_VBISIZE _IOR('v' , BASE_VIDIOCPRIVATE+8, int) - #endif #define btwrite(dat,adr) writel((dat), btv->bt848_mmio+(adr)) -- cgit v1.2.3 From f7d8cfd0cd4b120216f408c6f2bf8137eafbb8ce Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Oct 2007 17:51:47 -0200 Subject: remove V4L1 from being compiled when V4L2 only is selected From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/bttv-driver.c | 95 ++++++-------------------- linux/drivers/media/video/bt8xx/bttvp.h | 1 2 files changed, 24 insertions(+), 72 deletions(-) --- linux/drivers/media/video/bt8xx/bttv-driver.c | 95 +++++++-------------------- linux/drivers/media/video/bt8xx/bttvp.h | 1 - 2 files changed, 24 insertions(+), 72 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index fce6c5324..bddcbf620 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -12,6 +12,9 @@ V4L1 removal from: (c) 2005-2006 Nickolay V. Shmyrev + Fixes to be fully V4L2 compliant by + (c) 2006 Mauro Carvalho Chehab + Cropping and overscan support Copyright (C) 2005, 2006 Michael H. Schimek Sponsored by OPQ Systems AB @@ -176,7 +179,7 @@ static ssize_t show_card(struct device *cd, static ssize_t show_card(struct class_device *cd, char *buf) #endif { - struct video_device *vfd = to_video_device(cd); + struct video_device *vfd = container_of(cd, struct video_device, class_dev); struct bttv *btv = dev_get_drvdata(vfd->dev); return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET); } @@ -505,28 +508,24 @@ static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms); static const struct bttv_format bttv_formats[] = { { .name = "8 bpp, gray", - .palette = VIDEO_PALETTE_GREY, .fourcc = V4L2_PIX_FMT_GREY, .btformat = BT848_COLOR_FMT_Y8, .depth = 8, .flags = FORMAT_FLAGS_PACKED, },{ .name = "8 bpp, dithered color", - .palette = VIDEO_PALETTE_HI240, .fourcc = V4L2_PIX_FMT_HI240, .btformat = BT848_COLOR_FMT_RGB8, .depth = 8, .flags = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER, },{ .name = "15 bpp RGB, le", - .palette = VIDEO_PALETTE_RGB555, .fourcc = V4L2_PIX_FMT_RGB555, .btformat = BT848_COLOR_FMT_RGB15, .depth = 16, .flags = FORMAT_FLAGS_PACKED, },{ .name = "15 bpp RGB, be", - .palette = -1, .fourcc = V4L2_PIX_FMT_RGB555X, .btformat = BT848_COLOR_FMT_RGB15, .btswap = 0x03, /* byteswap */ @@ -534,14 +533,12 @@ static const struct bttv_format bttv_formats[] = { .flags = FORMAT_FLAGS_PACKED, },{ .name = "16 bpp RGB, le", - .palette = VIDEO_PALETTE_RGB565, .fourcc = V4L2_PIX_FMT_RGB565, .btformat = BT848_COLOR_FMT_RGB16, .depth = 16, .flags = FORMAT_FLAGS_PACKED, },{ .name = "16 bpp RGB, be", - .palette = -1, .fourcc = V4L2_PIX_FMT_RGB565X, .btformat = BT848_COLOR_FMT_RGB16, .btswap = 0x03, /* byteswap */ @@ -549,21 +546,18 @@ static const struct bttv_format bttv_formats[] = { .flags = FORMAT_FLAGS_PACKED, },{ .name = "24 bpp RGB, le", - .palette = VIDEO_PALETTE_RGB24, .fourcc = V4L2_PIX_FMT_BGR24, .btformat = BT848_COLOR_FMT_RGB24, .depth = 24, .flags = FORMAT_FLAGS_PACKED, },{ .name = "32 bpp RGB, le", - .palette = VIDEO_PALETTE_RGB32, .fourcc = V4L2_PIX_FMT_BGR32, .btformat = BT848_COLOR_FMT_RGB32, .depth = 32, .flags = FORMAT_FLAGS_PACKED, },{ .name = "32 bpp RGB, be", - .palette = -1, .fourcc = V4L2_PIX_FMT_RGB32, .btformat = BT848_COLOR_FMT_RGB32, .btswap = 0x0f, /* byte+word swap */ @@ -571,21 +565,18 @@ static const struct bttv_format bttv_formats[] = { .flags = FORMAT_FLAGS_PACKED, },{ .name = "4:2:2, packed, YUYV", - .palette = VIDEO_PALETTE_YUV422, .fourcc = V4L2_PIX_FMT_YUYV, .btformat = BT848_COLOR_FMT_YUY2, .depth = 16, .flags = FORMAT_FLAGS_PACKED, },{ .name = "4:2:2, packed, YUYV", - .palette = VIDEO_PALETTE_YUYV, .fourcc = V4L2_PIX_FMT_YUYV, .btformat = BT848_COLOR_FMT_YUY2, .depth = 16, .flags = FORMAT_FLAGS_PACKED, },{ .name = "4:2:2, packed, UYVY", - .palette = VIDEO_PALETTE_UYVY, .fourcc = V4L2_PIX_FMT_UYVY, .btformat = BT848_COLOR_FMT_YUY2, .btswap = 0x03, /* byteswap */ @@ -593,7 +584,6 @@ static const struct bttv_format bttv_formats[] = { .flags = FORMAT_FLAGS_PACKED, },{ .name = "4:2:2, planar, Y-Cb-Cr", - .palette = VIDEO_PALETTE_YUV422P, .fourcc = V4L2_PIX_FMT_YUV422P, .btformat = BT848_COLOR_FMT_YCrCb422, .depth = 16, @@ -602,7 +592,6 @@ static const struct bttv_format bttv_formats[] = { .vshift = 0, },{ .name = "4:2:0, planar, Y-Cb-Cr", - .palette = VIDEO_PALETTE_YUV420P, .fourcc = V4L2_PIX_FMT_YUV420, .btformat = BT848_COLOR_FMT_YCrCb422, .depth = 12, @@ -611,7 +600,6 @@ static const struct bttv_format bttv_formats[] = { .vshift = 1, },{ .name = "4:2:0, planar, Y-Cr-Cb", - .palette = -1, .fourcc = V4L2_PIX_FMT_YVU420, .btformat = BT848_COLOR_FMT_YCrCb422, .depth = 12, @@ -620,7 +608,6 @@ static const struct bttv_format bttv_formats[] = { .vshift = 1, },{ .name = "4:1:1, planar, Y-Cb-Cr", - .palette = VIDEO_PALETTE_YUV411P, .fourcc = V4L2_PIX_FMT_YUV411P, .btformat = BT848_COLOR_FMT_YCrCb411, .depth = 12, @@ -629,7 +616,6 @@ static const struct bttv_format bttv_formats[] = { .vshift = 0, },{ .name = "4:1:0, planar, Y-Cb-Cr", - .palette = VIDEO_PALETTE_YUV410P, .fourcc = V4L2_PIX_FMT_YUV410, .btformat = BT848_COLOR_FMT_YCrCb411, .depth = 9, @@ -638,7 +624,6 @@ static const struct bttv_format bttv_formats[] = { .vshift = 2, },{ .name = "4:1:0, planar, Y-Cr-Cb", - .palette = -1, .fourcc = V4L2_PIX_FMT_YVU410, .btformat = BT848_COLOR_FMT_YCrCb411, .depth = 9, @@ -647,7 +632,6 @@ static const struct bttv_format bttv_formats[] = { .vshift = 2, },{ .name = "raw scanlines", - .palette = VIDEO_PALETTE_RAW, .fourcc = -1, .btformat = BT848_COLOR_FMT_RAW, .depth = 8, @@ -1491,7 +1475,6 @@ static void bttv_reinit_bt848(struct bttv *btv) static int get_control(struct bttv *btv, struct v4l2_control *c) { - struct video_audio va; int i; for (i = 0; i < BTTV_CTLS; i++) @@ -1499,7 +1482,10 @@ static int get_control(struct bttv *btv, struct v4l2_control *c) break; if (i == BTTV_CTLS) return -EINVAL; +#ifdef CONFIG_VIDEO_V4L1 if (btv->audio_hook && i >= 4 && i <= 8) { + struct video_audio va; + memset(&va,0,sizeof(va)); btv->audio_hook(btv,&va,0); switch (c->id) { @@ -1521,6 +1507,7 @@ static int get_control(struct bttv *btv, struct v4l2_control *c) } return 0; } +#endif switch (c->id) { case V4L2_CID_BRIGHTNESS: c->value = btv->bright; @@ -1584,7 +1571,6 @@ static int get_control(struct bttv *btv, struct v4l2_control *c) static int set_control(struct bttv *btv, struct v4l2_control *c) { - struct video_audio va; int i,val; for (i = 0; i < BTTV_CTLS; i++) @@ -1592,7 +1578,10 @@ static int set_control(struct bttv *btv, struct v4l2_control *c) break; if (i == BTTV_CTLS) return -EINVAL; +#ifdef CONFIG_VIDEO_V4L1 if (btv->audio_hook && i >= 4 && i <= 8) { + struct video_audio va; + memset(&va,0,sizeof(va)); btv->audio_hook(btv,&va,0); switch (c->id) { @@ -1622,6 +1611,7 @@ static int set_control(struct bttv *btv, struct v4l2_control *c) btv->audio_hook(btv,&va,1); return 0; } +#endif switch (c->id) { case V4L2_CID_BRIGHTNESS: bt848_bright(btv,c->value); @@ -1729,20 +1719,6 @@ static void bttv_field_count(struct bttv *btv) } } -static const struct bttv_format* -format_by_palette(int palette) -{ - unsigned int i; - - for (i = 0; i < BTTV_FORMATS; i++) { - if (-1 == bttv_formats[i].palette) - continue; - if (bttv_formats[i].palette == palette) - return bttv_formats+i; - } - return NULL; -} - static const struct bttv_format* format_by_fourcc(int fourcc) { @@ -1956,6 +1932,7 @@ static struct videobuf_queue_ops bttv_video_qops = { static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) { switch (cmd) { +#ifdef CONFIG_VIDEO_V4L1 case VIDIOCGAUDIO: { struct video_audio *v = arg; @@ -1994,7 +1971,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) mutex_unlock(&btv->lock); return 0; } - +#endif /* *** v4l2 *** ************************************************ */ case VIDIOC_ENUMSTD: { @@ -2101,6 +2078,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) return -EINVAL; mutex_lock(&btv->lock); bttv_call_i2c_clients(btv, VIDIOC_S_TUNER, t); +#ifdef CONFIG_VIDEO_V4L1 if (btv->audio_hook) { struct video_audio va; memset(&va, 0, sizeof(struct video_audio)); @@ -2115,6 +2093,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) va.mode = VIDEO_SOUND_LANG2; btv->audio_hook(btv,&va,1); } +#endif mutex_unlock(&btv->lock); return 0; } @@ -2741,28 +2720,6 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, return 0; } #endif - case VIDIOCGVBIFMT: - case VIDIOCSVBIFMT: - case VIDIOCSYNC: - case VIDIOCMCAPTURE: - case VIDIOCCAPTURE: - case VIDIOCGFBUF: - case VIDIOCSFBUF: - case VIDIOCGWIN: - case VIDIOCSWIN: - case VIDIOCGCAP: - case VIDIOCGPICT: - case VIDIOCSPICT: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGTUNER: - case VIDIOCSTUNER: - case VIDIOCGCHAN: - case VIDIOCSCHAN: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - return v4l_compat_translate_ioctl(inode,file,cmd,arg, - bttv_do_ioctl); /* *** v4l2 *** ************************************************ */ case VIDIOC_QUERYCAP: @@ -3016,6 +2973,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, return 0; } *c = bttv_ctls[i]; +#ifdef CONFIG_VIDEO_V4L1 if (btv->audio_hook && i >= 4 && i <= 8) { struct video_audio va; memset(&va,0,sizeof(va)); @@ -3039,6 +2997,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, break; } } +#endif return 0; } case VIDIOC_G_PARM: @@ -3070,7 +3029,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, t->type = V4L2_TUNER_ANALOG_TV; if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) t->signal = 0xffff; - +#ifdef CONFIG_VIDEO_V4L1 if (btv->audio_hook) { /* Hmmm ... */ struct video_audio va; @@ -3088,6 +3047,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, | V4L2_TUNER_SUB_LANG2; } } +#endif /* FIXME: fill capability+audmode */ mutex_unlock(&btv->lock); return 0; @@ -3239,7 +3199,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_DBG_S_REGISTER: return bttv_common_ioctls(btv,cmd,arg); default: - return -ENOIOCTLCMD; + return v4l_compat_translate_ioctl(inode,file,cmd,arg, + bttv_do_ioctl); } return 0; @@ -3599,17 +3560,9 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_DBG_G_REGISTER: case VIDIOC_DBG_S_REGISTER: return bttv_common_ioctls(btv,cmd,arg); - case VIDIOCGCAP: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGTUNER: - case VIDIOCSTUNER: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: + default: return v4l_compat_translate_ioctl(inode,file,cmd,arg, radio_do_ioctl); - default: - return -ENOIOCTLCMD; } return 0; } @@ -4419,7 +4372,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, btv->init.btv = btv; btv->init.ov.w.width = 320; btv->init.ov.w.height = 240; - btv->init.fmt = format_by_palette(VIDEO_PALETTE_RGB24); + btv->init.fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); btv->init.width = 320; btv->init.height = 240; btv->input = 0; diff --git a/linux/drivers/media/video/bt8xx/bttvp.h b/linux/drivers/media/video/bt8xx/bttvp.h index 1f27e74a9..e27b6a487 100644 --- a/linux/drivers/media/video/bt8xx/bttvp.h +++ b/linux/drivers/media/video/bt8xx/bttvp.h @@ -121,7 +121,6 @@ extern const struct bttv_tvnorm bttv_tvnorms[]; struct bttv_format { char *name; - int palette; /* video4linux 1 */ int fourcc; /* video4linux 2 */ int btformat; /* BT848_COLOR_FMT_* */ int btswap; /* BT848_COLOR_CTL_* */ -- cgit v1.2.3 From 9a4c4bb7abbb9174990491388b3b5b963a8e824e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Oct 2007 17:54:54 -0200 Subject: Audio hooks moved to another file From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/Makefile | 2 linux/drivers/media/video/bt8xx/bttv-audio-hook.c | 390 +++++++++++++++++++++ linux/drivers/media/video/bt8xx/bttv-audio-hook.h | 23 + linux/drivers/media/video/bt8xx/bttv-cards.c | 399 ---------------------- linux/drivers/media/video/bt8xx/bttv.h | 2 linux/drivers/media/video/bt8xx/bttvp.h | 3 6 files changed, 420 insertions(+), 399 deletions(-) --- linux/drivers/media/video/bt8xx/Makefile | 2 +- linux/drivers/media/video/bt8xx/bttv-audio-hook.c | 390 +++++++++++++++++++++ linux/drivers/media/video/bt8xx/bttv-audio-hook.h | 23 ++ linux/drivers/media/video/bt8xx/bttv-cards.c | 399 +--------------------- linux/drivers/media/video/bt8xx/bttv.h | 2 + linux/drivers/media/video/bt8xx/bttvp.h | 3 +- 6 files changed, 420 insertions(+), 399 deletions(-) create mode 100644 linux/drivers/media/video/bt8xx/bttv-audio-hook.c create mode 100644 linux/drivers/media/video/bt8xx/bttv-audio-hook.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/Makefile b/linux/drivers/media/video/bt8xx/Makefile index a096a0341..924d216d9 100644 --- a/linux/drivers/media/video/bt8xx/Makefile +++ b/linux/drivers/media/video/bt8xx/Makefile @@ -4,7 +4,7 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \ bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \ - bttv-input.o + bttv-input.o bttv-audio-hook.o obj-$(CONFIG_VIDEO_BT848) += bttv.o diff --git a/linux/drivers/media/video/bt8xx/bttv-audio-hook.c b/linux/drivers/media/video/bt8xx/bttv-audio-hook.c new file mode 100644 index 000000000..1e7fcaa25 --- /dev/null +++ b/linux/drivers/media/video/bt8xx/bttv-audio-hook.c @@ -0,0 +1,390 @@ +/* + * Handlers for board audio hooks, splitted from bttv-cards + * + * Copyright (c) 2006 Mauro Carvalho Chehab (mchehab@infradead.org) + * This code is placed under the terms of the GNU General Public License + */ + +/* ----------------------------------------------------------------------- */ +/* winview */ + +#include "bttvp.h" +#include + +static void winview_audio(struct bttv *btv, struct video_audio *v, int set) +{ + /* PT2254A programming Jon Tombs, jon@gte.esi.us.es */ + int bits_out, loops, vol, data; + + if (!set) { + /* Fixed by Leandro Lucarella flags |= VIDEO_AUDIO_VOLUME; + return; + } + + /* 32 levels logarithmic */ + vol = 32 - ((v->volume>>11)); + /* units */ + bits_out = (PT2254_DBS_IN_2>>(vol%5)); + /* tens */ + bits_out |= (PT2254_DBS_IN_10>>(vol/5)); + bits_out |= PT2254_L_CHANNEL | PT2254_R_CHANNEL; + data = gpio_read(); + data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA| + WINVIEW_PT2254_STROBE); + for (loops = 17; loops >= 0 ; loops--) { + if (bits_out & (1<mode & VIDEO_SOUND_LANG1) + con = 0x000; + if (v->mode & VIDEO_SOUND_LANG2) + con = 0x300; + if (v->mode & VIDEO_SOUND_STEREO) + con = 0x200; +/* if (v->mode & VIDEO_SOUND_MONO) + * con = 0x100; */ + gpio_bits(0x300, con); + } else { + v->mode = VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } +} + +static void +gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set) +{ + unsigned int val, con; + + if (btv->radio_user) + return; + + val = gpio_read(); + if (set) { + con = 0x000; + if (v->mode & VIDEO_SOUND_LANG2) { + if (v->mode & VIDEO_SOUND_LANG1) { + /* LANG1 + LANG2 */ + con = 0x100; + } + else { + /* LANG2 */ + con = 0x300; + } + } + if (con != (val & 0x300)) { + gpio_bits(0x300, con); + if (bttv_gpio) + bttv_gpio_tracking(btv,"gvbctv5pci"); + } + } else { + switch (val & 0x70) { + case 0x10: + v->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + break; + case 0x30: + v->mode = VIDEO_SOUND_LANG2; + break; + case 0x50: + v->mode = VIDEO_SOUND_LANG1; + break; + case 0x60: + v->mode = VIDEO_SOUND_STEREO; + break; + case 0x70: + v->mode = VIDEO_SOUND_MONO; + break; + default: + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } + } +} + +/* + * Mario Medina Nussbaum + * I discover that on BT848_GPIO_DATA address a byte 0xcce enable stereo, + * 0xdde enables mono and 0xccd enables sap + * + * Petr Vandrovec + * P.S.: At least mask in line above is wrong - GPIO pins 3,2 select + * input/output sound connection, so both must be set for output mode. + * + * Looks like it's needed only for the "tvphone", the "tvphone 98" + * handles this with a tda9840 + * + */ +static void +avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, int set) +{ + int val = 0; + + if (set) { + if (v->mode & VIDEO_SOUND_LANG2) /* SAP */ + val = 0x02; + if (v->mode & VIDEO_SOUND_STEREO) + val = 0x01; + if (val) { + gpio_bits(0x03,val); + if (bttv_gpio) + bttv_gpio_tracking(btv,"avermedia"); + } + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1; + return; + } +} + +static void +avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, int set) +{ + int val = 0; + + if (set) { + if (v->mode & VIDEO_SOUND_LANG2) /* SAP */ + val = 0x01; + if (v->mode & VIDEO_SOUND_STEREO) /* STEREO */ + val = 0x02; + btaor(val, ~0x03, BT848_GPIO_DATA); + if (bttv_gpio) + bttv_gpio_tracking(btv,"avermedia"); + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + return; + } +} + +/* Lifetec 9415 handling */ +static void +lt9415_audio(struct bttv *btv, struct video_audio *v, int set) +{ + int val = 0; + + if (gpio_read() & 0x4000) { + v->mode = VIDEO_SOUND_MONO; + return; + } + + if (set) { + if (v->mode & VIDEO_SOUND_LANG2) /* A2 SAP */ + val = 0x0080; + if (v->mode & VIDEO_SOUND_STEREO) /* A2 stereo */ + val = 0x0880; + if ((v->mode & VIDEO_SOUND_LANG1) || + (v->mode & VIDEO_SOUND_MONO)) + val = 0; + gpio_bits(0x0880, val); + if (bttv_gpio) + bttv_gpio_tracking(btv,"lt9415"); + } else { + /* autodetect doesn't work with this card :-( */ + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + return; + } +} + +/* TDA9821 on TerraTV+ Bt848, Bt878 */ +static void +terratv_audio(struct bttv *btv, struct video_audio *v, int set) +{ + unsigned int con = 0; + + if (set) { + gpio_inout(0x180000,0x180000); + if (v->mode & VIDEO_SOUND_LANG2) + con = 0x080000; + if (v->mode & VIDEO_SOUND_STEREO) + con = 0x180000; + gpio_bits(0x180000, con); + if (bttv_gpio) + bttv_gpio_tracking(btv,"terratv"); + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } +} + +static void +winfast2000_audio(struct bttv *btv, struct video_audio *v, int set) +{ + unsigned long val = 0; + + if (set) { + /*btor (0xc32000, BT848_GPIO_OUT_EN);*/ + if (v->mode & VIDEO_SOUND_MONO) /* Mono */ + val = 0x420000; + if (v->mode & VIDEO_SOUND_LANG1) /* Mono */ + val = 0x420000; + if (v->mode & VIDEO_SOUND_LANG2) /* SAP */ + val = 0x410000; + if (v->mode & VIDEO_SOUND_STEREO) /* Stereo */ + val = 0x020000; + if (val) { + gpio_bits(0x430000, val); + if (bttv_gpio) + bttv_gpio_tracking(btv,"winfast2000"); + } + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } +} + +/* + * Dariusz Kowalewski + * sound control for Prolink PV-BT878P+9B (PixelView PlayTV Pro FM+NICAM + * revision 9B has on-board TDA9874A sound decoder). + * + * Note: There are card variants without tda9874a. Forcing the "stereo sound route" + * will mute this cards. + */ +static void +pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set) +{ + unsigned int val = 0; + + if (btv->radio_user) + return; + + if (set) { + if (v->mode & VIDEO_SOUND_MONO) { + val = 0x01; + } + if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2)) + || (v->mode & VIDEO_SOUND_STEREO)) { + val = 0x02; + } + if (val) { + gpio_bits(0x03,val); + if (bttv_gpio) + bttv_gpio_tracking(btv,"pvbt878p9b"); + } + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } +} + +/* + * Dariusz Kowalewski + * sound control for FlyVideo 2000S (with tda9874 decoder) + * based on pvbt878p9b_audio() - this is not tested, please fix!!! + */ +static void +fv2000s_audio(struct bttv *btv, struct video_audio *v, int set) +{ + unsigned int val = 0xffff; + + if (btv->radio_user) + return; + + if (set) { + if (v->mode & VIDEO_SOUND_MONO) { + val = 0x0000; + } + if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2)) + || (v->mode & VIDEO_SOUND_STEREO)) { + val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */ + } + if (val != 0xffff) { + gpio_bits(0x1800, val); + if (bttv_gpio) + bttv_gpio_tracking(btv,"fv2000s"); + } + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } +} + +/* + * sound control for Canopus WinDVR PCI + * Masaki Suzuki + */ +static void +windvr_audio(struct bttv *btv, struct video_audio *v, int set) +{ + unsigned long val = 0; + + if (set) { + if (v->mode & VIDEO_SOUND_MONO) + val = 0x040000; + if (v->mode & VIDEO_SOUND_LANG1) + val = 0; + if (v->mode & VIDEO_SOUND_LANG2) + val = 0x100000; + if (v->mode & VIDEO_SOUND_STEREO) + val = 0; + if (val) { + gpio_bits(0x140000, val); + if (bttv_gpio) + bttv_gpio_tracking(btv,"windvr"); + } + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } +} + +/* + * sound control for AD-TVK503 + * Hiroshi Takekawa + */ +static void +adtvk503_audio(struct bttv *btv, struct video_audio *v, int set) +{ + unsigned int con = 0xffffff; + + /* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */ + + if (set) { + /* btor(***, BT848_GPIO_OUT_EN); */ + if (v->mode & VIDEO_SOUND_LANG1) + con = 0x00000000; + if (v->mode & VIDEO_SOUND_LANG2) + con = 0x00180000; + if (v->mode & VIDEO_SOUND_STEREO) + con = 0x00000000; + if (v->mode & VIDEO_SOUND_MONO) + con = 0x00060000; + if (con != 0xffffff) { + gpio_bits(0x1e0000,con); + if (bttv_gpio) + bttv_gpio_tracking(btv, "adtvk503"); + } + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } +} diff --git a/linux/drivers/media/video/bt8xx/bttv-audio-hook.h b/linux/drivers/media/video/bt8xx/bttv-audio-hook.h new file mode 100644 index 000000000..9770cacc1 --- /dev/null +++ b/linux/drivers/media/video/bt8xx/bttv-audio-hook.h @@ -0,0 +1,23 @@ +/* + * Handlers for board audio hooks, splitted from bttv-cards + * + * Copyright (c) 2006 Mauro Carvalho Chehab (mchehab@infradead.org) + * This code is placed under the terms of the GNU General Public License + */ + +#include "bttvp.h" + +static void winview_audio(struct bttv *btv, struct video_audio *v, int set); +static void lt9415_audio(struct bttv *btv, struct video_audio *v, int set); +static void avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, + int set); +static void avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, + int set); +static void terratv_audio(struct bttv *btv, struct video_audio *v, int set); +static void gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set); +static void gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set); +static void winfast2000_audio(struct bttv *btv, struct video_audio *v, int set); +static void pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set); +static void fv2000s_audio(struct bttv *btv, struct video_audio *v, int set); +static void windvr_audio(struct bttv *btv, struct video_audio *v, int set); +static void adtvk503_audio(struct bttv *btv, struct video_audio *v, int set); diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index c45c0e9ae..9bb671855 100644 --- a/linux/drivers/media/video/bt8xx/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c @@ -43,6 +43,7 @@ #if 0 /* not working yet */ #include "bt832.h" #endif +#include "bttv-audio-hook.h" /* fwd decl */ static void boot_msp34xx(struct bttv *btv, int pin); @@ -54,20 +55,6 @@ static void modtec_eeprom(struct bttv *btv); static void init_PXC200(struct bttv *btv); static void init_RTV24(struct bttv *btv); -static void winview_audio(struct bttv *btv, struct video_audio *v, int set); -static void lt9415_audio(struct bttv *btv, struct video_audio *v, int set); -static void avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, - int set); -static void avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, - int set); -static void terratv_audio(struct bttv *btv, struct video_audio *v, int set); -static void gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set); -static void gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set); -static void winfast2000_audio(struct bttv *btv, struct video_audio *v, int set); -static void pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set); -static void fv2000s_audio(struct bttv *btv, struct video_audio *v, int set); -static void windvr_audio(struct bttv *btv, struct video_audio *v, int set); -static void adtvk503_audio(struct bttv *btv, struct video_audio *v, int set); static void rv605_muxsel(struct bttv *btv, unsigned int input); static void eagle_muxsel(struct bttv *btv, unsigned int input); static void xguard_muxsel(struct bttv *btv, unsigned int input); @@ -4020,7 +4007,7 @@ static void __devinit avermedia_eeprom(struct bttv *btv) void bttv_tda9880_setnorm(struct bttv *btv, int norm) { /* fix up our card entry */ - if(norm==VIDEO_MODE_NTSC) { + if(norm==V4L2_STD_NTSC) { bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomux[TVAUDIO_INPUT_TUNER]=0x957fff; bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomute=0x957fff; bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomux[TVAUDIO_INPUT_TUNER]=0x957fff; @@ -4424,388 +4411,6 @@ void tea5757_set_freq(struct bttv *btv, unsigned short freq) #endif } - -/* ----------------------------------------------------------------------- */ -/* winview */ - -static void winview_audio(struct bttv *btv, struct video_audio *v, int set) -{ - /* PT2254A programming Jon Tombs, jon@gte.esi.us.es */ - int bits_out, loops, vol, data; - - if (!set) { - /* Fixed by Leandro Lucarella flags |= VIDEO_AUDIO_VOLUME; - return; - } - - /* 32 levels logarithmic */ - vol = 32 - ((v->volume>>11)); - /* units */ - bits_out = (PT2254_DBS_IN_2>>(vol%5)); - /* tens */ - bits_out |= (PT2254_DBS_IN_10>>(vol/5)); - bits_out |= PT2254_L_CHANNEL | PT2254_R_CHANNEL; - data = gpio_read(); - data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA| - WINVIEW_PT2254_STROBE); - for (loops = 17; loops >= 0 ; loops--) { - if (bits_out & (1<mode & VIDEO_SOUND_LANG1) - con = 0x000; - if (v->mode & VIDEO_SOUND_LANG2) - con = 0x300; - if (v->mode & VIDEO_SOUND_STEREO) - con = 0x200; -/* if (v->mode & VIDEO_SOUND_MONO) - * con = 0x100; */ - gpio_bits(0x300, con); - } else { - v->mode = VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } -} - -static void -gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set) -{ - unsigned int val, con; - - if (btv->radio_user) - return; - - val = gpio_read(); - if (set) { - con = 0x000; - if (v->mode & VIDEO_SOUND_LANG2) { - if (v->mode & VIDEO_SOUND_LANG1) { - /* LANG1 + LANG2 */ - con = 0x100; - } - else { - /* LANG2 */ - con = 0x300; - } - } - if (con != (val & 0x300)) { - gpio_bits(0x300, con); - if (bttv_gpio) - bttv_gpio_tracking(btv,"gvbctv5pci"); - } - } else { - switch (val & 0x70) { - case 0x10: - v->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - break; - case 0x30: - v->mode = VIDEO_SOUND_LANG2; - break; - case 0x50: - v->mode = VIDEO_SOUND_LANG1; - break; - case 0x60: - v->mode = VIDEO_SOUND_STEREO; - break; - case 0x70: - v->mode = VIDEO_SOUND_MONO; - break; - default: - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } - } -} - -/* - * Mario Medina Nussbaum - * I discover that on BT848_GPIO_DATA address a byte 0xcce enable stereo, - * 0xdde enables mono and 0xccd enables sap - * - * Petr Vandrovec - * P.S.: At least mask in line above is wrong - GPIO pins 3,2 select - * input/output sound connection, so both must be set for output mode. - * - * Looks like it's needed only for the "tvphone", the "tvphone 98" - * handles this with a tda9840 - * - */ -static void -avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, int set) -{ - int val = 0; - - if (set) { - if (v->mode & VIDEO_SOUND_LANG2) /* SAP */ - val = 0x02; - if (v->mode & VIDEO_SOUND_STEREO) - val = 0x01; - if (val) { - gpio_bits(0x03,val); - if (bttv_gpio) - bttv_gpio_tracking(btv,"avermedia"); - } - } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1; - return; - } -} - -static void -avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, int set) -{ - int val = 0; - - if (set) { - if (v->mode & VIDEO_SOUND_LANG2) /* SAP */ - val = 0x01; - if (v->mode & VIDEO_SOUND_STEREO) /* STEREO */ - val = 0x02; - btaor(val, ~0x03, BT848_GPIO_DATA); - if (bttv_gpio) - bttv_gpio_tracking(btv,"avermedia"); - } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - return; - } -} - -/* Lifetec 9415 handling */ -static void -lt9415_audio(struct bttv *btv, struct video_audio *v, int set) -{ - int val = 0; - - if (gpio_read() & 0x4000) { - v->mode = VIDEO_SOUND_MONO; - return; - } - - if (set) { - if (v->mode & VIDEO_SOUND_LANG2) /* A2 SAP */ - val = 0x0080; - if (v->mode & VIDEO_SOUND_STEREO) /* A2 stereo */ - val = 0x0880; - if ((v->mode & VIDEO_SOUND_LANG1) || - (v->mode & VIDEO_SOUND_MONO)) - val = 0; - gpio_bits(0x0880, val); - if (bttv_gpio) - bttv_gpio_tracking(btv,"lt9415"); - } else { - /* autodetect doesn't work with this card :-( */ - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - return; - } -} - -/* TDA9821 on TerraTV+ Bt848, Bt878 */ -static void -terratv_audio(struct bttv *btv, struct video_audio *v, int set) -{ - unsigned int con = 0; - - if (set) { - gpio_inout(0x180000,0x180000); - if (v->mode & VIDEO_SOUND_LANG2) - con = 0x080000; - if (v->mode & VIDEO_SOUND_STEREO) - con = 0x180000; - gpio_bits(0x180000, con); - if (bttv_gpio) - bttv_gpio_tracking(btv,"terratv"); - } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } -} - -static void -winfast2000_audio(struct bttv *btv, struct video_audio *v, int set) -{ - unsigned long val = 0; - - if (set) { - /*btor (0xc32000, BT848_GPIO_OUT_EN);*/ - if (v->mode & VIDEO_SOUND_MONO) /* Mono */ - val = 0x420000; - if (v->mode & VIDEO_SOUND_LANG1) /* Mono */ - val = 0x420000; - if (v->mode & VIDEO_SOUND_LANG2) /* SAP */ - val = 0x410000; - if (v->mode & VIDEO_SOUND_STEREO) /* Stereo */ - val = 0x020000; - if (val) { - gpio_bits(0x430000, val); - if (bttv_gpio) - bttv_gpio_tracking(btv,"winfast2000"); - } - } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } -} - -/* - * Dariusz Kowalewski - * sound control for Prolink PV-BT878P+9B (PixelView PlayTV Pro FM+NICAM - * revision 9B has on-board TDA9874A sound decoder). - * - * Note: There are card variants without tda9874a. Forcing the "stereo sound route" - * will mute this cards. - */ -static void -pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set) -{ - unsigned int val = 0; - - if (btv->radio_user) - return; - - if (set) { - if (v->mode & VIDEO_SOUND_MONO) { - val = 0x01; - } - if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2)) - || (v->mode & VIDEO_SOUND_STEREO)) { - val = 0x02; - } - if (val) { - gpio_bits(0x03,val); - if (bttv_gpio) - bttv_gpio_tracking(btv,"pvbt878p9b"); - } - } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } -} - -/* - * Dariusz Kowalewski - * sound control for FlyVideo 2000S (with tda9874 decoder) - * based on pvbt878p9b_audio() - this is not tested, please fix!!! - */ -static void -fv2000s_audio(struct bttv *btv, struct video_audio *v, int set) -{ - unsigned int val = 0xffff; - - if (btv->radio_user) - return; - - if (set) { - if (v->mode & VIDEO_SOUND_MONO) { - val = 0x0000; - } - if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2)) - || (v->mode & VIDEO_SOUND_STEREO)) { - val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */ - } - if (val != 0xffff) { - gpio_bits(0x1800, val); - if (bttv_gpio) - bttv_gpio_tracking(btv,"fv2000s"); - } - } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } -} - -/* - * sound control for Canopus WinDVR PCI - * Masaki Suzuki - */ -static void -windvr_audio(struct bttv *btv, struct video_audio *v, int set) -{ - unsigned long val = 0; - - if (set) { - if (v->mode & VIDEO_SOUND_MONO) - val = 0x040000; - if (v->mode & VIDEO_SOUND_LANG1) - val = 0; - if (v->mode & VIDEO_SOUND_LANG2) - val = 0x100000; - if (v->mode & VIDEO_SOUND_STEREO) - val = 0; - if (val) { - gpio_bits(0x140000, val); - if (bttv_gpio) - bttv_gpio_tracking(btv,"windvr"); - } - } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } -} - -/* - * sound control for AD-TVK503 - * Hiroshi Takekawa - */ -static void -adtvk503_audio(struct bttv *btv, struct video_audio *v, int set) -{ - unsigned int con = 0xffffff; - - /* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */ - - if (set) { - /* btor(***, BT848_GPIO_OUT_EN); */ - if (v->mode & VIDEO_SOUND_LANG1) - con = 0x00000000; - if (v->mode & VIDEO_SOUND_LANG2) - con = 0x00180000; - if (v->mode & VIDEO_SOUND_STEREO) - con = 0x00000000; - if (v->mode & VIDEO_SOUND_MONO) - con = 0x00060000; - if (con != 0xffffff) { - gpio_bits(0x1e0000,con); - if (bttv_gpio) - bttv_gpio_tracking(btv, "adtvk503"); - } - } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } -} - /* RemoteVision MX (rv605) muxsel helper [Miguel Freitas] * * This is needed because rv605 don't use a normal multiplex, but a crosspoint diff --git a/linux/drivers/media/video/bt8xx/bttv.h b/linux/drivers/media/video/bt8xx/bttv.h index 66e93402d..d943b1fca 100644 --- a/linux/drivers/media/video/bt8xx/bttv.h +++ b/linux/drivers/media/video/bt8xx/bttv.h @@ -242,7 +242,9 @@ struct tvcard unsigned int radio_addr; unsigned int has_radio; +#ifdef CONFIG_VIDEO_V4L1 void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); +#endif void (*muxsel_hook)(struct bttv *btv, unsigned int input); }; diff --git a/linux/drivers/media/video/bt8xx/bttvp.h b/linux/drivers/media/video/bt8xx/bttvp.h index e27b6a487..ce132b58b 100644 --- a/linux/drivers/media/video/bt8xx/bttvp.h +++ b/linux/drivers/media/video/bt8xx/bttvp.h @@ -350,8 +350,9 @@ struct bttv { /* old gpio interface */ wait_queue_head_t gpioq; int shutdown; +#ifdef CONFIG_VIDEO_V4L1 void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); - +#endif /* new gpio interface */ spinlock_t gpio_lock; -- cgit v1.2.3 From 5bb33fe25ae2e49d52b945f25504c51ee116c3ee Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 25 Aug 2006 16:53:02 -0300 Subject: Forward VIDIOCGAUDIO and VIDIOCSAUDIO through v4l1-compat From: Nickolay V. Shmyrev Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/bttv-driver.c | 41 -------------------------- 1 file changed, 41 deletions(-) --- linux/drivers/media/video/bt8xx/bttv-driver.c | 41 --------------------------- 1 file changed, 41 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index bddcbf620..0c3a98955 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -1932,47 +1932,6 @@ static struct videobuf_queue_ops bttv_video_qops = { static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) { switch (cmd) { -#ifdef CONFIG_VIDEO_V4L1 - case VIDIOCGAUDIO: - { - struct video_audio *v = arg; - - memset(v,0,sizeof(*v)); - strcpy(v->name,"Television"); - v->flags |= VIDEO_AUDIO_MUTABLE; - v->mode = VIDEO_SOUND_MONO; - - mutex_lock(&btv->lock); - bttv_call_i2c_clients(btv,cmd,v); - - /* card specific hooks */ - if (btv->audio_hook) - btv->audio_hook(btv,v,0); - - mutex_unlock(&btv->lock); - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio *v = arg; - unsigned int audio = v->audio; - - if (audio >= bttv_tvcards[btv->c.type].audio_inputs) - return -EINVAL; - - mutex_lock(&btv->lock); - audio_mute(btv, (v->flags&VIDEO_AUDIO_MUTE) ? 1 : 0); - bttv_call_i2c_clients(btv,cmd,v); - - /* card specific hooks */ - if (btv->audio_hook) - btv->audio_hook(btv,v,1); - - mutex_unlock(&btv->lock); - return 0; - } -#endif - /* *** v4l2 *** ************************************************ */ case VIDIOC_ENUMSTD: { struct v4l2_standard *e = arg; -- cgit v1.2.3 From 6931c49714b2a66d311fd0ddce8aaa7ee48c94fd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Oct 2007 18:15:19 -0200 Subject: Remove bass, treble and balance from audio hook since they are unused From: Nickolay V. Shmyrev Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/bttv-driver.c | 30 -------------------------- v4l/versions.txt | 2 - 2 files changed, 1 insertion(+), 31 deletions(-) --- linux/drivers/media/video/bt8xx/bttv-driver.c | 30 --------------------------- 1 file changed, 30 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index 0c3a98955..7179f2d54 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -1495,15 +1495,6 @@ static int get_control(struct bttv *btv, struct v4l2_control *c) case V4L2_CID_AUDIO_VOLUME: c->value = va.volume; break; - case V4L2_CID_AUDIO_BALANCE: - c->value = va.balance; - break; - case V4L2_CID_AUDIO_BASS: - c->value = va.bass; - break; - case V4L2_CID_AUDIO_TREBLE: - c->value = va.treble; - break; } return 0; } @@ -1598,15 +1589,6 @@ static int set_control(struct bttv *btv, struct v4l2_control *c) case V4L2_CID_AUDIO_VOLUME: va.volume = c->value; break; - case V4L2_CID_AUDIO_BALANCE: - va.balance = c->value; - break; - case V4L2_CID_AUDIO_BASS: - va.bass = c->value; - break; - case V4L2_CID_AUDIO_TREBLE: - va.treble = c->value; - break; } btv->audio_hook(btv,&va,1); return 0; @@ -2942,18 +2924,6 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (!(va.flags & VIDEO_AUDIO_VOLUME)) *c = no_ctl; break; - case V4L2_CID_AUDIO_BALANCE: - if (!(va.flags & VIDEO_AUDIO_BALANCE)) - *c = no_ctl; - break; - case V4L2_CID_AUDIO_BASS: - if (!(va.flags & VIDEO_AUDIO_BASS)) - *c = no_ctl; - break; - case V4L2_CID_AUDIO_TREBLE: - if (!(va.flags & VIDEO_AUDIO_TREBLE)) - *c = no_ctl; - break; } } #endif -- cgit v1.2.3 From fc1f956eca9a6e77bd988271fe023dd49ea12d34 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Oct 2007 18:21:30 -0200 Subject: Restructurize volume hook and drop unused mute hook. From: Nickolay V. Shmyrev Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/bttv-audio-hook.c | 29 +++++++++----------- linux/drivers/media/video/bt8xx/bttv-driver.c | 31 ++-------------------- 2 files changed, 17 insertions(+), 43 deletions(-) --- linux/drivers/media/video/bt8xx/bttv-audio-hook.c | 29 ++++++++++----------- linux/drivers/media/video/bt8xx/bttv-driver.c | 31 +++-------------------- 2 files changed, 17 insertions(+), 43 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-audio-hook.c b/linux/drivers/media/video/bt8xx/bttv-audio-hook.c index 1e7fcaa25..1f25cdbed 100644 --- a/linux/drivers/media/video/bt8xx/bttv-audio-hook.c +++ b/linux/drivers/media/video/bt8xx/bttv-audio-hook.c @@ -5,13 +5,12 @@ * This code is placed under the terms of the GNU General Public License */ +#include "bttv-audio-hook.h" + /* ----------------------------------------------------------------------- */ /* winview */ -#include "bttvp.h" -#include - -static void winview_audio(struct bttv *btv, struct video_audio *v, int set) + void winview_audio(struct bttv *btv, struct video_audio *v, int set) { /* PT2254A programming Jon Tombs, jon@gte.esi.us.es */ int bits_out, loops, vol, data; @@ -57,7 +56,7 @@ static void winview_audio(struct bttv *btv, struct video_audio *v, int set) /* mono/stereo control for various cards (which don't use i2c chips but */ /* connect something to the GPIO pins */ -static void + void gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set) { unsigned int con = 0; @@ -79,7 +78,7 @@ gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set) } } -static void + void gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set) { unsigned int val, con; @@ -142,7 +141,7 @@ gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set) * handles this with a tda9840 * */ -static void + void avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, int set) { int val = 0; @@ -164,7 +163,7 @@ avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, int set) } } -static void + void avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, int set) { int val = 0; @@ -185,7 +184,7 @@ avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, int set) } /* Lifetec 9415 handling */ -static void + void lt9415_audio(struct bttv *btv, struct video_audio *v, int set) { int val = 0; @@ -215,7 +214,7 @@ lt9415_audio(struct bttv *btv, struct video_audio *v, int set) } /* TDA9821 on TerraTV+ Bt848, Bt878 */ -static void + void terratv_audio(struct bttv *btv, struct video_audio *v, int set) { unsigned int con = 0; @@ -235,7 +234,7 @@ terratv_audio(struct bttv *btv, struct video_audio *v, int set) } } -static void + void winfast2000_audio(struct bttv *btv, struct video_audio *v, int set) { unsigned long val = 0; @@ -269,7 +268,7 @@ winfast2000_audio(struct bttv *btv, struct video_audio *v, int set) * Note: There are card variants without tda9874a. Forcing the "stereo sound route" * will mute this cards. */ -static void + void pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set) { unsigned int val = 0; @@ -301,7 +300,7 @@ pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set) * sound control for FlyVideo 2000S (with tda9874 decoder) * based on pvbt878p9b_audio() - this is not tested, please fix!!! */ -static void + void fv2000s_audio(struct bttv *btv, struct video_audio *v, int set) { unsigned int val = 0xffff; @@ -332,7 +331,7 @@ fv2000s_audio(struct bttv *btv, struct video_audio *v, int set) * sound control for Canopus WinDVR PCI * Masaki Suzuki */ -static void + void windvr_audio(struct bttv *btv, struct video_audio *v, int set) { unsigned long val = 0; @@ -361,7 +360,7 @@ windvr_audio(struct bttv *btv, struct video_audio *v, int set) * sound control for AD-TVK503 * Hiroshi Takekawa */ -static void + void adtvk503_audio(struct bttv *btv, struct video_audio *v, int set) { unsigned int con = 0xffffff; diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index 7179f2d54..e3f53a721 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -1475,23 +1475,13 @@ static void bttv_reinit_bt848(struct bttv *btv) static int get_control(struct bttv *btv, struct v4l2_control *c) { - int i; - - for (i = 0; i < BTTV_CTLS; i++) - if (bttv_ctls[i].id == c->id) - break; - if (i == BTTV_CTLS) - return -EINVAL; #ifdef CONFIG_VIDEO_V4L1 - if (btv->audio_hook && i >= 4 && i <= 8) { + if (btv->audio_hook && (c->id == V4L2_CID_AUDIO_VOLUME)) { struct video_audio va; memset(&va,0,sizeof(va)); btv->audio_hook(btv,&va,0); switch (c->id) { - case V4L2_CID_AUDIO_MUTE: - c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0; - break; case V4L2_CID_AUDIO_VOLUME: c->value = va.volume; break; @@ -1562,30 +1552,15 @@ static int get_control(struct bttv *btv, struct v4l2_control *c) static int set_control(struct bttv *btv, struct v4l2_control *c) { - int i,val; + int val; - for (i = 0; i < BTTV_CTLS; i++) - if (bttv_ctls[i].id == c->id) - break; - if (i == BTTV_CTLS) - return -EINVAL; #ifdef CONFIG_VIDEO_V4L1 - if (btv->audio_hook && i >= 4 && i <= 8) { + if (btv->audio_hook && (c->id == V4L2_CID_AUDIO_VOLUME)) { struct video_audio va; memset(&va,0,sizeof(va)); btv->audio_hook(btv,&va,0); switch (c->id) { - case V4L2_CID_AUDIO_MUTE: - if (c->value) { - va.flags |= VIDEO_AUDIO_MUTE; - audio_mute(btv, 1); - } else { - va.flags &= ~VIDEO_AUDIO_MUTE; - audio_mute(btv, 0); - } - break; - case V4L2_CID_AUDIO_VOLUME: va.volume = c->value; break; -- cgit v1.2.3 From ba37c220adc7b3dac0ec2ff292d53afd9316a9ce Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 25 Aug 2006 16:53:04 -0300 Subject: Split hooks on volume and audio mode and rework their handling Also convert audio_mode_gpio functions from audio_hook From: Nickolay V. Shmyrev Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/bttv-audio-hook.c | 173 ++++++++++------------ linux/drivers/media/video/bt8xx/bttv-audio-hook.h | 28 +-- linux/drivers/media/video/bt8xx/bttv-cards.c | 38 ++-- linux/drivers/media/video/bt8xx/bttv-driver.c | 97 ++---------- linux/drivers/media/video/bt8xx/bttv.h | 7 linux/drivers/media/video/bt8xx/bttvp.h | 7 6 files changed, 144 insertions(+), 206 deletions(-) --- linux/drivers/media/video/bt8xx/bttv-audio-hook.c | 173 ++++++++++------------ linux/drivers/media/video/bt8xx/bttv-audio-hook.h | 28 ++-- linux/drivers/media/video/bt8xx/bttv-cards.c | 38 ++--- linux/drivers/media/video/bt8xx/bttv-driver.c | 97 +++--------- linux/drivers/media/video/bt8xx/bttv.h | 7 +- linux/drivers/media/video/bt8xx/bttvp.h | 7 +- 6 files changed, 144 insertions(+), 206 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-audio-hook.c b/linux/drivers/media/video/bt8xx/bttv-audio-hook.c index 1f25cdbed..a075198f8 100644 --- a/linux/drivers/media/video/bt8xx/bttv-audio-hook.c +++ b/linux/drivers/media/video/bt8xx/bttv-audio-hook.c @@ -7,22 +7,18 @@ #include "bttv-audio-hook.h" +#include + /* ----------------------------------------------------------------------- */ /* winview */ - void winview_audio(struct bttv *btv, struct video_audio *v, int set) +void winview_volume(struct bttv *btv, __u16 volume) { /* PT2254A programming Jon Tombs, jon@gte.esi.us.es */ int bits_out, loops, vol, data; - if (!set) { - /* Fixed by Leandro Lucarella flags |= VIDEO_AUDIO_VOLUME; - return; - } - /* 32 levels logarithmic */ - vol = 32 - ((v->volume>>11)); + vol = 32 - ((volume>>11)); /* units */ bits_out = (PT2254_DBS_IN_2>>(vol%5)); /* tens */ @@ -56,30 +52,28 @@ /* mono/stereo control for various cards (which don't use i2c chips but */ /* connect something to the GPIO pins */ - void -gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set) +void gvbctv3pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set) { unsigned int con = 0; if (set) { gpio_inout(0x300, 0x300); - if (v->mode & VIDEO_SOUND_LANG1) + if (t->audmode & V4L2_TUNER_MODE_LANG1) con = 0x000; - if (v->mode & VIDEO_SOUND_LANG2) + if (t->audmode & V4L2_TUNER_MODE_LANG2) con = 0x300; - if (v->mode & VIDEO_SOUND_STEREO) + if (t->audmode & V4L2_TUNER_MODE_STEREO) con = 0x200; -/* if (v->mode & VIDEO_SOUND_MONO) +/* if (t->audmode & V4L2_TUNER_MODE_MONO) * con = 0x100; */ gpio_bits(0x300, con); } else { - v->mode = VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + t->audmode = V4L2_TUNER_MODE_STEREO | + V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; } } - void -gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set) +void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set) { unsigned int val, con; @@ -89,8 +83,8 @@ gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set) val = gpio_read(); if (set) { con = 0x000; - if (v->mode & VIDEO_SOUND_LANG2) { - if (v->mode & VIDEO_SOUND_LANG1) { + if (t->audmode & V4L2_TUNER_MODE_LANG2) { + if (t->audmode & V4L2_TUNER_MODE_LANG1) { /* LANG1 + LANG2 */ con = 0x100; } @@ -107,23 +101,23 @@ gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set) } else { switch (val & 0x70) { case 0x10: - v->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + t->audmode = V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; break; case 0x30: - v->mode = VIDEO_SOUND_LANG2; + t->audmode = V4L2_TUNER_MODE_LANG2; break; case 0x50: - v->mode = VIDEO_SOUND_LANG1; + t->audmode = V4L2_TUNER_MODE_LANG1; break; case 0x60: - v->mode = VIDEO_SOUND_STEREO; + t->audmode = V4L2_TUNER_MODE_STEREO; break; case 0x70: - v->mode = VIDEO_SOUND_MONO; + t->audmode = V4L2_TUNER_MODE_MONO; break; default: - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO | + V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; } } } @@ -141,15 +135,15 @@ gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set) * handles this with a tda9840 * */ - void -avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, int set) + +void avermedia_tvphone_audio(struct bttv *btv, struct v4l2_tuner *t, int set) { int val = 0; if (set) { - if (v->mode & VIDEO_SOUND_LANG2) /* SAP */ + if (t->audmode & V4L2_TUNER_MODE_LANG2) /* SAP */ val = 0x02; - if (v->mode & VIDEO_SOUND_STEREO) + if (t->audmode & V4L2_TUNER_MODE_STEREO) val = 0x01; if (val) { gpio_bits(0x03,val); @@ -157,97 +151,96 @@ avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, int set) bttv_gpio_tracking(btv,"avermedia"); } } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1; + t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO | + V4L2_TUNER_MODE_LANG1; return; } } - void -avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, int set) + +void avermedia_tv_stereo_audio(struct bttv *btv, struct v4l2_tuner *t, int set) { int val = 0; if (set) { - if (v->mode & VIDEO_SOUND_LANG2) /* SAP */ + if (t->audmode & V4L2_TUNER_MODE_LANG2) /* SAP */ val = 0x01; - if (v->mode & VIDEO_SOUND_STEREO) /* STEREO */ + if (t->audmode & V4L2_TUNER_MODE_STEREO) /* STEREO */ val = 0x02; btaor(val, ~0x03, BT848_GPIO_DATA); if (bttv_gpio) bttv_gpio_tracking(btv,"avermedia"); } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO | + V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; return; } } /* Lifetec 9415 handling */ - void -lt9415_audio(struct bttv *btv, struct video_audio *v, int set) + +void lt9415_audio(struct bttv *btv, struct v4l2_tuner *t, int set) { int val = 0; if (gpio_read() & 0x4000) { - v->mode = VIDEO_SOUND_MONO; + t->audmode = V4L2_TUNER_MODE_MONO; return; } if (set) { - if (v->mode & VIDEO_SOUND_LANG2) /* A2 SAP */ + if (t->audmode & V4L2_TUNER_MODE_LANG2) /* A2 SAP */ val = 0x0080; - if (v->mode & VIDEO_SOUND_STEREO) /* A2 stereo */ + if (t->audmode & V4L2_TUNER_MODE_STEREO) /* A2 stereo */ val = 0x0880; - if ((v->mode & VIDEO_SOUND_LANG1) || - (v->mode & VIDEO_SOUND_MONO)) + if ((t->audmode & V4L2_TUNER_MODE_LANG1) || + (t->audmode & V4L2_TUNER_MODE_MONO)) val = 0; gpio_bits(0x0880, val); if (bttv_gpio) bttv_gpio_tracking(btv,"lt9415"); } else { /* autodetect doesn't work with this card :-( */ - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO | + V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; return; } } /* TDA9821 on TerraTV+ Bt848, Bt878 */ - void -terratv_audio(struct bttv *btv, struct video_audio *v, int set) +void terratv_audio(struct bttv *btv, struct v4l2_tuner *t, int set) { unsigned int con = 0; if (set) { gpio_inout(0x180000,0x180000); - if (v->mode & VIDEO_SOUND_LANG2) + if (t->audmode & V4L2_TUNER_MODE_LANG2) con = 0x080000; - if (v->mode & VIDEO_SOUND_STEREO) + if (t->audmode & V4L2_TUNER_MODE_STEREO) con = 0x180000; gpio_bits(0x180000, con); if (bttv_gpio) bttv_gpio_tracking(btv,"terratv"); } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO | + V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; } } - void -winfast2000_audio(struct bttv *btv, struct video_audio *v, int set) + +void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *t, int set) { unsigned long val = 0; if (set) { /*btor (0xc32000, BT848_GPIO_OUT_EN);*/ - if (v->mode & VIDEO_SOUND_MONO) /* Mono */ + if (t->audmode & V4L2_TUNER_MODE_MONO) /* Mono */ val = 0x420000; - if (v->mode & VIDEO_SOUND_LANG1) /* Mono */ + if (t->audmode & V4L2_TUNER_MODE_LANG1) /* Mono */ val = 0x420000; - if (v->mode & VIDEO_SOUND_LANG2) /* SAP */ + if (t->audmode & V4L2_TUNER_MODE_LANG2) /* SAP */ val = 0x410000; - if (v->mode & VIDEO_SOUND_STEREO) /* Stereo */ + if (t->audmode & V4L2_TUNER_MODE_STEREO) /* Stereo */ val = 0x020000; if (val) { gpio_bits(0x430000, val); @@ -255,8 +248,8 @@ winfast2000_audio(struct bttv *btv, struct video_audio *v, int set) bttv_gpio_tracking(btv,"winfast2000"); } } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO | + V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; } } @@ -268,8 +261,7 @@ winfast2000_audio(struct bttv *btv, struct video_audio *v, int set) * Note: There are card variants without tda9874a. Forcing the "stereo sound route" * will mute this cards. */ - void -pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set) +void pvbt878p9b_audio(struct bttv *btv, struct v4l2_tuner *t, int set) { unsigned int val = 0; @@ -277,11 +269,11 @@ pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set) return; if (set) { - if (v->mode & VIDEO_SOUND_MONO) { + if (t->audmode & V4L2_TUNER_MODE_MONO) { val = 0x01; } - if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2)) - || (v->mode & VIDEO_SOUND_STEREO)) { + if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2)) + || (t->audmode & V4L2_TUNER_MODE_STEREO)) { val = 0x02; } if (val) { @@ -290,8 +282,8 @@ pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set) bttv_gpio_tracking(btv,"pvbt878p9b"); } } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO | + V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; } } @@ -300,8 +292,7 @@ pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set) * sound control for FlyVideo 2000S (with tda9874 decoder) * based on pvbt878p9b_audio() - this is not tested, please fix!!! */ - void -fv2000s_audio(struct bttv *btv, struct video_audio *v, int set) +void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *t, int set) { unsigned int val = 0xffff; @@ -309,11 +300,11 @@ fv2000s_audio(struct bttv *btv, struct video_audio *v, int set) return; if (set) { - if (v->mode & VIDEO_SOUND_MONO) { + if (t->audmode & V4L2_TUNER_MODE_MONO) { val = 0x0000; } - if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2)) - || (v->mode & VIDEO_SOUND_STEREO)) { + if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2)) + || (t->audmode & V4L2_TUNER_MODE_STEREO)) { val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */ } if (val != 0xffff) { @@ -322,8 +313,8 @@ fv2000s_audio(struct bttv *btv, struct video_audio *v, int set) bttv_gpio_tracking(btv,"fv2000s"); } } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO | + V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; } } @@ -331,19 +322,18 @@ fv2000s_audio(struct bttv *btv, struct video_audio *v, int set) * sound control for Canopus WinDVR PCI * Masaki Suzuki */ - void -windvr_audio(struct bttv *btv, struct video_audio *v, int set) +void windvr_audio(struct bttv *btv, struct v4l2_tuner *t, int set) { unsigned long val = 0; if (set) { - if (v->mode & VIDEO_SOUND_MONO) + if (t->audmode & V4L2_TUNER_MODE_MONO) val = 0x040000; - if (v->mode & VIDEO_SOUND_LANG1) + if (t->audmode & V4L2_TUNER_MODE_LANG1) val = 0; - if (v->mode & VIDEO_SOUND_LANG2) + if (t->audmode & V4L2_TUNER_MODE_LANG2) val = 0x100000; - if (v->mode & VIDEO_SOUND_STEREO) + if (t->audmode & V4L2_TUNER_MODE_STEREO) val = 0; if (val) { gpio_bits(0x140000, val); @@ -351,8 +341,8 @@ windvr_audio(struct bttv *btv, struct video_audio *v, int set) bttv_gpio_tracking(btv,"windvr"); } } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO | + V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; } } @@ -360,8 +350,7 @@ windvr_audio(struct bttv *btv, struct video_audio *v, int set) * sound control for AD-TVK503 * Hiroshi Takekawa */ - void -adtvk503_audio(struct bttv *btv, struct video_audio *v, int set) +void adtvk503_audio(struct bttv *btv, struct v4l2_tuner *t, int set) { unsigned int con = 0xffffff; @@ -369,13 +358,13 @@ adtvk503_audio(struct bttv *btv, struct video_audio *v, int set) if (set) { /* btor(***, BT848_GPIO_OUT_EN); */ - if (v->mode & VIDEO_SOUND_LANG1) + if (t->audmode & V4L2_TUNER_MODE_LANG1) con = 0x00000000; - if (v->mode & VIDEO_SOUND_LANG2) + if (t->audmode & V4L2_TUNER_MODE_LANG2) con = 0x00180000; - if (v->mode & VIDEO_SOUND_STEREO) + if (t->audmode & V4L2_TUNER_MODE_STEREO) con = 0x00000000; - if (v->mode & VIDEO_SOUND_MONO) + if (t->audmode & V4L2_TUNER_MODE_MONO) con = 0x00060000; if (con != 0xffffff) { gpio_bits(0x1e0000,con); @@ -383,7 +372,7 @@ adtvk503_audio(struct bttv *btv, struct video_audio *v, int set) bttv_gpio_tracking(btv, "adtvk503"); } } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO | + V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; } } diff --git a/linux/drivers/media/video/bt8xx/bttv-audio-hook.h b/linux/drivers/media/video/bt8xx/bttv-audio-hook.h index 9770cacc1..159d07ade 100644 --- a/linux/drivers/media/video/bt8xx/bttv-audio-hook.h +++ b/linux/drivers/media/video/bt8xx/bttv-audio-hook.h @@ -7,17 +7,17 @@ #include "bttvp.h" -static void winview_audio(struct bttv *btv, struct video_audio *v, int set); -static void lt9415_audio(struct bttv *btv, struct video_audio *v, int set); -static void avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, - int set); -static void avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, - int set); -static void terratv_audio(struct bttv *btv, struct video_audio *v, int set); -static void gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set); -static void gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set); -static void winfast2000_audio(struct bttv *btv, struct video_audio *v, int set); -static void pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set); -static void fv2000s_audio(struct bttv *btv, struct video_audio *v, int set); -static void windvr_audio(struct bttv *btv, struct video_audio *v, int set); -static void adtvk503_audio(struct bttv *btv, struct video_audio *v, int set); +void winview_volume (struct bttv *btv, __u16 volume); + +void lt9415_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set); +void avermedia_tvphone_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set); +void avermedia_tv_stereo_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set); +void terratv_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set); +void gvbctv3pci_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set); +void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set); +void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set); +void pvbt878p9b_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set); +void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set); +void windvr_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set); +void adtvk503_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set); + diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index 9bb671855..798df8152 100644 --- a/linux/drivers/media/video/bt8xx/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c @@ -437,7 +437,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .audio_hook = avermedia_tvphone_audio, + .audio_mode_gpio= avermedia_tvphone_audio, .has_remote = 1, }, [BTTV_BOARD_MATRIX_VISION] = { @@ -549,7 +549,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .audio_hook = avermedia_tv_stereo_audio, + .audio_mode_gpio= avermedia_tv_stereo_audio, .no_gpioirq = 1, }, [BTTV_BOARD_VHX] = { @@ -619,7 +619,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .audio_hook = winview_audio, + .volume_gpio = winview_volume, .has_radio = 1, }, [BTTV_BOARD_AVEC_INTERCAP] = { @@ -743,7 +743,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .audio_hook = terratv_audio, + .audio_mode_gpio= terratv_audio, }, [BTTV_BOARD_HAUPPAUG_WCAM] = { .name = "Hauppauge WinCam newer (bt878)", @@ -791,7 +791,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .audio_hook = terratv_audio, + .audio_mode_gpio= terratv_audio, /* GPIO wiring: External 20 pin connector (for Active Radio Upgrade board) gpio00: i2c-sda @@ -935,7 +935,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_PHILIPS_PAL, /* default for now, gpio reads BFFF06 for Pal bg+dk */ .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .audio_hook = winfast2000_audio, + .audio_mode_gpio= winfast2000_audio, .has_remote = 1, }, [BTTV_BOARD_CHRONOS_VS2] = { @@ -1055,7 +1055,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .has_radio = 1, - .audio_hook = avermedia_tvphone_audio, + .audio_mode_gpio= avermedia_tvphone_audio, }, [BTTV_BOARD_PV951] = { .name = "ProVideo PV951", /* pic16c54 */ @@ -1187,7 +1187,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ALPS_TSHC6_NTSC, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .audio_hook = gvbctv3pci_audio, + .audio_mode_gpio= gvbctv3pci_audio, }, [BTTV_BOARD_PXELVWPLTVPAK] = { .name = "Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP", @@ -1492,7 +1492,7 @@ struct tvcard bttv_tvcards[] = { /* -dk-???: set mute=0x1800 for tda9874h daughterboard */ .gpiomux = { 0x0000,0x0800,0x1000,0x1000 }, .gpiomute = 0x1800, - .audio_hook = fv2000s_audio, + .audio_mode_gpio= fv2000s_audio, .no_msp34xx = 1, .no_tda9875 = 1, .needs_tvaudio = 1, @@ -1533,7 +1533,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_SHARP_2U5JF5540_NTSC, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .audio_hook = gvbctv3pci_audio, + .audio_mode_gpio= gvbctv3pci_audio, }, /* ---- card 0x44 ---------------------------------- */ @@ -1652,7 +1652,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .audio_hook = pvbt878p9b_audio, /* Note: not all cards have stereo */ + .audio_mode_gpio= pvbt878p9b_audio, /* Note: not all cards have stereo */ .has_radio = 1, /* Note: not all cards have radio */ .has_remote = 1, /* GPIO wiring: @@ -1730,7 +1730,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_PHILIPS_NTSC, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .audio_hook = windvr_audio, + .audio_mode_gpio= windvr_audio, }, [BTTV_BOARD_GRANDTEC_MULTI] = { .name = "GrandTec Multi Capture Card (Bt878)", @@ -1827,7 +1827,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_PHILIPS_NTSC_M, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .audio_hook = gvbctv5pci_audio, + .audio_mode_gpio= gvbctv5pci_audio, .has_radio = 1, }, [BTTV_BOARD_OSPREY1x0] = { @@ -2135,7 +2135,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_PHILIPS_NTSC, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .audio_hook = adtvk503_audio, + .audio_mode_gpio= adtvk503_audio, }, /* ---- card 0x64 ---------------------------------- */ @@ -3205,8 +3205,8 @@ static void flyvideo_gpio(struct bttv *btv) /* LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80 * LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00 * Audio options: from tuner, from tda9821/tda9821(mono,stereo,sap), from tda9874, ext., mute */ - if(has_tda9820_tda9821) btv->audio_hook = lt9415_audio; - /* todo: if(has_tda9874) btv->audio_hook = fv2000s_audio; */ + if(has_tda9820_tda9821) btv->audio_mode_gpio = lt9415_audio; + /* todo: if(has_tda9874) btv->audio_mode_gpio = fv2000s_audio; */ } static int miro_tunermap[] = { 0,6,2,3, 4,5,6,0, 3,0,4,5, 5,2,16,1, @@ -3635,8 +3635,10 @@ void __devinit bttv_init_card2(struct bttv *btv) btv->has_remote=1; if (!bttv_tvcards[btv->c.type].no_gpioirq) btv->gpioirq=1; - if (bttv_tvcards[btv->c.type].audio_hook) - btv->audio_hook=bttv_tvcards[btv->c.type].audio_hook; + if (bttv_tvcards[btv->c.type].volume_gpio) + btv->volume_gpio=bttv_tvcards[btv->c.type].volume_gpio; + if (bttv_tvcards[btv->c.type].audio_mode_gpio) + btv->audio_mode_gpio=bttv_tvcards[btv->c.type].audio_mode_gpio; if (bttv_tvcards[btv->c.type].digital_mode == DIGITAL_MODE_CAMERA) { /* detect Bt832 chip for quartzsight digital camera */ diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index e3f53a721..2aaa88dd6 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -1475,20 +1475,6 @@ static void bttv_reinit_bt848(struct bttv *btv) static int get_control(struct bttv *btv, struct v4l2_control *c) { -#ifdef CONFIG_VIDEO_V4L1 - if (btv->audio_hook && (c->id == V4L2_CID_AUDIO_VOLUME)) { - struct video_audio va; - - memset(&va,0,sizeof(va)); - btv->audio_hook(btv,&va,0); - switch (c->id) { - case V4L2_CID_AUDIO_VOLUME: - c->value = va.volume; - break; - } - return 0; - } -#endif switch (c->id) { case V4L2_CID_BRIGHTNESS: c->value = btv->bright; @@ -1554,21 +1540,6 @@ static int set_control(struct bttv *btv, struct v4l2_control *c) { int val; -#ifdef CONFIG_VIDEO_V4L1 - if (btv->audio_hook && (c->id == V4L2_CID_AUDIO_VOLUME)) { - struct video_audio va; - - memset(&va,0,sizeof(va)); - btv->audio_hook(btv,&va,0); - switch (c->id) { - case V4L2_CID_AUDIO_VOLUME: - va.volume = c->value; - break; - } - btv->audio_hook(btv,&va,1); - return 0; - } -#endif switch (c->id) { case V4L2_CID_BRIGHTNESS: bt848_bright(btv,c->value); @@ -1586,6 +1557,11 @@ static int set_control(struct bttv *btv, struct v4l2_control *c) audio_mute(btv, c->value); /* fall through */ case V4L2_CID_AUDIO_VOLUME: + if (btv->volume_gpio) { + btv->volume_gpio (btv, c->value); + } + bttv_call_i2c_clients(btv,VIDIOC_S_CTRL,c); + break; case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: @@ -1994,22 +1970,10 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) return -EINVAL; mutex_lock(&btv->lock); bttv_call_i2c_clients(btv, VIDIOC_S_TUNER, t); -#ifdef CONFIG_VIDEO_V4L1 - if (btv->audio_hook) { - struct video_audio va; - memset(&va, 0, sizeof(struct video_audio)); - if (t->audmode == V4L2_TUNER_MODE_MONO) - va.mode = VIDEO_SOUND_MONO; - else if (t->audmode == V4L2_TUNER_MODE_STEREO || - t->audmode == V4L2_TUNER_MODE_LANG1_LANG2) - va.mode = VIDEO_SOUND_STEREO; - else if (t->audmode == V4L2_TUNER_MODE_LANG1) - va.mode = VIDEO_SOUND_LANG1; - else if (t->audmode == V4L2_TUNER_MODE_LANG2) - va.mode = VIDEO_SOUND_LANG2; - btv->audio_hook(btv,&va,1); + + if (btv->audio_mode_gpio) { + btv->audio_mode_gpio (btv,t,1); } -#endif mutex_unlock(&btv->lock); return 0; } @@ -2889,19 +2853,11 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, return 0; } *c = bttv_ctls[i]; -#ifdef CONFIG_VIDEO_V4L1 - if (btv->audio_hook && i >= 4 && i <= 8) { - struct video_audio va; - memset(&va,0,sizeof(va)); - btv->audio_hook(btv,&va,0); - switch (bttv_ctls[i].id) { - case V4L2_CID_AUDIO_VOLUME: - if (!(va.flags & VIDEO_AUDIO_VOLUME)) - *c = no_ctl; - break; - } - } -#endif + + if (!btv->volume_gpio && + (bttv_ctls[i].id == V4L2_CID_AUDIO_VOLUME)) + *c = no_ctl; + return 0; } case VIDIOC_G_PARM: @@ -2933,26 +2889,11 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, t->type = V4L2_TUNER_ANALOG_TV; if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) t->signal = 0xffff; -#ifdef CONFIG_VIDEO_V4L1 - if (btv->audio_hook) { - /* Hmmm ... */ - struct video_audio va; - memset(&va, 0, sizeof(struct video_audio)); - btv->audio_hook(btv,&va,0); - t->audmode = V4L2_TUNER_MODE_MONO; - t->rxsubchans = V4L2_TUNER_SUB_MONO; - if(va.mode & VIDEO_SOUND_STEREO) { - t->audmode = V4L2_TUNER_MODE_STEREO; - t->rxsubchans = V4L2_TUNER_SUB_STEREO; - } - if(va.mode & VIDEO_SOUND_LANG2) { - t->audmode = V4L2_TUNER_MODE_LANG1; - t->rxsubchans = V4L2_TUNER_SUB_LANG1 - | V4L2_TUNER_SUB_LANG2; - } + + if (btv->audio_mode_gpio) { + btv->audio_mode_gpio (btv,t,0); } -#endif - /* FIXME: fill capability+audmode */ + mutex_unlock(&btv->lock); return 0; } @@ -3451,6 +3392,10 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); + if (btv->audio_mode_gpio) { + btv->audio_mode_gpio (btv,t,0); + } + mutex_unlock(&btv->lock); return 0; diff --git a/linux/drivers/media/video/bt8xx/bttv.h b/linux/drivers/media/video/bt8xx/bttv.h index d943b1fca..56d47a834 100644 --- a/linux/drivers/media/video/bt8xx/bttv.h +++ b/linux/drivers/media/video/bt8xx/bttv.h @@ -242,9 +242,10 @@ struct tvcard unsigned int radio_addr; unsigned int has_radio; -#ifdef CONFIG_VIDEO_V4L1 - void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); -#endif + + void (*volume_gpio)(struct bttv *btv, __u16 volume); + void (*audio_mode_gpio)(struct bttv *btv, struct v4l2_tuner *tuner, int set); + void (*muxsel_hook)(struct bttv *btv, unsigned int input); }; diff --git a/linux/drivers/media/video/bt8xx/bttvp.h b/linux/drivers/media/video/bt8xx/bttvp.h index ce132b58b..6e8519444 100644 --- a/linux/drivers/media/video/bt8xx/bttvp.h +++ b/linux/drivers/media/video/bt8xx/bttvp.h @@ -350,9 +350,10 @@ struct bttv { /* old gpio interface */ wait_queue_head_t gpioq; int shutdown; -#ifdef CONFIG_VIDEO_V4L1 - void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); -#endif + + void (*volume_gpio)(struct bttv *btv, __u16 volume); + void (*audio_mode_gpio)(struct bttv *btv, struct v4l2_tuner *tuner, int set); + /* new gpio interface */ spinlock_t gpio_lock; -- cgit v1.2.3 From a569bbcfb1eaa8fee24a6e70f43358088a84a77a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 25 Aug 2006 16:53:07 -0300 Subject: Report detected sound carrier into rxsubchans From: Nickolay V. Shmyrev Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/bttv-audio-hook.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) --- linux/drivers/media/video/bt8xx/bttv-audio-hook.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-audio-hook.c b/linux/drivers/media/video/bt8xx/bttv-audio-hook.c index a075198f8..67b634235 100644 --- a/linux/drivers/media/video/bt8xx/bttv-audio-hook.c +++ b/linux/drivers/media/video/bt8xx/bttv-audio-hook.c @@ -101,24 +101,28 @@ void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set) } else { switch (val & 0x70) { case 0x10: - t->audmode = V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; + t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; break; case 0x30: - t->audmode = V4L2_TUNER_MODE_LANG2; + t->rxsubchans = V4L2_TUNER_SUB_LANG2; break; case 0x50: - t->audmode = V4L2_TUNER_MODE_LANG1; + t->rxsubchans = V4L2_TUNER_SUB_LANG1; break; case 0x60: - t->audmode = V4L2_TUNER_MODE_STEREO; + t->rxsubchans = V4L2_TUNER_SUB_STEREO; break; case 0x70: - t->audmode = V4L2_TUNER_MODE_MONO; + t->rxsubchans = V4L2_TUNER_SUB_MONO; break; default: - t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO | - V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; + t->rxsubchans = V4L2_TUNER_SUB_MONO | + V4L2_TUNER_SUB_STEREO | + V4L2_TUNER_SUB_LANG1 | + V4L2_TUNER_SUB_LANG2; } + t->audmode = V4L2_TUNER_MODE_STEREO | + V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; } } -- cgit v1.2.3 From b680b9bc92b814d1594cb65e7f49877d09793cb3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 25 Aug 2006 16:53:08 -0300 Subject: Converted tvaudio from V4L1 to V4L2 From: Mauro Carvalho Chehab V4L1 ioctls were replaced to V4L2 were applicable. The older ones already implemented were removed. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tvaudio.c | 306 ++++++++++++++++++++---------------- 1 file changed, 178 insertions(+), 128 deletions(-) --- linux/drivers/media/video/tvaudio.c | 308 +++++++++++++++++++++--------------- 1 file changed, 179 insertions(+), 129 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tvaudio.c b/linux/drivers/media/video/tvaudio.c index f238718a3..5c3bd5030 100644 --- a/linux/drivers/media/video/tvaudio.c +++ b/linux/drivers/media/video/tvaudio.c @@ -319,14 +319,16 @@ static void generic_checkmode(struct CHIPSTATE *chip) v4l_dbg(1, debug, &chip->c, "%s: thread checkmode\n", chip->c.name); chip->prevmode = mode; - if (mode & VIDEO_SOUND_STEREO) - desc->setmode(chip,VIDEO_SOUND_STEREO); - else if (mode & VIDEO_SOUND_LANG1) - desc->setmode(chip,VIDEO_SOUND_LANG1); - else if (mode & VIDEO_SOUND_LANG2) - desc->setmode(chip,VIDEO_SOUND_LANG2); + if (mode & V4L2_TUNER_MODE_STEREO) + desc->setmode(chip,V4L2_TUNER_MODE_STEREO); + if (mode & V4L2_TUNER_MODE_LANG1_LANG2) + desc->setmode(chip,V4L2_TUNER_MODE_STEREO); + else if (mode & V4L2_TUNER_MODE_LANG1) + desc->setmode(chip,V4L2_TUNER_MODE_LANG1); + else if (mode & V4L2_TUNER_MODE_LANG2) + desc->setmode(chip,V4L2_TUNER_MODE_LANG2); else - desc->setmode(chip,VIDEO_SOUND_MONO); + desc->setmode(chip,V4L2_TUNER_MODE_MONO); } /* ---------------------------------------------------------------------- */ @@ -357,11 +359,11 @@ static int tda9840_getmode(struct CHIPSTATE *chip) int val, mode; val = chip_read(chip); - mode = VIDEO_SOUND_MONO; + mode = V4L2_TUNER_MODE_MONO; if (val & TDA9840_DS_DUAL) - mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + mode |= V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; if (val & TDA9840_ST_STEREO) - mode |= VIDEO_SOUND_STEREO; + mode |= V4L2_TUNER_MODE_STEREO; v4l_dbg(1, debug, &chip->c, "tda9840_getmode(): raw chip read: %d, return: %d\n", val, mode); @@ -374,16 +376,16 @@ static void tda9840_setmode(struct CHIPSTATE *chip, int mode) int t = chip->shadow.bytes[TDA9840_SW + 1] & ~0x7e; switch (mode) { - case VIDEO_SOUND_MONO: + case V4L2_TUNER_MODE_MONO: t |= TDA9840_MONO; break; - case VIDEO_SOUND_STEREO: + case V4L2_TUNER_MODE_STEREO: t |= TDA9840_STEREO; break; - case VIDEO_SOUND_LANG1: + case V4L2_TUNER_MODE_LANG1: t |= TDA9840_DUALA; break; - case VIDEO_SOUND_LANG2: + case V4L2_TUNER_MODE_LANG2: t |= TDA9840_DUALB; break; default: @@ -514,7 +516,7 @@ static int tda985x_getmode(struct CHIPSTATE *chip) chip_read(chip)) >> 4; /* Add mono mode regardless of SAP and stereo */ /* Allows forced mono */ - return mode | VIDEO_SOUND_MONO; + return mode | V4L2_TUNER_MODE_MONO; } static void tda985x_setmode(struct CHIPSTATE *chip, int mode) @@ -523,13 +525,13 @@ static void tda985x_setmode(struct CHIPSTATE *chip, int mode) int c6 = chip->shadow.bytes[TDA985x_C6+1] & 0x3f; switch (mode) { - case VIDEO_SOUND_MONO: + case V4L2_TUNER_MODE_MONO: c6 |= TDA985x_MONO; break; - case VIDEO_SOUND_STEREO: + case V4L2_TUNER_MODE_STEREO: c6 |= TDA985x_STEREO; break; - case VIDEO_SOUND_LANG1: + case V4L2_TUNER_MODE_LANG1: c6 |= TDA985x_SAP; break; default: @@ -662,11 +664,11 @@ static int tda9873_getmode(struct CHIPSTATE *chip) int val,mode; val = chip_read(chip); - mode = VIDEO_SOUND_MONO; + mode = V4L2_TUNER_MODE_MONO; if (val & TDA9873_STEREO) - mode |= VIDEO_SOUND_STEREO; + mode |= V4L2_TUNER_MODE_STEREO; if (val & TDA9873_DUAL) - mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + mode |= V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; v4l_dbg(1, debug, &chip->c, "tda9873_getmode(): raw chip read: %d, return: %d\n", val, mode); return mode; @@ -686,16 +688,16 @@ static void tda9873_setmode(struct CHIPSTATE *chip, int mode) v4l_dbg(1, debug, &chip->c, "tda9873_setmode(): sw_data = %d\n", sw_data); switch (mode) { - case VIDEO_SOUND_MONO: + case V4L2_TUNER_MODE_MONO: sw_data |= TDA9873_TR_MONO; break; - case VIDEO_SOUND_STEREO: + case V4L2_TUNER_MODE_STEREO: sw_data |= TDA9873_TR_STEREO; break; - case VIDEO_SOUND_LANG1: + case V4L2_TUNER_MODE_LANG1: sw_data |= TDA9873_TR_DUALA; break; - case VIDEO_SOUND_LANG2: + case V4L2_TUNER_MODE_LANG2: sw_data |= TDA9873_TR_DUALB; break; default: @@ -853,7 +855,7 @@ static int tda9874a_getmode(struct CHIPSTATE *chip) int dsr,nsr,mode; int necr; /* just for debugging */ - mode = VIDEO_SOUND_MONO; + mode = V4L2_TUNER_MODE_MONO; if(-1 == (dsr = chip_read2(chip,TDA9874A_DSR))) return mode; @@ -872,23 +874,23 @@ static int tda9874a_getmode(struct CHIPSTATE *chip) * that sound has (temporarily) switched from NICAM to * mono FM (or AM) on 1st sound carrier due to high NICAM bit * error count. So in fact there is no stereo in this case :-( - * But changing the mode to VIDEO_SOUND_MONO would switch + * But changing the mode to V4L2_TUNER_MODE_MONO would switch * external 4052 multiplexer in audio_hook(). */ #if 0 if((nsr & 0x02) && !(dsr & 0x10)) /* NSR.S/MB=1 and DSR.AMSTAT=0 */ - mode |= VIDEO_SOUND_STEREO; + mode |= V4L2_TUNER_MODE_STEREO; #else if(nsr & 0x02) /* NSR.S/MB=1 */ - mode |= VIDEO_SOUND_STEREO; + mode |= V4L2_TUNER_MODE_STEREO; #endif if(nsr & 0x01) /* NSR.D/SB=1 */ - mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + mode |= V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; } else { if(dsr & 0x02) /* DSR.IDSTE=1 */ - mode |= VIDEO_SOUND_STEREO; + mode |= V4L2_TUNER_MODE_STEREO; if(dsr & 0x04) /* DSR.IDDUA=1 */ - mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + mode |= V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; } v4l_dbg(1, debug, &chip->c, "tda9874a_getmode(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n", @@ -919,14 +921,14 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode) int mdacosr = (tda9874a_mode) ? 0x82:0x80; switch(mode) { - case VIDEO_SOUND_MONO: - case VIDEO_SOUND_STEREO: + case V4L2_TUNER_MODE_MONO: + case V4L2_TUNER_MODE_STEREO: break; - case VIDEO_SOUND_LANG1: + case V4L2_TUNER_MODE_LANG1: aosr = 0x80; /* auto-select, dual A/A */ mdacosr = (tda9874a_mode) ? 0x82:0x80; break; - case VIDEO_SOUND_LANG2: + case V4L2_TUNER_MODE_LANG2: aosr = 0xa0; /* auto-select, dual B/B */ mdacosr = (tda9874a_mode) ? 0x83:0x81; break; @@ -944,11 +946,11 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode) int fmmr,aosr; switch(mode) { - case VIDEO_SOUND_MONO: + case V4L2_TUNER_MODE_MONO: fmmr = 0x00; /* mono */ aosr = 0x10; /* A/A */ break; - case VIDEO_SOUND_STEREO: + case V4L2_TUNER_MODE_STEREO: if(tda9874a_mode) { fmmr = 0x00; aosr = 0x00; /* handled by NICAM auto-mute */ @@ -957,11 +959,11 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode) aosr = 0x00; } break; - case VIDEO_SOUND_LANG1: + case V4L2_TUNER_MODE_LANG1: fmmr = 0x02; /* dual */ aosr = 0x10; /* dual A/A */ break; - case VIDEO_SOUND_LANG2: + case V4L2_TUNER_MODE_LANG2: fmmr = 0x02; /* dual */ aosr = 0x20; /* dual B/B */ break; @@ -1122,20 +1124,20 @@ static void tda8425_setmode(struct CHIPSTATE *chip, int mode) { int s1 = chip->shadow.bytes[TDA8425_S1+1] & 0xe1; - if (mode & VIDEO_SOUND_LANG1) { + if (mode & V4L2_TUNER_MODE_LANG1) { s1 |= TDA8425_S1_ML_SOUND_A; s1 |= TDA8425_S1_STEREO_PSEUDO; - } else if (mode & VIDEO_SOUND_LANG2) { + } else if (mode & V4L2_TUNER_MODE_LANG2) { s1 |= TDA8425_S1_ML_SOUND_B; s1 |= TDA8425_S1_STEREO_PSEUDO; } else { s1 |= TDA8425_S1_ML_STEREO; - if (mode & VIDEO_SOUND_MONO) + if (mode & V4L2_TUNER_MODE_MONO) s1 |= TDA8425_S1_STEREO_MONO; - if (mode & VIDEO_SOUND_STEREO) + if (mode & V4L2_TUNER_MODE_STEREO) s1 |= TDA8425_S1_STEREO_SPATIAL; } chip_write(chip,TDA8425_S1,s1); @@ -1194,11 +1196,11 @@ static int ta8874z_getmode(struct CHIPSTATE *chip) int val, mode; val = chip_read(chip); - mode = VIDEO_SOUND_MONO; + mode = V4L2_TUNER_MODE_MONO; if (val & TA8874Z_B1){ - mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + mode |= V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; }else if (!(val & TA8874Z_B0)){ - mode |= VIDEO_SOUND_STEREO; + mode |= V4L2_TUNER_MODE_STEREO; } /* v4l_dbg(1, debug, &chip->c, "ta8874z_getmode(): raw chip read: 0x%02x, return: 0x%02x\n", val, mode); */ return mode; @@ -1216,16 +1218,16 @@ static void ta8874z_setmode(struct CHIPSTATE *chip, int mode) v4l_dbg(1, debug, &chip->c, "ta8874z_setmode(): mode: 0x%02x\n", mode); switch(mode){ - case VIDEO_SOUND_MONO: + case V4L2_TUNER_MODE_MONO: t = &ta8874z_mono; break; - case VIDEO_SOUND_STEREO: + case V4L2_TUNER_MODE_STEREO: t = &ta8874z_stereo; break; - case VIDEO_SOUND_LANG1: + case V4L2_TUNER_MODE_LANG1: t = &ta8874z_main; break; - case VIDEO_SOUND_LANG2: + case V4L2_TUNER_MODE_LANG2: t = &ta8874z_sub; break; default: @@ -1609,7 +1611,48 @@ static int chip_detach(struct i2c_client *client) return 0; } -static int tvaudio_set_ctrl(struct CHIPSTATE *chip, struct v4l2_control *ctrl) +static int tvaudio_get_ctrl(struct CHIPSTATE *chip, + struct v4l2_control *ctrl) +{ + struct CHIPDESC *desc = chiplist + chip->type; + + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + ctrl->value=chip->muted; + return 0; + case V4L2_CID_AUDIO_VOLUME: + if (!desc->flags & CHIP_HAS_VOLUME) + break; + ctrl->value = max(chip->left,chip->right); + return 0; + case V4L2_CID_AUDIO_BALANCE: + { + int volume; + if (!desc->flags & CHIP_HAS_VOLUME) + break; + volume = max(chip->left,chip->right); + if (volume) + ctrl->value=(32768*min(chip->left,chip->right))/volume; + else + ctrl->value=32768; + return 0; + } + case V4L2_CID_AUDIO_BASS: + if (desc->flags & CHIP_HAS_BASSTREBLE) + break; + ctrl->value = chip->bass; + return 0; + case V4L2_CID_AUDIO_TREBLE: + if (desc->flags & CHIP_HAS_BASSTREBLE) + return -EINVAL; + ctrl->value = chip->treble; + return 0; + } + return -EINVAL; +} + +static int tvaudio_set_ctrl(struct CHIPSTATE *chip, + struct v4l2_control *ctrl) { struct CHIPDESC *desc = chiplist + chip->type; @@ -1623,11 +1666,60 @@ static int tvaudio_set_ctrl(struct CHIPSTATE *chip, struct v4l2_control *ctrl) else chip_write_masked(chip,desc->inputreg, desc->inputmap[chip->input],desc->inputmask); - break; - default: - return -EINVAL; + return 0; + case V4L2_CID_AUDIO_VOLUME: + { + int volume,balance; + + if (!desc->flags & CHIP_HAS_VOLUME) + break; + + volume = max(chip->left,chip->right); + if (volume) + balance=(32768*min(chip->left,chip->right))/volume; + else + balance=32768; + + volume=ctrl->value; + chip->left = (min(65536 - balance,32768) * volume) / 32768; + chip->right = (min(balance,volume *(__u16)32768)) / 32768; + + chip_write(chip,desc->leftreg,desc->volfunc(chip->left)); + chip_write(chip,desc->rightreg,desc->volfunc(chip->right)); + + return 0; } - return 0; + case V4L2_CID_AUDIO_BALANCE: + { + int volume, balance; + if (!desc->flags & CHIP_HAS_VOLUME) + break; + + volume = max(chip->left,chip->right); + balance = ctrl->value; + + chip_write(chip,desc->leftreg,desc->volfunc(chip->left)); + chip_write(chip,desc->rightreg,desc->volfunc(chip->right)); + + return 0; + } + case V4L2_CID_AUDIO_BASS: + if (desc->flags & CHIP_HAS_BASSTREBLE) + break; + chip->bass = ctrl->value; + chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass)); + + return 0; + case V4L2_CID_AUDIO_TREBLE: + if (desc->flags & CHIP_HAS_BASSTREBLE) + return -EINVAL; + + chip->treble = ctrl->value; + chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble)); + + return 0; + } + return -EINVAL; } @@ -1648,67 +1740,36 @@ static int chip_command(struct i2c_client *client, chip->watch_stereo = 0; /* del_timer(&chip->wt); */ break; - /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a kernel pointer here... */ - case VIDIOCGAUDIO: - { - struct video_audio *va = arg; - - if (desc->flags & CHIP_HAS_VOLUME) { - va->flags |= VIDEO_AUDIO_VOLUME; - va->volume = max(chip->left,chip->right); - if (va->volume) - va->balance = (32768*min(chip->left,chip->right))/ - va->volume; - else - va->balance = 32768; - } - if (desc->flags & CHIP_HAS_BASSTREBLE) { - va->flags |= VIDEO_AUDIO_BASS | VIDEO_AUDIO_TREBLE; - va->bass = chip->bass; - va->treble = chip->treble; - } - if (!chip->radio) { - if (desc->getmode) - va->mode = desc->getmode(chip); - else - va->mode = VIDEO_SOUND_MONO; - } - break; - } - - case VIDIOCSAUDIO: + case VIDIOC_QUERYCTRL: { - struct video_audio *va = arg; - - if (desc->flags & CHIP_HAS_VOLUME) { - chip->left = (min(65536 - va->balance,32768) * - va->volume) / 32768; - chip->right = (min(va->balance,(__u16)32768) * - va->volume) / 32768; - chip_write(chip,desc->leftreg,desc->volfunc(chip->left)); - chip_write(chip,desc->rightreg,desc->volfunc(chip->right)); - } - if (desc->flags & CHIP_HAS_BASSTREBLE) { - chip->bass = va->bass; - chip->treble = va->treble; - chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass)); - chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble)); - } - if (desc->setmode && va->mode) { - chip->watch_stereo = 0; - /* del_timer(&chip->wt); */ - chip->mode = va->mode; - desc->setmode(chip,va->mode); + struct v4l2_queryctrl *qc = arg; + + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + break; + case V4L2_CID_AUDIO_VOLUME: + case V4L2_CID_AUDIO_BALANCE: + if (!desc->flags & CHIP_HAS_VOLUME) + return -EINVAL; + break; + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + if (desc->flags & CHIP_HAS_BASSTREBLE) + return -EINVAL; + break; + default: + return -EINVAL; } - break; + return v4l2_ctrl_query_fill_std(qc); } - case VIDIOC_S_CTRL: return tvaudio_set_ctrl(chip, arg); + case VIDIOC_G_CTRL: + return tvaudio_get_ctrl(chip, arg); case VIDIOC_INT_G_AUDIO_ROUTING: { struct v4l2_routing *rt = arg; @@ -1717,7 +1778,6 @@ static int chip_command(struct i2c_client *client, rt->output = 0; break; } - case VIDIOC_INT_S_AUDIO_ROUTING: { struct v4l2_routing *rt = arg; @@ -1732,7 +1792,6 @@ static int chip_command(struct i2c_client *client, desc->inputmap[chip->input], desc->inputmask); break; } - case VIDIOC_S_TUNER: { struct v4l2_tuner *vt = arg; @@ -1742,17 +1801,13 @@ static int chip_command(struct i2c_client *client, break; switch (vt->audmode) { case V4L2_TUNER_MODE_MONO: - mode = VIDEO_SOUND_MONO; - break; case V4L2_TUNER_MODE_STEREO: - case V4L2_TUNER_MODE_LANG1_LANG2: - mode = VIDEO_SOUND_STEREO; - break; case V4L2_TUNER_MODE_LANG1: - mode = VIDEO_SOUND_LANG1; - break; case V4L2_TUNER_MODE_LANG2: - mode = VIDEO_SOUND_LANG2; + mode = vt->audmode; + break; + case V4L2_TUNER_MODE_LANG1_LANG2: + mode = V4L2_TUNER_MODE_STEREO; break; default: return -EINVAL; @@ -1767,11 +1822,10 @@ static int chip_command(struct i2c_client *client, } break; } - case VIDIOC_G_TUNER: { struct v4l2_tuner *vt = arg; - int mode = VIDEO_SOUND_MONO; + int mode = V4L2_TUNER_MODE_MONO; if (chip->radio) break; @@ -1783,30 +1837,26 @@ static int chip_command(struct i2c_client *client, if (desc->getmode) mode = desc->getmode(chip); - if (mode & VIDEO_SOUND_MONO) + if (mode & V4L2_TUNER_MODE_MONO) vt->rxsubchans |= V4L2_TUNER_SUB_MONO; - if (mode & VIDEO_SOUND_STEREO) + if (mode & V4L2_TUNER_MODE_STEREO) vt->rxsubchans |= V4L2_TUNER_SUB_STEREO; /* Note: for SAP it should be mono/lang2 or stereo/lang2. When this module is converted fully to v4l2, then this should change for those chips that can detect SAP. */ - if (mode & VIDEO_SOUND_LANG1) + if (mode & V4L2_TUNER_MODE_LANG1) vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; break; } - - case VIDIOCSCHAN: case VIDIOC_S_STD: chip->radio = 0; break; - - case VIDIOCSFREQ: case VIDIOC_S_FREQUENCY: chip->mode = 0; /* automatic */ if (desc->checkmode) { - desc->setmode(chip,VIDEO_SOUND_MONO); - if (chip->prevmode != VIDEO_SOUND_MONO) + desc->setmode(chip,V4L2_TUNER_MODE_MONO); + if (chip->prevmode != V4L2_TUNER_MODE_MONO) chip->prevmode = -1; /* reset previous mode */ mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); /* the thread will call checkmode() later */ -- cgit v1.2.3 From 3d9484603e60fca1923a4a893fda56a42419fdfc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 25 Aug 2006 16:53:09 -0300 Subject: V4L2 port of tda7432 from V4L1 api From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tda7432.c | 232 ++++++++++++++++++------------------ 1 file changed, 121 insertions(+), 111 deletions(-) --- linux/drivers/media/video/tda7432.c | 232 +++++++++++++++++++----------------- 1 file changed, 121 insertions(+), 111 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tda7432.c b/linux/drivers/media/video/tda7432.c index 580f571ca..5c58967ce 100644 --- a/linux/drivers/media/video/tda7432.c +++ b/linux/drivers/media/video/tda7432.c @@ -8,6 +8,7 @@ * Muting and tone control by Jonathan Isom * * Copyright (c) 2000 Eric Sandeen + * Copyright (c) 2006 Mauro Carvalho Chehab * This code is placed under the terms of the GNU General Public License * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu) * Which was based on tda8425.c by Greg Alexander (c) 1998 @@ -297,7 +298,7 @@ static void do_tda7432_init(struct i2c_client *client) t->volume = 0x3b ; /* -27dB Volume */ if (loudness) /* Turn loudness on? */ t->volume |= TDA7432_LD_ON; - t->muted = VIDEO_AUDIO_MUTE; + t->muted = 1; t->treble = TDA7432_TREBLE_0DB; /* 0dB Treble */ t->bass = TDA7432_BASS_0DB; /* 0dB Bass */ t->lf = TDA7432_ATTEN_0DB; /* 0dB attenuation */ @@ -369,151 +370,160 @@ static int tda7432_detach(struct i2c_client *client) return 0; } -static int tda7432_command(struct i2c_client *client, - unsigned int cmd, void *arg) +static int tda7432_get_ctrl(struct i2c_client *client, + struct v4l2_control *ctrl) { struct tda7432 *t = i2c_get_clientdata(client); - v4l_dbg(2, debug,client,"In tda7432_command\n"); - if (debug>1) - v4l_i2c_print_ioctl(client,cmd); - switch (cmd) { - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ - - /* Query card - scale from TDA7432 settings to V4L settings */ - case VIDIOCGAUDIO: - { - struct video_audio *va = arg; - - va->flags |= VIDEO_AUDIO_VOLUME | - VIDEO_AUDIO_BASS | - VIDEO_AUDIO_TREBLE | - VIDEO_AUDIO_MUTABLE; - if (t->muted) - va->flags |= VIDEO_AUDIO_MUTE; - va->mode |= VIDEO_SOUND_STEREO; - /* Master volume control - * V4L volume is min 0, max 65535 - * TDA7432 Volume: - * Min (-79dB) is 0x6f - * Max (+20dB) is 0x07 (630) - * Max (0dB) is 0x20 (829) - * (Mask out bit 7 of vol - it's for the loudness setting) - */ + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + ctrl->value=t->muted; + return 0; + case V4L2_CID_AUDIO_VOLUME: if (!maxvol){ /* max +20db */ - va->volume = ( 0x6f - (t->volume & 0x7F) ) * 630; + ctrl->value = ( 0x6f - (t->volume & 0x7F) ) * 630; } else { /* max 0db */ - va->volume = ( 0x6f - (t->volume & 0x7F) ) * 829; + ctrl->value = ( 0x6f - (t->volume & 0x7F) ) * 829; } - - /* Balance depends on L,R attenuation - * V4L balance is 0 to 65535, middle is 32768 - * TDA7432 attenuation: min (0dB) is 0, max (-37.5dB) is 0x1f - * to scale up to V4L numbers, mult by 1057 - * attenuation exists for lf, lr, rf, rr - * we use only lf and rf (front channels) - */ - + return 0; + case V4L2_CID_AUDIO_BALANCE: + { if ( (t->lf) < (t->rf) ) /* right is attenuated, balance shifted left */ - va->balance = (32768 - 1057*(t->rf)); + ctrl->value = (32768 - 1057*(t->rf)); else /* left is attenuated, balance shifted right */ - va->balance = (32768 + 1057*(t->lf)); - + ctrl->value = (32768 + 1057*(t->lf)); + return 0; + } + case V4L2_CID_AUDIO_BASS: + { /* Bass/treble 4 bits each */ - va->bass=t->bass; - if(va->bass >= 0x8) - va->bass = ~(va->bass - 0x8) & 0xf; - va->bass = (va->bass << 12)+(va->bass << 8)+(va->bass << 4)+(va->bass); - va->treble=t->treble; - if(va->treble >= 0x8) - va->treble = ~(va->treble - 0x8) & 0xf; - va->treble = (va->treble << 12)+(va->treble << 8)+(va->treble << 4)+(va->treble); - - break; /* VIDIOCGAUDIO case */ + int bass=t->bass; + if(bass >= 0x8) + bass = ~(bass - 0x8) & 0xf; + ctrl->value = (bass << 12)+(bass << 8)+(bass << 4)+(bass); + return 0; } - - /* Set card - scale from V4L settings to TDA7432 settings */ - case VIDIOCSAUDIO: + case V4L2_CID_AUDIO_TREBLE: { - struct video_audio *va = arg; + int treble=t->treble; + if(treble >= 0x8) + treble = ~(treble - 0x8) & 0xf; + ctrl->value = (treble << 12)+(treble << 8)+(treble << 4)+(treble); + return 0; + } + } + return -EINVAL; +} - if(va->flags & VIDEO_AUDIO_VOLUME){ - if(!maxvol){ /* max +20db */ - t->volume = 0x6f - ((va->volume)/630); - } else { /* max 0db */ - t->volume = 0x6f - ((va->volume)/829); - } +static int tda7432_set_ctrl(struct i2c_client *client, + struct v4l2_control *ctrl) +{ + struct tda7432 *t = i2c_get_clientdata(client); + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + t->muted=ctrl->value; + break; + case V4L2_CID_AUDIO_VOLUME: + if(!maxvol){ /* max +20db */ + t->volume = 0x6f - ((ctrl->value)/630); + } else { /* max 0db */ + t->volume = 0x6f - ((ctrl->value)/829); + } if (loudness) /* Turn on the loudness bit */ t->volume |= TDA7432_LD_ON; - tda7432_write(client,TDA7432_VL, t->volume); - } - - if(va->flags & VIDEO_AUDIO_BASS) - { - t->bass = va->bass >> 12; - if(t->bass>= 0x8) - t->bass = (~t->bass & 0xf) + 0x8 ; - } - if(va->flags & VIDEO_AUDIO_TREBLE) - { - t->treble= va->treble >> 12; - if(t->treble>= 0x8) - t->treble = (~t->treble & 0xf) + 0x8 ; - } - if(va->flags & (VIDEO_AUDIO_TREBLE| VIDEO_AUDIO_BASS)) - tda7432_write(client,TDA7432_TN, 0x10 | (t->bass << 4) | t->treble ); - - if(va->flags & VIDEO_AUDIO_BALANCE) { - if (va->balance < 32768) - { + tda7432_write(client,TDA7432_VL, t->volume); + return 0; + case V4L2_CID_AUDIO_BALANCE: + if (ctrl->value < 32768) { /* shifted to left, attenuate right */ - t->rr = (32768 - va->balance)/1057; + t->rr = (32768 - ctrl->value)/1057; t->rf = t->rr; t->lr = TDA7432_ATTEN_0DB; t->lf = TDA7432_ATTEN_0DB; - } - else if(va->balance > 32769) - { + } else if(ctrl->value > 32769) { /* shifted to right, attenuate left */ - t->lf = (va->balance - 32768)/1057; + t->lf = (ctrl->value - 32768)/1057; t->lr = t->lf; t->rr = TDA7432_ATTEN_0DB; t->rf = TDA7432_ATTEN_0DB; - } - else - { + } else { /* centered */ t->rr = TDA7432_ATTEN_0DB; t->rf = TDA7432_ATTEN_0DB; t->lf = TDA7432_ATTEN_0DB; t->lr = TDA7432_ATTEN_0DB; } - } + break; + case V4L2_CID_AUDIO_BASS: + t->bass = ctrl->value >> 12; + if(t->bass>= 0x8) + t->bass = (~t->bass & 0xf) + 0x8 ; + + tda7432_write(client,TDA7432_TN, 0x10 | (t->bass << 4) | t->treble ); + return 0; + case V4L2_CID_AUDIO_TREBLE: + t->treble= ctrl->value >> 12; + if(t->treble>= 0x8) + t->treble = (~t->treble & 0xf) + 0x8 ; + + tda7432_write(client,TDA7432_TN, 0x10 | (t->bass << 4) | t->treble ); + return 0; + default: + return -EINVAL; + } - t->muted=(va->flags & VIDEO_AUDIO_MUTE); - if (t->muted) - { - /* Mute & update balance*/ - tda7432_write(client,TDA7432_LF, t->lf | TDA7432_MUTE); - tda7432_write(client,TDA7432_LR, t->lr | TDA7432_MUTE); - tda7432_write(client,TDA7432_RF, t->rf | TDA7432_MUTE); - tda7432_write(client,TDA7432_RR, t->rr | TDA7432_MUTE); - } else { - tda7432_write(client,TDA7432_LF, t->lf); - tda7432_write(client,TDA7432_LR, t->lr); - tda7432_write(client,TDA7432_RF, t->rf); - tda7432_write(client,TDA7432_RR, t->rr); - } + /* Used for both mute and balance changes */ + if (t->muted) + { + /* Mute & update balance*/ + tda7432_write(client,TDA7432_LF, t->lf | TDA7432_MUTE); + tda7432_write(client,TDA7432_LR, t->lr | TDA7432_MUTE); + tda7432_write(client,TDA7432_RF, t->rf | TDA7432_MUTE); + tda7432_write(client,TDA7432_RR, t->rr | TDA7432_MUTE); + } else { + tda7432_write(client,TDA7432_LF, t->lf); + tda7432_write(client,TDA7432_LR, t->lr); + tda7432_write(client,TDA7432_RF, t->rf); + tda7432_write(client,TDA7432_RR, t->rr); + } + return 0; +} - break; +static int tda7432_command(struct i2c_client *client, + unsigned int cmd, void *arg) +{ + v4l_dbg(2, debug,client,"In tda7432_command\n"); + if (debug>1) + v4l_i2c_print_ioctl(client,cmd); + + switch (cmd) { + /* --- v4l ioctls --- */ + /* take care: bttv does userspace copying, we'll get a + kernel pointer here... */ + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *qc = arg; + + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + case V4L2_CID_AUDIO_VOLUME: + case V4L2_CID_AUDIO_BALANCE: + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + default: + return -EINVAL; + } + return v4l2_ctrl_query_fill_std(qc); + } + case VIDIOC_S_CTRL: + return tda7432_set_ctrl(client, arg); - } /* end of VIDEOCSAUDIO case */ + case VIDIOC_G_CTRL: + return tda7432_get_ctrl(client, arg); } /* end of (cmd) switch */ -- cgit v1.2.3 From 75295223e9a92f14264545531c8fdaca1c1ae427 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 25 Aug 2006 16:53:10 -0300 Subject: V4L2 conversion for tda9875 from V4L1 API From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tda9875.c | 163 ++++++++++++++++++++++++------------ 1 file changed, 110 insertions(+), 53 deletions(-) --- linux/drivers/media/video/tda9875.c | 167 ++++++++++++++++++++++++------------ 1 file changed, 112 insertions(+), 55 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tda9875.c b/linux/drivers/media/video/tda9875.c index 8b0988cba..340ea2300 100644 --- a/linux/drivers/media/video/tda9875.c +++ b/linux/drivers/media/video/tda9875.c @@ -7,6 +7,7 @@ * * Copyright (c) 2000 Guillaume Delvit based on Gerd Knorr source and * Eric Sandeen + * Copyright (c) 2006 Mauro Carvalho Chehab * This code is placed under the terms of the GNU General Public License * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu) * Which was based on tda8425.c by Greg Alexander (c) 1998 @@ -305,87 +306,143 @@ static int tda9875_detach(struct i2c_client *client) return 0; } -static int tda9875_command(struct i2c_client *client, - unsigned int cmd, void *arg) +static int tda9875_get_ctrl(struct i2c_client *client, + struct v4l2_control *ctrl) { struct tda9875 *t = i2c_get_clientdata(client); - dprintk("In tda9875_command...\n"); + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: + { + int left = (t->lvol+84)*606; + int right = (t->rvol+84)*606; - switch (cmd) { - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ - case VIDIOCGAUDIO: + ctrl->value=max(left,right); + return 0; + } + case V4L2_CID_AUDIO_BALANCE: { - struct video_audio *va = arg; - int left,right; + int left = (t->lvol+84)*606; + int right = (t->rvol+84)*606; + int volume = max(left,right); + int balance = (32768*min(left,right))/ + (volume ? volume : 1); + ctrl->value=(leftvalue = (t->bass+12)*2427; /* min -12 max +15 */ + return 0; + case V4L2_CID_AUDIO_TREBLE: + ctrl->value = (t->treble+12)*2730;/* min -12 max +12 */ + return 0; + } + return -EINVAL; +} - dprintk("VIDIOCGAUDIO\n"); +static int tda9875_set_ctrl(struct i2c_client *client, + struct v4l2_control *ctrl) +{ + struct tda9875 *t = i2c_get_clientdata(client); + int chvol=0, volume, balance, left, right; - va->flags |= VIDEO_AUDIO_VOLUME | - VIDEO_AUDIO_BASS | - VIDEO_AUDIO_TREBLE; + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: + left = (t->lvol+84)*606; + right = (t->rvol+84)*606; + + volume = max(left,right); + balance = (32768*min(left,right))/ + (volume ? volume : 1); + balance =(leftvalue; - /* min is -84 max is 24 */ + chvol=1; + break; + case V4L2_CID_AUDIO_BALANCE: left = (t->lvol+84)*606; right = (t->rvol+84)*606; - va->volume=max(left,right); - va->balance=(32768*min(left,right))/ - (va->volume ? va->volume : 1); - va->balance=(leftbalance) : va->balance; - va->bass = (t->bass+12)*2427; /* min -12 max +15 */ - va->treble = (t->treble+12)*2730;/* min -12 max +12 */ - va->mode |= VIDEO_SOUND_MONO; - - break; /* VIDIOCGAUDIO case */ + + volume=max(left,right); + + balance = ctrl->value; + + chvol=1; + break; + case V4L2_CID_AUDIO_BASS: + t->bass = ((ctrl->value/2400)-12) & 0xff; + if (t->bass > 15) + t->bass = 15; + if (t->bass < -12) + t->bass = -12 & 0xff; + break; + case V4L2_CID_AUDIO_TREBLE: + t->treble = ((ctrl->value/2700)-12) & 0xff; + if (t->treble > 12) + t->treble = 12; + if (t->treble < -12) + t->treble = -12 & 0xff; + break; + default: + return -EINVAL; } - case VIDIOCSAUDIO: - { - struct video_audio *va = arg; - int left,right; - - dprintk("VIDEOCSAUDIO...\n"); - left = (min(65536 - va->balance,32768) * - va->volume) / 32768; - right = (min(va->balance,(__u16)32768) * - va->volume) / 32768; + if (chvol) { + left = (min(65536 - balance,32768) * + volume) / 32768; + right = (min(balance,32768) * + volume) / 32768; t->lvol = ((left/606)-84) & 0xff; if (t->lvol > 24) - t->lvol = 24; + t->lvol = 24; if (t->lvol < -84) - t->lvol = -84 & 0xff; + t->lvol = -84 & 0xff; t->rvol = ((right/606)-84) & 0xff; if (t->rvol > 24) - t->rvol = 24; + t->rvol = 24; if (t->rvol < -84) - t->rvol = -84 & 0xff; - - t->bass = ((va->bass/2400)-12) & 0xff; - if (t->bass > 15) - t->bass = 15; - if (t->bass < -12) - t->bass = -12 & 0xff; - - t->treble = ((va->treble/2700)-12) & 0xff; - if (t->treble > 12) - t->treble = 12; - if (t->treble < -12) - t->treble = -12 & 0xff; + t->rvol = -84 & 0xff; + } +//printk("tda9875 bal:%04x vol:%04x bass:%04x treble:%04x\n",va->balance,va->volume,va->bass,va->treble); + tda9875_set(client); -//printk("tda9875 bal:%04x vol:%04x bass:%04x treble:%04x\n",va->balance,va->volume,va->bass,va->treble); + return 0; +} - tda9875_set(client); +static int tda9875_command(struct i2c_client *client, + unsigned int cmd, void *arg) +{ + dprintk("In tda9875_command...\n"); - break; + switch (cmd) { + /* --- v4l ioctls --- */ + /* take care: bttv does userspace copying, we'll get a + kernel pointer here... */ + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *qc = arg; + + switch (qc->id) { + case V4L2_CID_AUDIO_VOLUME: + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + default: + return -EINVAL; + } + return v4l2_ctrl_query_fill_std(qc); + } + case VIDIOC_S_CTRL: + return tda9875_set_ctrl(client, arg); - } /* end of VIDEOCSAUDIO case */ + case VIDIOC_G_CTRL: + return tda9875_get_ctrl(client, arg); default: /* Not VIDEOCGAUDIO or VIDEOCSAUDIO */ -- cgit v1.2.3 From b8056c434721c17f8cc3426ce74a440b1e760d9d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 25 Aug 2006 16:53:11 -0300 Subject: Make Kconfig reflect the changes at audio helper modules From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) --- linux/drivers/media/video/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 2e571eb93..20f7c57bb 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -45,7 +45,7 @@ comment "Audio decoders" config VIDEO_TVAUDIO tristate "Simple audio decoder chips" - depends on VIDEO_V4L1 && I2C + depends on VIDEO_V4L2 && I2C ---help--- Support for several audio decoder chips found on some bt8xx boards: Philips: tda9840, tda9873h, tda9874h/a, tda9850, tda985x, tea6300, @@ -57,7 +57,7 @@ config VIDEO_TVAUDIO config VIDEO_TDA7432 tristate "Philips TDA7432 audio processor" - depends on VIDEO_V4L1 && I2C + depends on VIDEO_V4L2 && I2C ---help--- Support for tda7432 audio decoder chip found on some bt8xx boards. @@ -75,7 +75,7 @@ config VIDEO_TDA9840 config VIDEO_TDA9875 tristate "Philips TDA9875 audio processor" - depends on VIDEO_V4L1 && I2C + depends on VIDEO_V4L2 && I2C ---help--- Support for tda9875 audio decoder chip found on some bt8xx boards. -- cgit v1.2.3 From 7c8e1a2aecbfdcad224468d9500ce587901fbcc4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 24 Oct 2007 12:08:20 -0200 Subject: Remove the obsoleted xc3028 From: Mauro Carvalho Chehab Remove the old xc3028.c file, replacing all occurrences of TUNER_XCEIVE_XC3028 to TUNER_XC2028. Some work is still may be required to make sure that non-tm6000 drivers will be capable of using tuner-xc2028. Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/CARDLIST.tuner | 2 +- linux/drivers/media/video/em28xx/em28xx-cards.c | 10 +++------- linux/drivers/media/video/ivtv/ivtv-cards.c | 6 +++--- linux/drivers/media/video/ivtv/ivtv-driver.c | 2 +- linux/drivers/media/video/tuner-core.c | 5 ----- linux/drivers/media/video/tuner-types.c | 6 +++--- linux/include/media/tuner.h | 2 +- v4l/Makefile | 4 ---- 8 files changed, 12 insertions(+), 25 deletions(-) --- linux/drivers/media/video/em28xx/em28xx-cards.c | 10 +++------- linux/drivers/media/video/ivtv/ivtv-cards.c | 6 +++--- linux/drivers/media/video/ivtv/ivtv-driver.c | 2 +- linux/drivers/media/video/tuner-core.c | 5 ----- linux/drivers/media/video/tuner-types.c | 6 +++--- 5 files changed, 10 insertions(+), 19 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 9809463b6..441b03d30 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -157,13 +157,12 @@ struct em28xx_board em28xx_boards[] = { MSP_DSP_IN_SCART, MSP_DSP_IN_SCART), }}, }, -#ifdef CONFIG_XC3028 [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = { .name = "Hauppauge WinTV HVR 900", .vchannels = 3, .norm = VIDEO_MODE_PAL, .tda9887_conf = TDA9887_PRESENT, - .tuner_type = TUNER_XCEIVE_XC3028, + .tuner_type = TUNER_XC2028, .has_tuner = 1, .decoder = EM28XX_TVP5150, .input = {{ @@ -186,7 +185,7 @@ struct em28xx_board em28xx_boards[] = { .norm = VIDEO_MODE_PAL, .tda9887_conf = TDA9887_PRESENT, .has_tuner = 1, - .tuner_type = TUNER_XCEIVE_XC3028, + .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, .input = {{ .type = EM28XX_VMUX_TELEVISION, @@ -210,7 +209,7 @@ struct em28xx_board em28xx_boards[] = { .norm = VIDEO_MODE_PAL, .tda9887_conf = TDA9887_PRESENT, .has_tuner = 1, - .tuner_type = TUNER_XCEIVE_XC3028, + .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, .input = {{ .type = EM28XX_VMUX_TELEVISION, @@ -226,7 +225,6 @@ struct em28xx_board em28xx_boards[] = { .amux = 1, }}, }, -#endif [EM2820_BOARD_MSI_VOX_USB_2] = { .name = "MSI VOX USB 2.0", .vchannels = 3, @@ -345,11 +343,9 @@ struct usb_device_id em28xx_id_table [] = { { USB_DEVICE(0x2304, 0x0208), .driver_info = EM2820_BOARD_PINNACLE_USB_2 }, { USB_DEVICE(0x2040, 0x4200), .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, { USB_DEVICE(0x2304, 0x0207), .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, -#ifdef CONFIG_XC3028 { USB_DEVICE(0x2040, 0x6500), .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, { USB_DEVICE(0x0ccd, 0x0042), .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS }, { USB_DEVICE(0x0ccd, 0x0047), .driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS }, -#endif { }, }; diff --git a/linux/drivers/media/video/ivtv/ivtv-cards.c b/linux/drivers/media/video/ivtv/ivtv-cards.c index 26c1cb3fd..bf6948eda 100644 --- a/linux/drivers/media/video/ivtv/ivtv-cards.c +++ b/linux/drivers/media/video/ivtv/ivtv-cards.c @@ -863,7 +863,7 @@ static const struct ivtv_card ivtv_card_pg600v2 = { }, #endif .tuners = { - { .std = V4L2_STD_ALL, .tuner = TUNER_XCEIVE_XC3028 }, + { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, }, .pci_list = ivtv_pci_pg600v2, }; @@ -909,7 +909,7 @@ static const struct ivtv_card ivtv_card_club3d = { }, #endif .tuners = { - { .std = V4L2_STD_ALL, .tuner = TUNER_XCEIVE_XC3028 }, + { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, }, .pci_list = ivtv_pci_club3d, }; @@ -954,7 +954,7 @@ static const struct ivtv_card ivtv_card_avertv_mce116 = { .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 }, /* enable line-in */ #endif .tuners = { - { .std = V4L2_STD_ALL, .tuner = TUNER_XCEIVE_XC3028 }, + { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, }, .pci_list = ivtv_pci_avertv_mce116, }; diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c index 59837795c..051593a17 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.c +++ b/linux/drivers/media/video/ivtv/ivtv-driver.c @@ -833,7 +833,7 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) /* load modules */ #ifndef CONFIG_VIDEO_TUNER if (hw & IVTV_HW_TUNER) { - if (itv->options.tuner == TUNER_XCEIVE_XC3028) { + if (itv->options.tuner == TUNER_XC2028) { IVTV_INFO("Xceive tuner not yet supported, only composite and S-Video inputs will be available\n"); itv->tunerid = 1; } diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 79c2d1981..48aabcb70 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -352,11 +352,6 @@ static void set_type(struct i2c_client *c, unsigned int type, case TUNER_TDA9887: tda9887_tuner_init(t); break; -#ifdef CONFIG_XC3028 - case TUNER_XCEIVE_XC3028: - xc3028_init(c); - break; -#endif default: attach_simple_tuner(t); break; diff --git a/linux/drivers/media/video/tuner-types.c b/linux/drivers/media/video/tuner-types.c index 13f3c7378..ff8b72854 100644 --- a/linux/drivers/media/video/tuner-types.c +++ b/linux/drivers/media/video/tuner-types.c @@ -1500,9 +1500,9 @@ struct tunertype tuners[] = { .params = tuner_samsung_tcpn_2121p30a_params, .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_params), }, - [TUNER_XCEIVE_XC3028] = { /* Xceive 3028 */ - .name = "Xceive xc3028", - /* see xc3028.c for details */ + [TUNER_XC2028] = { /* Xceive 2028 */ + .name = "Xceive xc2028/xc3028 tuner", + /* see tuner-xc2028.c for details */ }, [TUNER_THOMSON_FE6600] = { /* Thomson PAL / DVB-T */ .name = "Thomson FE6600", -- cgit v1.2.3 From 2a79b63774ae84b3f0f43c058e9c2a1bf8cf0ce9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 2 Oct 2007 11:57:03 -0300 Subject: Add tuner-xc2028 driver From: Mauro Carvalho Chehab Add support for Xceive XC2028/XC3028 tuner driver Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/Kconfig | 12 linux/drivers/media/video/Makefile | 4 linux/drivers/media/video/tuner-core.c | 5 linux/drivers/media/video/tuner-driver.h | 2 linux/drivers/media/video/tuner-xc2028.c | 407 +++++++++++++++++++++++++++++++ linux/drivers/media/video/tuner-xc2028.h | 9 v4l/versions.txt | 1 7 files changed, 440 insertions(+) --- linux/drivers/media/video/Kconfig | 12 + linux/drivers/media/video/Makefile | 4 + linux/drivers/media/video/tuner-core.c | 5 + linux/drivers/media/video/tuner-driver.h | 2 + linux/drivers/media/video/tuner-xc2028.c | 407 +++++++++++++++++++++++++++++++ linux/drivers/media/video/tuner-xc2028.h | 9 + 6 files changed, 439 insertions(+) create mode 100644 linux/drivers/media/video/tuner-xc2028.c create mode 100644 linux/drivers/media/video/tuner-xc2028.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 20f7c57bb..546c9c284 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -505,6 +505,18 @@ config TUNER_3036 Say Y here to include support for Philips SAB3036 compatible tuners. If in doubt, say N. +config TUNER_XC2028 + tristate "Xceive xc2028 support for tm5600/tm6000 driver" + depends on I2C + select VIDEO_TUNER + help + Say Y here to include support for Xceive xc2028 tuner. This is + required on a few tm5600/tm6000 designs. You should notice + that this module currently works only with the special + firmware versions used on those Trident chips. + + If in doubt, say N. + config VIDEO_VINO tristate "SGI Vino Video For Linux (EXPERIMENTAL)" depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2 diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index b5a064163..1fd775e0a 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -6,6 +6,10 @@ zr36067-objs := zoran_procfs.o zoran_device.o \ zoran_driver.o zoran_card.o tuner-objs := tuner-core.o tuner-types.o tda9887.o +ifneq ($(CONFIG_TUNER_XC2028),) + tuner-objs += tuner-xc2028.o +endif + msp3400-objs := msp3400-driver.o msp3400-kthreads.o obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o \ diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 48aabcb70..45354d230 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -218,6 +218,8 @@ static void set_freq(struct i2c_client *c, unsigned long freq) set_tv_freq(c, freq); t->tv_freq = freq; break; + default: + tuner_dbg("freq set: unknown mode: 0x%04x!\n",t->mode); } } @@ -349,6 +351,9 @@ static void set_type(struct i2c_client *c, unsigned int type, i2c_master_send(c,buffer,4); attach_simple_tuner(t); break; + case TUNER_XC2028: + xc2028_tuner_init(c); + break; case TUNER_TDA9887: tda9887_tuner_init(t); break; diff --git a/linux/drivers/media/video/tuner-driver.h b/linux/drivers/media/video/tuner-driver.h index 9da949b25..b2e376ef3 100644 --- a/linux/drivers/media/video/tuner-driver.h +++ b/linux/drivers/media/video/tuner-driver.h @@ -70,6 +70,8 @@ struct tuner { struct tuner_operations ops; }; +extern int xc2028_tuner_init(struct i2c_client *c); + /* ------------------------------------------------------------------------ */ extern int tda9887_tuner_init(struct tuner *t); diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c new file mode 100644 index 000000000..4855cbd0b --- /dev/null +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -0,0 +1,407 @@ +/* tuner-xc2028 + * + * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org) + * This code is placed under the terms of the GNU General Public License v2 + */ + +#include +#include +#include +#include "compat.h" +#include +#include +#include "tuner-driver.h" +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#include "i2c-compat.h" +#endif +#include "tuner-xc2028.h" + +/* Firmwares used on tm5600/tm6000 + xc2028/xc3028 */ +static const char *firmware_6M = "tm6000_xc3028_DTV_6M.fw"; +static const char *firmware_8M = "tm6000_xc3028_78M.fw"; +static const char *firmware_DK = "tm6000_xc3028_DK_PAL_MTS.fw"; +static const char *firmware_MN = "tm6000_xc3028_MN_BTSC.fw"; + +struct xc2028_data { + v4l2_std_id firm_type; /* video stds supported by current firmware */ + int bandwidth; /* Firmware bandwidth: 6M, 7M or 8M */ + int need_load_generic; /* The generic firmware were loaded? */ +}; + +#define i2c_send(rc,c,buf,size) \ +if (size != (rc = i2c_master_send(c, buf, size))) \ + tuner_warn("i2c output error: rc = %d (should be %d)\n", \ + rc, (int)size); + +#define i2c_rcv(rc,c,buf,size) \ +if (size != (rc = i2c_master_recv(c, buf, size))) \ + tuner_warn("i2c input error: rc = %d (should be %d)\n", \ + rc, (int)size); + +#define send_seq(c, data...) \ +{ int rc; \ + const static u8 _val[] = data; \ + if (sizeof(_val) != \ + (rc = i2c_master_send \ + (c, _val, sizeof(_val)))) { \ + printk(KERN_ERR "Error on line %d: %d\n",__LINE__,rc); \ + return; \ + } \ + msleep (10); \ +} + +static int xc2028_get_reg(struct i2c_client *c, u16 reg) +{ + int rc; + unsigned char buf[1]; + struct tuner *t = i2c_get_clientdata(c); + + buf[0]= reg; + + i2c_send(rc, c, buf, sizeof(buf)); + if (rc<0) + return rc; + + if (t->tuner_callback) { + rc = t->tuner_callback( c->adapter->algo_data, + XC2028_RESET_CLK, 0); + if (rc<0) + return rc; + } + + i2c_rcv(rc, c, buf, 2); + if (rc<0) + return rc; + + return (buf[1])|(buf[0]<<8); +} + +static int load_firmware (struct i2c_client *c, const char *name) +{ + const struct firmware *fw=NULL; + struct tuner *t = i2c_get_clientdata(c); + unsigned char *p, *endp; + int len=0, rc=0; + static const char firmware_ver[] = "tm6000/xcv v1"; + + tuner_info("Loading firmware %s\n", name); + rc = request_firmware(&fw, name, &c->dev); + if (rc < 0) { + tuner_info("Error %d while requesting firmware\n", rc); + return rc; + } + p=fw->data; + endp=p+fw->size; + + if(fw->size==0) { + tuner_info("Error: firmware size is zero!\n"); + rc=-EINVAL; + goto err; + } + if (fw->sizesize,(int)sizeof(firmware_ver)-1); + rc=-EINVAL; + goto err; + } + + if (memcmp(p,firmware_ver,sizeof(firmware_ver)-1)) { + /* Firmware is incorrect */ + tuner_info("Error: firmware is not for tm5600/6000 + Xcv2028/3028!\n"); + rc=-EINVAL; + goto err; + } + p+=sizeof(firmware_ver)-1; + + while(ptuner_callback(c->adapter->algo_data, + XC2028_TUNER_RESET, (*p)&0x7f); + if (rc<0) { + tuner_info("Error at RESET code %d\n", + (*p)&0x7f); + goto err; + } + p++; + continue; + } + len=*p; + p++; + if (p+len+1>endp) { + /* Firmware is incorrect */ + tuner_info("Error: firmware is truncated!\n"); + rc=-EINVAL; + goto err; + } + if (len<=0) { + tuner_info("Error: firmware file is corrupted!\n"); + rc=-EINVAL; + goto err; + } + + i2c_send(rc, c, p, len); + if (rc<0) + goto err; + p+=len; + + if (*p) + msleep(*p); + p++; + } + + +err: + release_firmware(fw); + + return rc; +} + +static int check_firmware(struct i2c_client *c) +{ + int rc, version; + struct tuner *t = i2c_get_clientdata(c); + struct xc2028_data *xc2028 = t->priv; + const char *name; + + if (!t->tuner_callback) { + printk(KERN_ERR "xc2028: need tuner_callback to load firmware\n"); + return -EINVAL; + } + + if (xc2028->need_load_generic) { + if (xc2028->bandwidth==6) + name = firmware_6M; + else + name = firmware_8M; + + /* Reset is needed before loading firmware */ + rc = t->tuner_callback(c->adapter->algo_data, + XC2028_TUNER_RESET, 0); + if (rc<0) + return rc; + + rc = load_firmware(c,name); + if (rc<0) + return rc; + + xc2028->need_load_generic=0; + xc2028->firm_type=0; + } + + if (xc2028->firm_type & t->std) + return 0; + + if (t->std & V4L2_STD_MN) + name=firmware_MN; + else + name=firmware_DK; + + rc = load_firmware(c,name); + if (rc<0) + return rc; + + version = xc2028_get_reg(c, 0x4); + tuner_info("Firmware version is %d.%d\n", + (version>>4)&0x0f,(version)&0x0f); + + xc2028->firm_type=t->std; + + return 0; +} + +static int xc2028_signal(struct i2c_client *c) +{ + int lock, signal; + + if (check_firmware(c)<0) + return 0; + + lock = xc2028_get_reg(c, 0x2); + if (lock<=0) + return lock; + + /* Frequency is locked. Return signal quality */ + + signal = xc2028_get_reg(c, 0x40); + + if(signal<=0) + return lock; + + return signal; +} + +#define DIV 15625 + +static void set_tv_freq(struct i2c_client *c, unsigned int freq) +{ + int rc; + unsigned char buf[5]; + struct tuner *t = i2c_get_clientdata(c); + unsigned long div = (freq*62500l+DIV/2)/DIV; + + if (check_firmware(c)<0) + return; + + /* Reset GPIO 1 */ + if (t->tuner_callback) { + rc = t->tuner_callback( c->adapter->algo_data, + XC2028_TUNER_RESET, 0); + if (rc<0) + return; + } + msleep(10); + + send_seq (c, {0x12, 0x39}); + send_seq (c, {0x0c, 0x80, 0xf0, 0xf7, 0x3e, 0x75, 0xc1, 0x8a, 0xe4}); + send_seq (c, {0x0c, 0x02, 0x00}); + send_seq (c, {0x05, 0x0f, 0xee, 0xaa, 0x5f, 0xea, 0x90}); + send_seq (c, {0x06, 0x00, 0x0a, 0x4d, 0x8c, 0xf2, 0xd8, 0xcf, 0x30}); + send_seq (c, {0x06, 0x79, 0x9f}); + send_seq (c, {0x0b, 0x0d, 0xa4, 0x6c}); + send_seq (c, {0x0a, 0x01, 0x67, 0x24, 0x40, 0x08, 0xc3, 0x20, 0x10}); + send_seq (c, {0x0a, 0x64, 0x3c, 0xfa, 0xf7, 0xe1, 0x0c, 0x2c}); + send_seq (c, {0x09, 0x0b}); + send_seq (c, {0x10, 0x13}); + send_seq (c, {0x16, 0x12}); + send_seq (c, {0x1f, 0x02}); + send_seq (c, {0x21, 0x02}); + send_seq (c, {0x01, 0x02}); + send_seq (c, {0x2b, 0x10}); + send_seq (c, {0x02, 0x02}); + send_seq (c, {0x02, 0x03}); + send_seq (c, {0x00, 0x8c}); + + send_seq (c, {0x00, 0x01, 0x00, 0x00}); + send_seq (c, {0x00, 0xcc, 0x20, 0x06}); + send_seq (c, {0x2b, 0x1a}); + send_seq (c, {0x2b, 0x1b}); + send_seq (c, {0x14, 0x01, 0x1b, 0x19, 0xb5, 0x29, 0xab, 0x09, 0x55}); + send_seq (c, {0x14, 0x44, 0x05, 0x65}); + send_seq (c, {0x13, 0x18, 0x08, 0x00, 0x00, 0x6c, 0x18, 0x16, 0x8c}); + send_seq (c, {0x13, 0x49, 0x2a, 0xab}); + send_seq (c, {0x0d, 0x01, 0x4b, 0x03, 0x97, 0x55, 0xc7, 0xd7, 0x00}); + send_seq (c, {0x0d, 0xa1, 0xeb, 0x8f, 0x5c}); + send_seq (c, {0x1a, 0x00, 0x00, 0x16, 0x8a, 0x40, 0x00, 0x00, 0x00, 0x20}); + send_seq (c, {0x2d, 0x01}); + send_seq (c, {0x18, 0x00}); + send_seq (c, {0x1b, 0x0d, 0x86, 0x51, 0xd2, 0x35, 0xa4, 0x92, 0xa5}); + send_seq (c, {0x1b, 0xb5, 0x25, 0x65}); + send_seq (c, {0x1d, 0x00}); + send_seq (c, {0x0f, 0x00, 0x29, 0x56, 0xb0, 0x00, 0xb6}); + send_seq (c, {0x20, 0x00}); + send_seq (c, {0x1e, 0x09, 0x02, 0x5b, 0x6c, 0x00, 0x4b, 0x81, 0x56}); + send_seq (c, {0x1e, 0x46, 0x69, 0x0b}); + send_seq (c, {0x22, 0x32}); + send_seq (c, {0x23, 0x0a}); + send_seq (c, {0x25, 0x00, 0x09, 0x90, 0x09, 0x06, 0x64, 0x02, 0x41}); + send_seq (c, {0x26, 0xcc}); + send_seq (c, {0x29, 0x40}); + send_seq (c, {0x21, 0x03}); + send_seq (c, {0x00, 0x8c}); + send_seq (c, {0x00, 0x00, 0x00, 0x00}); + + /* CMD= Set frequency */ + send_seq(c, {0x00, 0x02, 0x00, 0x00}); + if (t->tuner_callback) { + rc = t->tuner_callback( c->adapter->algo_data, + XC2028_RESET_CLK, 1); + if (rc<0) + return; + } + + msleep(10); +// send_seq(c, {0x00, 0x00, 0x10, 0xd0, 0x00}); +// msleep(100); + buf[0]= 0xff & (div>>24); + buf[1]= 0xff & (div>>16); + buf[2]= 0xff & (div>>8); + buf[3]= 0xff & (div); + buf[4]= 0; + + i2c_send(rc, c, buf, sizeof(buf)); + if (rc<0) + return; + msleep(100); + + printk("divider= %02x %02x %02x %02x (freq=%d.%02d)\n", + buf[1],buf[2],buf[3],buf[4], + freq / 16, freq % 16 * 100 / 16); +// printk("signal=%d\n",xc2028_signal(c)); +} + +#if 0 +static int xc2028_stereo(struct i2c_client *c) +{ + unsigned char buffer[5]; + int rc; + struct tuner *t = i2c_get_clientdata(c); + + if (check_firmware(c)<0) + return 0; +} + +#endif + +static void xc2028_release(struct i2c_client *c) +{ + struct tuner *t = i2c_get_clientdata(c); + + kfree(t->priv); + t->priv = NULL; +} + +static struct tuner_operations tea5767_tuner_ops = { + .set_tv_freq = set_tv_freq, + .has_signal = xc2028_signal, + .release = xc2028_release, +// .is_stereo = xc2028_stereo, +}; + + +static int init=0; + +int xc2028_tuner_init(struct i2c_client *c) +{ + struct tuner *t = i2c_get_clientdata(c); + int version = xc2028_get_reg(c, 0x4); + int prd_id = xc2028_get_reg(c, 0x8); + struct xc2028_data *xc2028; + + if (init) { + printk (KERN_ERR "Module already initialized!\n"); + return 0; + } + init++; + + xc2028 = kzalloc(sizeof(*xc2028), GFP_KERNEL); + if (!xc2028) + return -ENOMEM; + t->priv = xc2028; + +#ifdef HACK + xc2028->firm_type=1; + xc2028->bandwidth=6; +#endif + xc2028->bandwidth=6; + xc2028->need_load_generic=1; + + /* FIXME: Check where t->priv will be freed */ + + if (version<0) + version=0; + + if (prd_id<0) + prd_id=0; + + strlcpy(c->name, "xc2028", sizeof(c->name)); + tuner_info("type set to %d (%s, hw ver=%d.%d, fw ver=%d.%d, id=0x%04x)\n", + t->type, c->name, + (version>>12)&0x0f,(version>>8)&0x0f, + (version>>4)&0x0f,(version)&0x0f, prd_id); + + memcpy(&t->ops, &tea5767_tuner_ops, sizeof(struct tuner_operations)); + + return 0; +} diff --git a/linux/drivers/media/video/tuner-xc2028.h b/linux/drivers/media/video/tuner-xc2028.h new file mode 100644 index 000000000..7c540c387 --- /dev/null +++ b/linux/drivers/media/video/tuner-xc2028.h @@ -0,0 +1,9 @@ +/* tuner-xc2028 + * + * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org) + * This code is placed under the terms of the GNU General Public License v2 + */ + +/* xc2028 commands for callback */ +#define XC2028_TUNER_RESET 0 +#define XC2028_RESET_CLK 1 -- cgit v1.2.3 From 908c46b58537173c0c70a9a9f0702d86b26ae7b1 Mon Sep 17 00:00:00 2001 From: Michel Ludwig Date: Wed, 18 Jul 2007 10:26:38 -0300 Subject: Improve tuner-xc2028 script From: Michel Ludwig Signed-off-by: Michel Ludwig Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-xc2028.c | 50 ++++++++++++++++++------------- 1 file changed, 30 insertions(+), 20 deletions(-) --- linux/drivers/media/video/tuner-xc2028.c | 50 +++++++++++++++++++------------- 1 file changed, 30 insertions(+), 20 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c index 4855cbd0b..4ce21b25b 100644 --- a/linux/drivers/media/video/tuner-xc2028.c +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -193,6 +193,26 @@ static int check_firmware(struct i2c_client *c) if (xc2028->firm_type & t->std) return 0; + send_seq (c, {0x12, 0x39}); + send_seq (c, {0x0c, 0x80, 0xf0, 0xf7, 0x3e, 0x75, 0xc1, 0x8a, 0xe4}); + send_seq (c, {0x0c, 0x02, 0x00}); + send_seq (c, {0x05, 0x0f, 0xee, 0xaa, 0x5f, 0xea, 0x90}); + send_seq (c, {0x06, 0x00, 0x0a, 0x4d, 0x8c, 0xf2, 0xd8, 0xcf, 0x30}); + send_seq (c, {0x06, 0x79, 0x9f}); + send_seq (c, {0x0b, 0x0d, 0xa4, 0x6c}); + send_seq (c, {0x0a, 0x01, 0x67, 0x24, 0x40, 0x08, 0xc3, 0x20, 0x10}); + send_seq (c, {0x0a, 0x64, 0x3c, 0xfa, 0xf7, 0xe1, 0x0c, 0x2c}); + send_seq (c, {0x09, 0x0b}); + send_seq (c, {0x10, 0x13}); + send_seq (c, {0x16, 0x12}); + send_seq (c, {0x1f, 0x02}); + send_seq (c, {0x21, 0x02}); + send_seq (c, {0x01, 0x02}); + send_seq (c, {0x2b, 0x10}); + send_seq (c, {0x02, 0x02}); + send_seq (c, {0x02, 0x03}); + send_seq (c, {0x00, 0x8c}); + if (t->std & V4L2_STD_MN) name=firmware_MN; else @@ -253,26 +273,7 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) } msleep(10); - send_seq (c, {0x12, 0x39}); - send_seq (c, {0x0c, 0x80, 0xf0, 0xf7, 0x3e, 0x75, 0xc1, 0x8a, 0xe4}); - send_seq (c, {0x0c, 0x02, 0x00}); - send_seq (c, {0x05, 0x0f, 0xee, 0xaa, 0x5f, 0xea, 0x90}); - send_seq (c, {0x06, 0x00, 0x0a, 0x4d, 0x8c, 0xf2, 0xd8, 0xcf, 0x30}); - send_seq (c, {0x06, 0x79, 0x9f}); - send_seq (c, {0x0b, 0x0d, 0xa4, 0x6c}); - send_seq (c, {0x0a, 0x01, 0x67, 0x24, 0x40, 0x08, 0xc3, 0x20, 0x10}); - send_seq (c, {0x0a, 0x64, 0x3c, 0xfa, 0xf7, 0xe1, 0x0c, 0x2c}); - send_seq (c, {0x09, 0x0b}); - send_seq (c, {0x10, 0x13}); - send_seq (c, {0x16, 0x12}); - send_seq (c, {0x1f, 0x02}); - send_seq (c, {0x21, 0x02}); - send_seq (c, {0x01, 0x02}); - send_seq (c, {0x2b, 0x10}); - send_seq (c, {0x02, 0x02}); - send_seq (c, {0x02, 0x03}); - send_seq (c, {0x00, 0x8c}); - +#if 0 send_seq (c, {0x00, 0x01, 0x00, 0x00}); send_seq (c, {0x00, 0xcc, 0x20, 0x06}); send_seq (c, {0x2b, 0x1a}); @@ -301,7 +302,16 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) send_seq (c, {0x21, 0x03}); send_seq (c, {0x00, 0x8c}); send_seq (c, {0x00, 0x00, 0x00, 0x00}); +//#else + char *name; + + if (t->std & V4L2_STD_MN) + name=firmware_MN; + else + name=firmware_DK; + rc = load_firmware(c,name); +#endif /* CMD= Set frequency */ send_seq(c, {0x00, 0x02, 0x00, 0x00}); if (t->tuner_callback) { -- cgit v1.2.3 From 0f878821893fd3ecaa207f773994c536e5f3f5d1 Mon Sep 17 00:00:00 2001 From: Michel Ludwig Date: Wed, 18 Jul 2007 10:29:10 -0300 Subject: Add experimental DVB frontend tuner interface to xc2028/3028. From: Michel Ludwig Signed-off-by: Michel Ludwig Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-xc2028.c | 208 ++++++++++++++++++++++++++++--- linux/drivers/media/video/tuner-xc2028.h | 5 2 files changed, 193 insertions(+), 20 deletions(-) --- linux/drivers/media/video/tuner-xc2028.c | 208 ++++++++++++++++++++++++++++--- linux/drivers/media/video/tuner-xc2028.h | 5 + 2 files changed, 193 insertions(+), 20 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c index 4ce21b25b..dc85e4333 100644 --- a/linux/drivers/media/video/tuner-xc2028.c +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -1,6 +1,8 @@ /* tuner-xc2028 * * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org) + * Copyright (c) 2007 Michel Ludwig (michel.ludwig@gmail.com) + * - frontend interface * This code is placed under the terms of the GNU General Public License v2 */ @@ -10,22 +12,41 @@ #include "compat.h" #include #include +#include #include "tuner-driver.h" #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "i2c-compat.h" #endif #include "tuner-xc2028.h" +#include +#include "dvb_frontend.h" + +/* digital TV standards */ +#define V4L2_STD_DTV_6MHZ ((v4l2_std_id)0x04000000) +#define V4L2_STD_DTV_7MHZ ((v4l2_std_id)0x08000000) +#define V4L2_STD_DTV_8MHZ ((v4l2_std_id)0x10000000) + /* Firmwares used on tm5600/tm6000 + xc2028/xc3028 */ static const char *firmware_6M = "tm6000_xc3028_DTV_6M.fw"; -static const char *firmware_8M = "tm6000_xc3028_78M.fw"; +// static const char *firmware_78M = "tm6000_xc3028_78M.fw"; +static const char *firmware_7M = "tm6000_xc3028_7M.fw"; +static const char *firmware_8M = "tm6000_xc3028_8M.fw"; +static const char *firmware_B = "tm6000_xc3028_B_PAL.fw"; static const char *firmware_DK = "tm6000_xc3028_DK_PAL_MTS.fw"; static const char *firmware_MN = "tm6000_xc3028_MN_BTSC.fw"; +static const char *firmware_INIT0 = "tm6000_xc3028_INIT0.fw"; +static const char *firmware_8MHZ_INIT0 = "tm6000_xc3028_8MHZ_INIT0.fw"; struct xc2028_data { - v4l2_std_id firm_type; /* video stds supported by current firmware */ - int bandwidth; /* Firmware bandwidth: 6M, 7M or 8M */ - int need_load_generic; /* The generic firmware were loaded? */ + v4l2_std_id firm_type; /* video stds supported + by current firmware */ + fe_bandwidth_t bandwidth; /* Firmware bandwidth: + 6M, 7M or 8M */ + int need_load_generic; /* The generic firmware + were loaded? */ + enum tuner_mode mode; + struct i2c_client *i2c_client; }; #define i2c_send(rc,c,buf,size) \ @@ -84,7 +105,7 @@ static int load_firmware (struct i2c_client *c, const char *name) int len=0, rc=0; static const char firmware_ver[] = "tm6000/xcv v1"; - tuner_info("Loading firmware %s\n", name); + tuner_info("xc2028: Loading firmware %s\n", name); rc = request_firmware(&fw, name, &c->dev); if (rc < 0) { tuner_info("Error %d while requesting firmware\n", rc); @@ -158,24 +179,39 @@ err: return rc; } -static int check_firmware(struct i2c_client *c) +static int check_firmware(struct i2c_client *c, enum tuner_mode new_mode, + fe_bandwidth_t bandwidth) { int rc, version; struct tuner *t = i2c_get_clientdata(c); struct xc2028_data *xc2028 = t->priv; const char *name; + int change_digital_bandwidth; if (!t->tuner_callback) { printk(KERN_ERR "xc2028: need tuner_callback to load firmware\n"); return -EINVAL; } + printk(KERN_INFO "xc2028: I am in mode %u and I should switch to mode %i\n", + xc2028->mode, new_mode); + + /* first of all, determine whether we have switched the mode */ + if(new_mode != xc2028->mode) { + xc2028->mode = new_mode; + xc2028->need_load_generic = 1; + } + + change_digital_bandwidth = (xc2028->mode == T_DIGITAL_TV + && bandwidth != xc2028->bandwidth) ? 1 : 0; + tuner_info("xc2028: old bandwidth %u, new bandwidth %u\n", xc2028->bandwidth, + bandwidth); + if (xc2028->need_load_generic) { if (xc2028->bandwidth==6) - name = firmware_6M; + name = firmware_INIT0; else - name = firmware_8M; - + name = firmware_8MHZ_INIT0; /* Reset is needed before loading firmware */ rc = t->tuner_callback(c->adapter->algo_data, XC2028_TUNER_RESET, 0); @@ -188,11 +224,38 @@ static int check_firmware(struct i2c_client *c) xc2028->need_load_generic=0; xc2028->firm_type=0; + if(xc2028->mode == T_DIGITAL_TV) { + change_digital_bandwidth=1; + } + } + + tuner_info("xc2028: I should change bandwidth %u\n", + change_digital_bandwidth); + + if (change_digital_bandwidth) { + switch(bandwidth) { + case BANDWIDTH_8_MHZ: + t->std = V4L2_STD_DTV_8MHZ; + break; + + case BANDWIDTH_7_MHZ: + t->std = V4L2_STD_DTV_7MHZ; + break; + + case BANDWIDTH_6_MHZ: + t->std = V4L2_STD_DTV_6MHZ; + break; + + default: + tuner_info("error: bandwidth not supported.\n"); + }; + xc2028->bandwidth = bandwidth; } if (xc2028->firm_type & t->std) return 0; +#if 0 send_seq (c, {0x12, 0x39}); send_seq (c, {0x0c, 0x80, 0xf0, 0xf7, 0x3e, 0x75, 0xc1, 0x8a, 0xe4}); send_seq (c, {0x0c, 0x02, 0x00}); @@ -212,13 +275,24 @@ static int check_firmware(struct i2c_client *c) send_seq (c, {0x02, 0x02}); send_seq (c, {0x02, 0x03}); send_seq (c, {0x00, 0x8c}); +#endif if (t->std & V4L2_STD_MN) name=firmware_MN; + else if (t->std & V4L2_STD_DTV_6MHZ) + name=firmware_6M; + else if (t->std & V4L2_STD_DTV_7MHZ) + name=firmware_7M; + else if (t->std & V4L2_STD_DTV_8MHZ) + name=firmware_8M; + else if (t->std & V4L2_STD_PAL_B) + name=firmware_B; else name=firmware_DK; - rc = load_firmware(c,name); + tuner_info("xc2028: loading firmware named %s.\n", name); + + rc = load_firmware(c, name); if (rc<0) return rc; @@ -235,8 +309,7 @@ static int xc2028_signal(struct i2c_client *c) { int lock, signal; - if (check_firmware(c)<0) - return 0; + printk(KERN_INFO "xc2028: %s called\n", __FUNCTION__); lock = xc2028_get_reg(c, 0x2); if (lock<=0) @@ -254,16 +327,37 @@ static int xc2028_signal(struct i2c_client *c) #define DIV 15625 -static void set_tv_freq(struct i2c_client *c, unsigned int freq) +static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */, + enum tuner_mode new_mode, fe_bandwidth_t bandwidth) { int rc; unsigned char buf[5]; struct tuner *t = i2c_get_clientdata(c); - unsigned long div = (freq*62500l+DIV/2)/DIV; + u32 div, offset = 0; - if (check_firmware(c)<0) + printk("xc3028: should set frequency %d kHz)\n", freq / 1000); + + if (check_firmware(c, new_mode, bandwidth)<0) return; + if(new_mode == T_DIGITAL_TV) { + switch(bandwidth) { + case BANDWIDTH_8_MHZ: + offset = 2750000; + break; + + case BANDWIDTH_7_MHZ: + offset = 2750000; + break; + + case BANDWIDTH_6_MHZ: + default: + printk(KERN_ERR "xc2028: bandwidth not implemented!\n"); + } + } + + div = (freq - offset + DIV/2)/DIV; + /* Reset GPIO 1 */ if (t->tuner_callback) { rc = t->tuner_callback( c->adapter->algo_data, @@ -324,6 +418,7 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) msleep(10); // send_seq(c, {0x00, 0x00, 0x10, 0xd0, 0x00}); // msleep(100); + buf[0]= 0xff & (div>>24); buf[1]= 0xff & (div>>16); buf[2]= 0xff & (div>>8); @@ -354,6 +449,14 @@ static int xc2028_stereo(struct i2c_client *c) #endif +static void set_tv_freq(struct i2c_client *c, unsigned int freq) +{ + printk(KERN_INFO "xc2028: %s called\n", __FUNCTION__); + + generic_set_tv_freq(c, freq * 62500l, T_ANALOG_TV, + BANDWIDTH_8_MHZ /* unimportant */); +} + static void xc2028_release(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); @@ -379,6 +482,8 @@ int xc2028_tuner_init(struct i2c_client *c) int prd_id = xc2028_get_reg(c, 0x8); struct xc2028_data *xc2028; + tuner_info("Xcv2028/3028 init called!\n"); + if (init) { printk (KERN_ERR "Module already initialized!\n"); return 0; @@ -390,12 +495,9 @@ int xc2028_tuner_init(struct i2c_client *c) return -ENOMEM; t->priv = xc2028; -#ifdef HACK - xc2028->firm_type=1; - xc2028->bandwidth=6; -#endif - xc2028->bandwidth=6; + xc2028->bandwidth=BANDWIDTH_6_MHZ; xc2028->need_load_generic=1; + xc2028->mode = T_UNINITIALIZED; /* FIXME: Check where t->priv will be freed */ @@ -415,3 +517,69 @@ int xc2028_tuner_init(struct i2c_client *c) return 0; } + +static int xc3028_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct i2c_client *c = fe->tuner_priv; + + printk(KERN_INFO "xc2028: %s called\n", __FUNCTION__); + + generic_set_tv_freq(c, p->frequency, T_DIGITAL_TV, + p->u.ofdm.bandwidth); + + return 0; +} + +static int xc3028_dvb_release(struct dvb_frontend *fe) +{ + printk(KERN_INFO "xc2028: %s called\n", __FUNCTION__); + + fe->tuner_priv = NULL; + + return 0; +} + +static int xc3028_dvb_init(struct dvb_frontend *fe) +{ + printk(KERN_INFO "xc2028: %s called\n", __FUNCTION__); + + return 0; +} + +static const struct dvb_tuner_ops xc3028_dvb_tuner_ops = { + .info = { + .name = "Xceive XC3028", + .frequency_min = 42000000, + .frequency_max = 864000000, + .frequency_step = 50000, + }, + + .release = xc3028_dvb_release, + .init = xc3028_dvb_init, + +// int (*sleep)(struct dvb_frontend *fe); + + /** This is for simple PLLs - set all parameters in one go. */ + .set_params = xc3028_set_params, + + /** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */ +// int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len); + +// int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency); +// int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth); + +// int (*get_status)(struct dvb_frontend *fe, u32 *status); +}; + +int xc2028_attach(struct i2c_client *c, struct dvb_frontend *fe) +{ + fe->tuner_priv = c; + + memcpy(&fe->ops.tuner_ops, &xc3028_dvb_tuner_ops, sizeof(fe->ops.tuner_ops)); + + return 0; +} + +EXPORT_SYMBOL(xc2028_attach); + diff --git a/linux/drivers/media/video/tuner-xc2028.h b/linux/drivers/media/video/tuner-xc2028.h index 7c540c387..34ff4cba1 100644 --- a/linux/drivers/media/video/tuner-xc2028.h +++ b/linux/drivers/media/video/tuner-xc2028.h @@ -7,3 +7,8 @@ /* xc2028 commands for callback */ #define XC2028_TUNER_RESET 0 #define XC2028_RESET_CLK 1 + +struct dvb_frontend; +struct i2c_client; + +int xc2028_attach(struct i2c_client *c, struct dvb_frontend *fe); -- cgit v1.2.3 From d8052d9ecc1214929a538a3147d65f8550b70733 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 18 Jul 2007 13:33:23 -0300 Subject: Some fixes on tuner-xc2028 From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-xc2028.c | 113 +++++++++++++------------------ 1 file changed, 48 insertions(+), 65 deletions(-) --- linux/drivers/media/video/tuner-xc2028.c | 113 +++++++++++++------------------ 1 file changed, 48 insertions(+), 65 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c index dc85e4333..a387f03d4 100644 --- a/linux/drivers/media/video/tuner-xc2028.c +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -28,15 +28,19 @@ #define V4L2_STD_DTV_8MHZ ((v4l2_std_id)0x10000000) /* Firmwares used on tm5600/tm6000 + xc2028/xc3028 */ -static const char *firmware_6M = "tm6000_xc3028_DTV_6M.fw"; -// static const char *firmware_78M = "tm6000_xc3028_78M.fw"; -static const char *firmware_7M = "tm6000_xc3028_7M.fw"; -static const char *firmware_8M = "tm6000_xc3028_8M.fw"; -static const char *firmware_B = "tm6000_xc3028_B_PAL.fw"; -static const char *firmware_DK = "tm6000_xc3028_DK_PAL_MTS.fw"; -static const char *firmware_MN = "tm6000_xc3028_MN_BTSC.fw"; -static const char *firmware_INIT0 = "tm6000_xc3028_INIT0.fw"; -static const char *firmware_8MHZ_INIT0 = "tm6000_xc3028_8MHZ_INIT0.fw"; + +/* Generic firmwares */ +static const char *firmware_INIT0 = "tm_xc3028_MTS_init0.fw"; +static const char *firmware_8MHZ_INIT0 = "tm_xc3028_8M_MTS_init0.fw"; +static const char *firmware_INIT1 = "tm_xc3028_68M_MTS_init1.fw"; + +/* Standard-specific firmwares */ +static const char *firmware_6M = "tm_xc3028_DTV_6M.fw"; +static const char *firmware_7M = "tm_xc3028_7M.fw"; +static const char *firmware_8M = "tm_xc3028_8M.fw"; +static const char *firmware_B = "tm_xc3028_B_PAL.fw"; +static const char *firmware_DK = "tm_xc3028_DK_PAL_MTS.fw"; +static const char *firmware_MN = "tm_xc3028_MN_BTSC.fw"; struct xc2028_data { v4l2_std_id firm_type; /* video stds supported @@ -83,13 +87,14 @@ static int xc2028_get_reg(struct i2c_client *c, u16 reg) if (rc<0) return rc; +#if 0 if (t->tuner_callback) { rc = t->tuner_callback( c->adapter->algo_data, XC2028_RESET_CLK, 0); if (rc<0) return rc; } - +#endif i2c_rcv(rc, c, buf, 2); if (rc<0) return rc; @@ -108,7 +113,11 @@ static int load_firmware (struct i2c_client *c, const char *name) tuner_info("xc2028: Loading firmware %s\n", name); rc = request_firmware(&fw, name, &c->dev); if (rc < 0) { - tuner_info("Error %d while requesting firmware\n", rc); + if (rc==-ENOENT) + tuner_info("Error: firmware %s not found.\n", name); + else + tuner_info("Error %d while requesting firmware %s \n", rc, name); + return rc; } p=fw->data; @@ -208,10 +217,11 @@ static int check_firmware(struct i2c_client *c, enum tuner_mode new_mode, bandwidth); if (xc2028->need_load_generic) { - if (xc2028->bandwidth==6) - name = firmware_INIT0; - else + if (xc2028->bandwidth==8) name = firmware_8MHZ_INIT0; + else + name = firmware_INIT0; + /* Reset is needed before loading firmware */ rc = t->tuner_callback(c->adapter->algo_data, XC2028_TUNER_RESET, 0); @@ -252,30 +262,22 @@ static int check_firmware(struct i2c_client *c, enum tuner_mode new_mode, xc2028->bandwidth = bandwidth; } - if (xc2028->firm_type & t->std) + if (xc2028->firm_type & t->std) { + tuner_info("xc3028: no need to load a std-specific firmware.\n"); return 0; + } #if 0 - send_seq (c, {0x12, 0x39}); - send_seq (c, {0x0c, 0x80, 0xf0, 0xf7, 0x3e, 0x75, 0xc1, 0x8a, 0xe4}); - send_seq (c, {0x0c, 0x02, 0x00}); - send_seq (c, {0x05, 0x0f, 0xee, 0xaa, 0x5f, 0xea, 0x90}); - send_seq (c, {0x06, 0x00, 0x0a, 0x4d, 0x8c, 0xf2, 0xd8, 0xcf, 0x30}); - send_seq (c, {0x06, 0x79, 0x9f}); - send_seq (c, {0x0b, 0x0d, 0xa4, 0x6c}); - send_seq (c, {0x0a, 0x01, 0x67, 0x24, 0x40, 0x08, 0xc3, 0x20, 0x10}); - send_seq (c, {0x0a, 0x64, 0x3c, 0xfa, 0xf7, 0xe1, 0x0c, 0x2c}); - send_seq (c, {0x09, 0x0b}); - send_seq (c, {0x10, 0x13}); - send_seq (c, {0x16, 0x12}); - send_seq (c, {0x1f, 0x02}); - send_seq (c, {0x21, 0x02}); - send_seq (c, {0x01, 0x02}); - send_seq (c, {0x2b, 0x10}); - send_seq (c, {0x02, 0x02}); - send_seq (c, {0x02, 0x03}); - send_seq (c, {0x00, 0x8c}); + /* Reset GPIO 1 */ + if (t->tuner_callback) { + rc = t->tuner_callback( c->adapter->algo_data, + XC2028_TUNER_RESET, 0); + if (rc<0) + return; + } + msleep(10); #endif + rc = load_firmware(c,firmware_INIT1); if (t->std & V4L2_STD_MN) name=firmware_MN; @@ -291,7 +293,6 @@ static int check_firmware(struct i2c_client *c, enum tuner_mode new_mode, name=firmware_DK; tuner_info("xc2028: loading firmware named %s.\n", name); - rc = load_firmware(c, name); if (rc<0) return rc; @@ -335,6 +336,13 @@ static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */, struct tuner *t = i2c_get_clientdata(c); u32 div, offset = 0; +#if 0 + /* HACK: It seems that specific firmware need to be reloaded + when freq is changed */ + struct xc2028_data *xc2028 = t->priv; + + xc2028->firm_type=0; +#endif printk("xc3028: should set frequency %d kHz)\n", freq / 1000); if (check_firmware(c, new_mode, bandwidth)<0) @@ -358,6 +366,7 @@ static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */, div = (freq - offset + DIV/2)/DIV; +#if 1 /* Reset GPIO 1 */ if (t->tuner_callback) { rc = t->tuner_callback( c->adapter->algo_data, @@ -366,39 +375,13 @@ static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */, return; } msleep(10); +#endif -#if 0 - send_seq (c, {0x00, 0x01, 0x00, 0x00}); - send_seq (c, {0x00, 0xcc, 0x20, 0x06}); - send_seq (c, {0x2b, 0x1a}); - send_seq (c, {0x2b, 0x1b}); - send_seq (c, {0x14, 0x01, 0x1b, 0x19, 0xb5, 0x29, 0xab, 0x09, 0x55}); - send_seq (c, {0x14, 0x44, 0x05, 0x65}); - send_seq (c, {0x13, 0x18, 0x08, 0x00, 0x00, 0x6c, 0x18, 0x16, 0x8c}); - send_seq (c, {0x13, 0x49, 0x2a, 0xab}); - send_seq (c, {0x0d, 0x01, 0x4b, 0x03, 0x97, 0x55, 0xc7, 0xd7, 0x00}); - send_seq (c, {0x0d, 0xa1, 0xeb, 0x8f, 0x5c}); - send_seq (c, {0x1a, 0x00, 0x00, 0x16, 0x8a, 0x40, 0x00, 0x00, 0x00, 0x20}); - send_seq (c, {0x2d, 0x01}); - send_seq (c, {0x18, 0x00}); - send_seq (c, {0x1b, 0x0d, 0x86, 0x51, 0xd2, 0x35, 0xa4, 0x92, 0xa5}); - send_seq (c, {0x1b, 0xb5, 0x25, 0x65}); - send_seq (c, {0x1d, 0x00}); - send_seq (c, {0x0f, 0x00, 0x29, 0x56, 0xb0, 0x00, 0xb6}); - send_seq (c, {0x20, 0x00}); - send_seq (c, {0x1e, 0x09, 0x02, 0x5b, 0x6c, 0x00, 0x4b, 0x81, 0x56}); - send_seq (c, {0x1e, 0x46, 0x69, 0x0b}); - send_seq (c, {0x22, 0x32}); - send_seq (c, {0x23, 0x0a}); - send_seq (c, {0x25, 0x00, 0x09, 0x90, 0x09, 0x06, 0x64, 0x02, 0x41}); - send_seq (c, {0x26, 0xcc}); - send_seq (c, {0x29, 0x40}); - send_seq (c, {0x21, 0x03}); - send_seq (c, {0x00, 0x8c}); - send_seq (c, {0x00, 0x00, 0x00, 0x00}); -//#else +#if 1 char *name; + rc = load_firmware(c,firmware_INIT1); + if (t->std & V4L2_STD_MN) name=firmware_MN; else -- cgit v1.2.3 From a6fa3993d483af17447492726b0f670dd5f14e2b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 18 Jul 2007 23:14:25 -0300 Subject: Some cleanups at tuner-xc2028 driver From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tm6000/tm6000-video.c | 2 linux/drivers/media/video/tuner-xc2028.c | 54 ++++--------------------------- 1 file changed, 7 insertions(+), 47 deletions(-) --- linux/drivers/media/video/tuner-xc2028.c | 54 +++++--------------------------- 1 file changed, 7 insertions(+), 47 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c index a387f03d4..722ab00be 100644 --- a/linux/drivers/media/video/tuner-xc2028.c +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -267,16 +267,6 @@ static int check_firmware(struct i2c_client *c, enum tuner_mode new_mode, return 0; } -#if 0 - /* Reset GPIO 1 */ - if (t->tuner_callback) { - rc = t->tuner_callback( c->adapter->algo_data, - XC2028_TUNER_RESET, 0); - if (rc<0) - return; - } - msleep(10); -#endif rc = load_firmware(c,firmware_INIT1); if (t->std & V4L2_STD_MN) @@ -336,37 +326,13 @@ static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */, struct tuner *t = i2c_get_clientdata(c); u32 div, offset = 0; -#if 0 +#if 1 /* HACK: It seems that specific firmware need to be reloaded when freq is changed */ struct xc2028_data *xc2028 = t->priv; xc2028->firm_type=0; -#endif - printk("xc3028: should set frequency %d kHz)\n", freq / 1000); - - if (check_firmware(c, new_mode, bandwidth)<0) - return; - if(new_mode == T_DIGITAL_TV) { - switch(bandwidth) { - case BANDWIDTH_8_MHZ: - offset = 2750000; - break; - - case BANDWIDTH_7_MHZ: - offset = 2750000; - break; - - case BANDWIDTH_6_MHZ: - default: - printk(KERN_ERR "xc2028: bandwidth not implemented!\n"); - } - } - - div = (freq - offset + DIV/2)/DIV; - -#if 1 /* Reset GPIO 1 */ if (t->tuner_callback) { rc = t->tuner_callback( c->adapter->algo_data, @@ -376,19 +342,16 @@ static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */, } msleep(10); #endif + printk("xc3028: should set frequency %d kHz)\n", freq / 1000); -#if 1 - char *name; + if (check_firmware(c, new_mode, bandwidth)<0) + return; - rc = load_firmware(c,firmware_INIT1); + if(new_mode == T_DIGITAL_TV) + offset = 2750000; - if (t->std & V4L2_STD_MN) - name=firmware_MN; - else - name=firmware_DK; + div = (freq - offset + DIV/2)/DIV; - rc = load_firmware(c,name); -#endif /* CMD= Set frequency */ send_seq(c, {0x00, 0x02, 0x00, 0x00}); if (t->tuner_callback) { @@ -399,8 +362,6 @@ static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */, } msleep(10); -// send_seq(c, {0x00, 0x00, 0x10, 0xd0, 0x00}); -// msleep(100); buf[0]= 0xff & (div>>24); buf[1]= 0xff & (div>>16); @@ -416,7 +377,6 @@ static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */, printk("divider= %02x %02x %02x %02x (freq=%d.%02d)\n", buf[1],buf[2],buf[3],buf[4], freq / 16, freq % 16 * 100 / 16); -// printk("signal=%d\n",xc2028_signal(c)); } #if 0 -- cgit v1.2.3 From 65de801c051f783e016e022cba03311ba64c524e Mon Sep 17 00:00:00 2001 From: Michel Ludwig Date: Fri, 27 Jul 2007 08:24:39 -0300 Subject: Make the naming of the DTV firmware files more consistent. From: Michel Ludwig Signed-off-by: Michel Ludwig Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-xc2028.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) --- linux/drivers/media/video/tuner-xc2028.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c index 722ab00be..153d023a5 100644 --- a/linux/drivers/media/video/tuner-xc2028.c +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -36,8 +36,8 @@ static const char *firmware_INIT1 = "tm_xc3028_68M_MTS_init1.fw"; /* Standard-specific firmwares */ static const char *firmware_6M = "tm_xc3028_DTV_6M.fw"; -static const char *firmware_7M = "tm_xc3028_7M.fw"; -static const char *firmware_8M = "tm_xc3028_8M.fw"; +static const char *firmware_7M = "tm_xc3028_DTV_7M.fw"; +static const char *firmware_8M = "tm_xc3028_DTV_8M.fw"; static const char *firmware_B = "tm_xc3028_B_PAL.fw"; static const char *firmware_DK = "tm_xc3028_DK_PAL_MTS.fw"; static const char *firmware_MN = "tm_xc3028_MN_BTSC.fw"; -- cgit v1.2.3 From 63c63d931c469cf4cbda715ad4bc4a92783ce84b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Sep 2007 18:27:03 -0300 Subject: Avoid having two tuner commands happening at the same time From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-xc2028.c | 60 ++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 13 deletions(-) --- linux/drivers/media/video/tuner-xc2028.c | 60 +++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c index 153d023a5..e55fa5c25 100644 --- a/linux/drivers/media/video/tuner-xc2028.c +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -9,10 +9,15 @@ #include #include #include -#include "compat.h" #include #include #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) +#include +#else +#include +#endif +#include "compat.h" #include "tuner-driver.h" #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "i2c-compat.h" @@ -51,6 +56,12 @@ struct xc2028_data { were loaded? */ enum tuner_mode mode; struct i2c_client *i2c_client; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) + struct mutex lock; +#else + struct semaphore lock; +#endif }; #define i2c_send(rc,c,buf,size) \ @@ -298,20 +309,28 @@ static int check_firmware(struct i2c_client *c, enum tuner_mode new_mode, static int xc2028_signal(struct i2c_client *c) { - int lock, signal; + struct tuner *t = i2c_get_clientdata(c); + struct xc2028_data *xc2028 = t->priv; + int frq_lock, signal=0; + + mutex_lock(&xc2028->lock); printk(KERN_INFO "xc2028: %s called\n", __FUNCTION__); - lock = xc2028_get_reg(c, 0x2); - if (lock<=0) - return lock; + frq_lock = xc2028_get_reg(c, 0x2); + if (frq_lock<=0) + goto ret; /* Frequency is locked. Return signal quality */ signal = xc2028_get_reg(c, 0x40); - if(signal<=0) - return lock; + if(signal<=0) { + signal=frq_lock; + } + +ret: + mutex_unlock(&xc2028->lock); return signal; } @@ -331,6 +350,8 @@ static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */, when freq is changed */ struct xc2028_data *xc2028 = t->priv; + mutex_lock(&xc2028->lock); + xc2028->firm_type=0; /* Reset GPIO 1 */ @@ -338,14 +359,14 @@ static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */, rc = t->tuner_callback( c->adapter->algo_data, XC2028_TUNER_RESET, 0); if (rc<0) - return; + goto ret; } msleep(10); #endif printk("xc3028: should set frequency %d kHz)\n", freq / 1000); if (check_firmware(c, new_mode, bandwidth)<0) - return; + goto ret; if(new_mode == T_DIGITAL_TV) offset = 2750000; @@ -358,7 +379,7 @@ static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */, rc = t->tuner_callback( c->adapter->algo_data, XC2028_RESET_CLK, 1); if (rc<0) - return; + goto ret; } msleep(10); @@ -371,23 +392,32 @@ static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */, i2c_send(rc, c, buf, sizeof(buf)); if (rc<0) - return; + goto ret; msleep(100); printk("divider= %02x %02x %02x %02x (freq=%d.%02d)\n", buf[1],buf[2],buf[3],buf[4], freq / 16, freq % 16 * 100 / 16); + +ret: + mutex_unlock(&xc2028->lock); } #if 0 static int xc2028_stereo(struct i2c_client *c) { unsigned char buffer[5]; - int rc; + int rc=0; struct tuner *t = i2c_get_clientdata(c); + struct xc2028_data *xc2028 = t->priv; + mutex_lock(&xc2028->lock); if (check_firmware(c)<0) - return 0; + goto ret; + +ret: + mutex_unlock(&xc2028->lock); + return ret; } #endif @@ -442,6 +472,8 @@ int xc2028_tuner_init(struct i2c_client *c) xc2028->need_load_generic=1; xc2028->mode = T_UNINITIALIZED; + mutex_init(&xc2028->lock); + /* FIXME: Check where t->priv will be freed */ if (version<0) @@ -524,5 +556,7 @@ int xc2028_attach(struct i2c_client *c, struct dvb_frontend *fe) return 0; } + + EXPORT_SYMBOL(xc2028_attach); -- cgit v1.2.3 From a1bf9e7b7282eca1a559270b1e3d39df743c52b3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 23 Oct 2007 16:24:06 -0200 Subject: Convert tuner-xc2028 driver to the newer hybrid approach From: Mauro Carvalho Chehab This changeset converts tuner-xc2028 to the newer hybrid approach. It also prevents creating twice the xc3028 private struct by both DVB and V4L parts. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/Kconfig | 8 linux/drivers/media/video/Kconfig | 12 linux/drivers/media/video/Makefile | 5 linux/drivers/media/video/tuner-core.c | 12 linux/drivers/media/video/tuner-driver.h | 2 linux/drivers/media/video/tuner-xc2028.c | 424 ++++++++++++++----------------- linux/drivers/media/video/tuner-xc2028.h | 24 + 7 files changed, 248 insertions(+), 239 deletions(-) --- linux/drivers/media/Kconfig | 8 + linux/drivers/media/video/Kconfig | 12 - linux/drivers/media/video/Makefile | 5 +- linux/drivers/media/video/tuner-core.c | 12 +- linux/drivers/media/video/tuner-driver.h | 2 - linux/drivers/media/video/tuner-xc2028.c | 424 +++++++++++++++---------------- linux/drivers/media/video/tuner-xc2028.h | 24 +- 7 files changed, 248 insertions(+), 239 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/Kconfig b/linux/drivers/media/Kconfig index dd9bd4310..ee778ee71 100644 --- a/linux/drivers/media/Kconfig +++ b/linux/drivers/media/Kconfig @@ -69,6 +69,7 @@ source "drivers/media/common/Kconfig" config VIDEO_TUNER tristate depends on I2C + select TUNER_XC2028 if !VIDEO_TUNER_CUSTOMIZE select TUNER_MT20XX if !VIDEO_TUNER_CUSTOMIZE select TUNER_TDA8290 if !VIDEO_TUNER_CUSTOMIZE select TUNER_TEA5761 if !VIDEO_TUNER_CUSTOMIZE @@ -89,6 +90,13 @@ menuconfig VIDEO_TUNER_CUSTOMIZE if VIDEO_TUNER_CUSTOMIZE +config TUNER_XC2028 + tristate "XCeive xc2028/xc3028 tuners" + depends on I2C + default m if VIDEO_TUNER_CUSTOMIZE + help + Say Y here to include support for the xc2028/xc3028 tuners. + config TUNER_MT20XX tristate "Microtune 2032 / 2050 tuners" depends on I2C diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 546c9c284..20f7c57bb 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -505,18 +505,6 @@ config TUNER_3036 Say Y here to include support for Philips SAB3036 compatible tuners. If in doubt, say N. -config TUNER_XC2028 - tristate "Xceive xc2028 support for tm5600/tm6000 driver" - depends on I2C - select VIDEO_TUNER - help - Say Y here to include support for Xceive xc2028 tuner. This is - required on a few tm5600/tm6000 designs. You should notice - that this module currently works only with the special - firmware versions used on those Trident chips. - - If in doubt, say N. - config VIDEO_VINO tristate "SGI Vino Video For Linux (EXPERIMENTAL)" depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2 diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 1fd775e0a..08ac197cc 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -6,10 +6,6 @@ zr36067-objs := zoran_procfs.o zoran_device.o \ zoran_driver.o zoran_card.o tuner-objs := tuner-core.o tuner-types.o tda9887.o -ifneq ($(CONFIG_TUNER_XC2028),) - tuner-objs += tuner-xc2028.o -endif - msp3400-objs := msp3400-driver.o msp3400-kthreads.o obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o \ @@ -85,6 +81,7 @@ obj-$(CONFIG_TUNER_3036) += tuner-3036.o obj-$(CONFIG_VIDEO_TUNER) += tuner.o +obj-$(CONFIG_TUNER_XC2028) += tuner-xc2028.o obj-$(CONFIG_TUNER_SIMPLE) += tuner-simple.o obj-$(CONFIG_TUNER_MT20XX) += mt20xx.o obj-$(CONFIG_TUNER_TDA8290) += tda8290.o diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 45354d230..3c8ffe423 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -28,6 +28,7 @@ #include "tda8290.h" #include "tea5761.h" #include "tea5767.h" +#include "tuner-xc2028.h" #include "tuner-simple.h" #define UNSET (-1U) @@ -352,8 +353,17 @@ static void set_type(struct i2c_client *c, unsigned int type, attach_simple_tuner(t); break; case TUNER_XC2028: - xc2028_tuner_init(c); + { + int rc=xc2028_attach(&t->fe, t->i2c.adapter, t->i2c.addr, + &c->dev, c->adapter->algo_data, + t->tuner_callback); + if (rc<0) { + t->type = TUNER_ABSENT; + t->mode_mask = T_UNINITIALIZED; + return; + } break; + } case TUNER_TDA9887: tda9887_tuner_init(t); break; diff --git a/linux/drivers/media/video/tuner-driver.h b/linux/drivers/media/video/tuner-driver.h index b2e376ef3..9da949b25 100644 --- a/linux/drivers/media/video/tuner-driver.h +++ b/linux/drivers/media/video/tuner-driver.h @@ -70,8 +70,6 @@ struct tuner { struct tuner_operations ops; }; -extern int xc2028_tuner_init(struct i2c_client *c); - /* ------------------------------------------------------------------------ */ extern int tda9887_tuner_init(struct tuner *t); diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c index e55fa5c25..a94796e55 100644 --- a/linux/drivers/media/video/tuner-xc2028.c +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -18,7 +18,7 @@ #include #endif #include "compat.h" -#include "tuner-driver.h" +#include "tuner-i2c.h" #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "i2c-compat.h" #endif @@ -27,10 +27,9 @@ #include #include "dvb_frontend.h" -/* digital TV standards */ -#define V4L2_STD_DTV_6MHZ ((v4l2_std_id)0x04000000) -#define V4L2_STD_DTV_7MHZ ((v4l2_std_id)0x08000000) -#define V4L2_STD_DTV_8MHZ ((v4l2_std_id)0x10000000) +#define PREFIX "xc2028 " + +static LIST_HEAD(xc2028_list); /* Firmwares used on tm5600/tm6000 + xc2028/xc3028 */ @@ -48,6 +47,15 @@ static const char *firmware_DK = "tm_xc3028_DK_PAL_MTS.fw"; static const char *firmware_MN = "tm_xc3028_MN_BTSC.fw"; struct xc2028_data { + struct list_head xc2028_list; + struct tuner_i2c_props i2c_props; + int (*tuner_callback) (void *dev, + int command, int arg); + struct device *dev; + void *video_dev; + int count; + u32 frequency; + v4l2_std_id firm_type; /* video stds supported by current firmware */ fe_bandwidth_t bandwidth; /* Firmware bandwidth: @@ -56,73 +64,68 @@ struct xc2028_data { were loaded? */ enum tuner_mode mode; struct i2c_client *i2c_client; - + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) - struct mutex lock; + struct mutex lock; #else - struct semaphore lock; + struct semaphore lock; #endif }; -#define i2c_send(rc,c,buf,size) \ -if (size != (rc = i2c_master_send(c, buf, size))) \ - tuner_warn("i2c output error: rc = %d (should be %d)\n", \ +#define i2c_send(rc, priv, buf, size) \ +if (size != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buf, size))) \ + tuner_info("i2c output error: rc = %d (should be %d)\n", \ rc, (int)size); -#define i2c_rcv(rc,c,buf,size) \ -if (size != (rc = i2c_master_recv(c, buf, size))) \ - tuner_warn("i2c input error: rc = %d (should be %d)\n", \ +#define i2c_rcv(rc, priv, buf, size) \ +if (size != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buf, size))) \ + tuner_info("i2c input error: rc = %d (should be %d)\n", \ rc, (int)size); -#define send_seq(c, data...) \ +#define send_seq(priv, data...) \ { int rc; \ - const static u8 _val[] = data; \ + static u8 _val[] = data; \ if (sizeof(_val) != \ - (rc = i2c_master_send \ - (c, _val, sizeof(_val)))) { \ - printk(KERN_ERR "Error on line %d: %d\n",__LINE__,rc); \ - return; \ + (rc = tuner_i2c_xfer_send (&priv->i2c_props, \ + _val, sizeof(_val)))) { \ + tuner_info("Error on line %d: %d\n",__LINE__,rc); \ + return -EINVAL; \ } \ msleep (10); \ } -static int xc2028_get_reg(struct i2c_client *c, u16 reg) +static int xc2028_get_reg(struct xc2028_data *priv, u16 reg) { int rc; unsigned char buf[1]; - struct tuner *t = i2c_get_clientdata(c); + + tuner_info("%s called\n", __FUNCTION__); buf[0]= reg; - i2c_send(rc, c, buf, sizeof(buf)); + i2c_send(rc, priv, buf, sizeof(buf)); if (rc<0) return rc; -#if 0 - if (t->tuner_callback) { - rc = t->tuner_callback( c->adapter->algo_data, - XC2028_RESET_CLK, 0); - if (rc<0) - return rc; - } -#endif - i2c_rcv(rc, c, buf, 2); + i2c_rcv(rc, priv, buf, 2); if (rc<0) return rc; return (buf[1])|(buf[0]<<8); } -static int load_firmware (struct i2c_client *c, const char *name) +static int load_firmware (struct dvb_frontend *fe, const char *name) { + struct xc2028_data *priv = fe->tuner_priv; const struct firmware *fw=NULL; - struct tuner *t = i2c_get_clientdata(c); unsigned char *p, *endp; int len=0, rc=0; static const char firmware_ver[] = "tm6000/xcv v1"; - tuner_info("xc2028: Loading firmware %s\n", name); - rc = request_firmware(&fw, name, &c->dev); + tuner_info("%s called\n", __FUNCTION__); + + tuner_info("Loading firmware %s\n", name); + rc = request_firmware(&fw, name, priv->dev); if (rc < 0) { if (rc==-ENOENT) tuner_info("Error: firmware %s not found.\n", name); @@ -158,7 +161,7 @@ static int load_firmware (struct i2c_client *c, const char *name) while(ptuner_callback(c->adapter->algo_data, + rc = priv->tuner_callback(priv->video_dev, XC2028_TUNER_RESET, (*p)&0x7f); if (rc<0) { tuner_info("Error at RESET code %d\n", @@ -182,7 +185,7 @@ static int load_firmware (struct i2c_client *c, const char *name) goto err; } - i2c_send(rc, c, p, len); + i2c_send(rc, priv, p, len); if (rc<0) goto err; p+=len; @@ -199,173 +202,175 @@ err: return rc; } -static int check_firmware(struct i2c_client *c, enum tuner_mode new_mode, +static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode, + v4l2_std_id std, fe_bandwidth_t bandwidth) { + struct xc2028_data *priv = fe->tuner_priv; int rc, version; - struct tuner *t = i2c_get_clientdata(c); - struct xc2028_data *xc2028 = t->priv; const char *name; int change_digital_bandwidth; - if (!t->tuner_callback) { - printk(KERN_ERR "xc2028: need tuner_callback to load firmware\n"); - return -EINVAL; - } + tuner_info("%s called\n", __FUNCTION__); - printk(KERN_INFO "xc2028: I am in mode %u and I should switch to mode %i\n", - xc2028->mode, new_mode); + tuner_info( "I am in mode %u and I should switch to mode %i\n", + priv->mode, new_mode); /* first of all, determine whether we have switched the mode */ - if(new_mode != xc2028->mode) { - xc2028->mode = new_mode; - xc2028->need_load_generic = 1; + if(new_mode != priv->mode) { + priv->mode = new_mode; + priv->need_load_generic = 1; } - change_digital_bandwidth = (xc2028->mode == T_DIGITAL_TV - && bandwidth != xc2028->bandwidth) ? 1 : 0; - tuner_info("xc2028: old bandwidth %u, new bandwidth %u\n", xc2028->bandwidth, + change_digital_bandwidth = (priv->mode == T_DIGITAL_TV + && bandwidth != priv->bandwidth) ? 1 : 0; + tuner_info("old bandwidth %u, new bandwidth %u\n", priv->bandwidth, bandwidth); - if (xc2028->need_load_generic) { - if (xc2028->bandwidth==8) + if (priv->need_load_generic) { + if (priv->bandwidth==8) name = firmware_8MHZ_INIT0; else name = firmware_INIT0; /* Reset is needed before loading firmware */ - rc = t->tuner_callback(c->adapter->algo_data, - XC2028_TUNER_RESET, 0); + rc = priv->tuner_callback(priv->video_dev, + XC2028_TUNER_RESET, 0); if (rc<0) return rc; - rc = load_firmware(c,name); + rc = load_firmware(fe,name); if (rc<0) return rc; - xc2028->need_load_generic=0; - xc2028->firm_type=0; - if(xc2028->mode == T_DIGITAL_TV) { + priv->need_load_generic=0; + priv->firm_type=0; + if(priv->mode == T_DIGITAL_TV) { change_digital_bandwidth=1; } } - tuner_info("xc2028: I should change bandwidth %u\n", + tuner_info("I should change bandwidth %u\n", change_digital_bandwidth); + /* FIXME: t->std makes no sense here */ if (change_digital_bandwidth) { switch(bandwidth) { case BANDWIDTH_8_MHZ: - t->std = V4L2_STD_DTV_8MHZ; + std = V4L2_STD_DTV_8MHZ; break; case BANDWIDTH_7_MHZ: - t->std = V4L2_STD_DTV_7MHZ; + std = V4L2_STD_DTV_7MHZ; break; case BANDWIDTH_6_MHZ: - t->std = V4L2_STD_DTV_6MHZ; + std = V4L2_STD_DTV_6MHZ; break; default: tuner_info("error: bandwidth not supported.\n"); }; - xc2028->bandwidth = bandwidth; + priv->bandwidth = bandwidth; } - if (xc2028->firm_type & t->std) { + if (priv->firm_type & std) { tuner_info("xc3028: no need to load a std-specific firmware.\n"); return 0; } - rc = load_firmware(c,firmware_INIT1); + rc = load_firmware(fe,firmware_INIT1); - if (t->std & V4L2_STD_MN) + if (std & V4L2_STD_MN) name=firmware_MN; - else if (t->std & V4L2_STD_DTV_6MHZ) + else if (std & V4L2_STD_DTV_6MHZ) name=firmware_6M; - else if (t->std & V4L2_STD_DTV_7MHZ) + else if (std & V4L2_STD_DTV_7MHZ) name=firmware_7M; - else if (t->std & V4L2_STD_DTV_8MHZ) + else if (std & V4L2_STD_DTV_8MHZ) name=firmware_8M; - else if (t->std & V4L2_STD_PAL_B) + else if (std & V4L2_STD_PAL_B) name=firmware_B; else name=firmware_DK; - tuner_info("xc2028: loading firmware named %s.\n", name); - rc = load_firmware(c, name); + tuner_info("loading firmware named %s.\n", name); + rc = load_firmware(fe, name); if (rc<0) return rc; - version = xc2028_get_reg(c, 0x4); + version = xc2028_get_reg(priv, 0x4); tuner_info("Firmware version is %d.%d\n", (version>>4)&0x0f,(version)&0x0f); - xc2028->firm_type=t->std; + priv->firm_type=std; return 0; } -static int xc2028_signal(struct i2c_client *c) +static int xc2028_signal(struct dvb_frontend *fe, u16 *strength) { - struct tuner *t = i2c_get_clientdata(c); - struct xc2028_data *xc2028 = t->priv; + struct xc2028_data *priv = fe->tuner_priv; int frq_lock, signal=0; - mutex_lock(&xc2028->lock); + tuner_info("%s called\n", __FUNCTION__); - printk(KERN_INFO "xc2028: %s called\n", __FUNCTION__); + mutex_lock(&priv->lock); - frq_lock = xc2028_get_reg(c, 0x2); + *strength = 0; + + frq_lock = xc2028_get_reg(priv, 0x2); if (frq_lock<=0) goto ret; /* Frequency is locked. Return signal quality */ - signal = xc2028_get_reg(c, 0x40); + signal = xc2028_get_reg(priv, 0x40); if(signal<=0) { signal=frq_lock; } ret: - mutex_unlock(&xc2028->lock); + mutex_unlock(&priv->lock); + + *strength = signal; - return signal; + return 0; } #define DIV 15625 -static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */, - enum tuner_mode new_mode, fe_bandwidth_t bandwidth) +static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */, + enum tuner_mode new_mode, + v4l2_std_id std, + fe_bandwidth_t bandwidth) { - int rc; + struct xc2028_data *priv = fe->tuner_priv; + int rc=-EINVAL; unsigned char buf[5]; - struct tuner *t = i2c_get_clientdata(c); u32 div, offset = 0; + tuner_info("%s called\n", __FUNCTION__); + #if 1 /* HACK: It seems that specific firmware need to be reloaded when freq is changed */ - struct xc2028_data *xc2028 = t->priv; - mutex_lock(&xc2028->lock); + mutex_lock(&priv->lock); - xc2028->firm_type=0; + priv->firm_type=0; /* Reset GPIO 1 */ - if (t->tuner_callback) { - rc = t->tuner_callback( c->adapter->algo_data, - XC2028_TUNER_RESET, 0); - if (rc<0) - goto ret; - } + rc = priv->tuner_callback(priv->video_dev, XC2028_TUNER_RESET, 0); + if (rc<0) + goto ret; + msleep(10); #endif - printk("xc3028: should set frequency %d kHz)\n", freq / 1000); + tuner_info("should set frequency %d kHz)\n", freq / 1000); - if (check_firmware(c, new_mode, bandwidth)<0) + if (check_firmware(fe, new_mode, std, bandwidth)<0) goto ret; if(new_mode == T_DIGITAL_TV) @@ -374,13 +379,10 @@ static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */, div = (freq - offset + DIV/2)/DIV; /* CMD= Set frequency */ - send_seq(c, {0x00, 0x02, 0x00, 0x00}); - if (t->tuner_callback) { - rc = t->tuner_callback( c->adapter->algo_data, - XC2028_RESET_CLK, 1); - if (rc<0) - goto ret; - } + send_seq(priv, {0x00, 0x02, 0x00, 0x00}); + rc = priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1); + if (rc<0) + goto ret; msleep(10); @@ -390,139 +392,82 @@ static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */, buf[3]= 0xff & (div); buf[4]= 0; - i2c_send(rc, c, buf, sizeof(buf)); + i2c_send(rc, priv, buf, sizeof(buf)); if (rc<0) goto ret; msleep(100); + priv->frequency=freq; + printk("divider= %02x %02x %02x %02x (freq=%d.%02d)\n", buf[1],buf[2],buf[3],buf[4], - freq / 16, freq % 16 * 100 / 16); - -ret: - mutex_unlock(&xc2028->lock); -} + freq / 1000000, (freq%1000000)/10000); -#if 0 -static int xc2028_stereo(struct i2c_client *c) -{ - unsigned char buffer[5]; - int rc=0; - struct tuner *t = i2c_get_clientdata(c); - struct xc2028_data *xc2028 = t->priv; - - mutex_lock(&xc2028->lock); - if (check_firmware(c)<0) - goto ret; + rc=0; ret: - mutex_unlock(&xc2028->lock); - return ret; -} - -#endif - -static void set_tv_freq(struct i2c_client *c, unsigned int freq) -{ - printk(KERN_INFO "xc2028: %s called\n", __FUNCTION__); + mutex_unlock(&priv->lock); - generic_set_tv_freq(c, freq * 62500l, T_ANALOG_TV, - BANDWIDTH_8_MHZ /* unimportant */); + return rc; } -static void xc2028_release(struct i2c_client *c) +static int xc2028_set_tv_freq(struct dvb_frontend *fe, + struct analog_parameters *p) { - struct tuner *t = i2c_get_clientdata(c); - - kfree(t->priv); - t->priv = NULL; -} - -static struct tuner_operations tea5767_tuner_ops = { - .set_tv_freq = set_tv_freq, - .has_signal = xc2028_signal, - .release = xc2028_release, -// .is_stereo = xc2028_stereo, -}; + struct xc2028_data *priv = fe->tuner_priv; + tuner_info("%s called\n", __FUNCTION__); -static int init=0; + return generic_set_tv_freq(fe, 62500l*p->frequency, T_ANALOG_TV, + p->std, + BANDWIDTH_8_MHZ /* NOT USED */); +} -int xc2028_tuner_init(struct i2c_client *c) +static int xc2028_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) { - struct tuner *t = i2c_get_clientdata(c); - int version = xc2028_get_reg(c, 0x4); - int prd_id = xc2028_get_reg(c, 0x8); - struct xc2028_data *xc2028; + struct xc2028_data *priv = fe->tuner_priv; - tuner_info("Xcv2028/3028 init called!\n"); + tuner_info("%s called\n", __FUNCTION__); - if (init) { - printk (KERN_ERR "Module already initialized!\n"); - return 0; + /* FIXME: Only OFDM implemented */ + if (fe->ops.info.type != FE_OFDM) { + tuner_info ("DTV type not implemented.\n"); + return -EINVAL; } - init++; - - xc2028 = kzalloc(sizeof(*xc2028), GFP_KERNEL); - if (!xc2028) - return -ENOMEM; - t->priv = xc2028; - - xc2028->bandwidth=BANDWIDTH_6_MHZ; - xc2028->need_load_generic=1; - xc2028->mode = T_UNINITIALIZED; - - mutex_init(&xc2028->lock); - - /* FIXME: Check where t->priv will be freed */ - - if (version<0) - version=0; - - if (prd_id<0) - prd_id=0; - strlcpy(c->name, "xc2028", sizeof(c->name)); - tuner_info("type set to %d (%s, hw ver=%d.%d, fw ver=%d.%d, id=0x%04x)\n", - t->type, c->name, - (version>>12)&0x0f,(version>>8)&0x0f, - (version>>4)&0x0f,(version)&0x0f, prd_id); + return generic_set_tv_freq(fe, p->frequency, T_DIGITAL_TV, + 0, /* NOT USED */ + p->u.ofdm.bandwidth); - memcpy(&t->ops, &tea5767_tuner_ops, sizeof(struct tuner_operations)); - - return 0; } -static int xc3028_set_params(struct dvb_frontend *fe, - struct dvb_frontend_parameters *p) +static int xc2028_dvb_release(struct dvb_frontend *fe) { - struct i2c_client *c = fe->tuner_priv; + struct xc2028_data *priv = fe->tuner_priv; - printk(KERN_INFO "xc2028: %s called\n", __FUNCTION__); + tuner_info("%s called\n", __FUNCTION__); - generic_set_tv_freq(c, p->frequency, T_DIGITAL_TV, - p->u.ofdm.bandwidth); + priv->count--; + + if (!priv->count) + kfree (priv); return 0; } -static int xc3028_dvb_release(struct dvb_frontend *fe) +static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency) { - printk(KERN_INFO "xc2028: %s called\n", __FUNCTION__); - - fe->tuner_priv = NULL; + struct xc2028_data *priv = fe->tuner_priv; - return 0; -} + tuner_info("%s called\n", __FUNCTION__); -static int xc3028_dvb_init(struct dvb_frontend *fe) -{ - printk(KERN_INFO "xc2028: %s called\n", __FUNCTION__); + *frequency = priv->frequency; return 0; } -static const struct dvb_tuner_ops xc3028_dvb_tuner_ops = { +static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = { .info = { .name = "Xceive XC3028", .frequency_min = 42000000, @@ -530,33 +475,74 @@ static const struct dvb_tuner_ops xc3028_dvb_tuner_ops = { .frequency_step = 50000, }, - .release = xc3028_dvb_release, - .init = xc3028_dvb_init, + .set_analog_params = xc2028_set_tv_freq, + .release = xc2028_dvb_release, + .get_frequency = xc2028_get_frequency, + .get_rf_strength = xc2028_signal, + .set_params = xc2028_set_params, // int (*sleep)(struct dvb_frontend *fe); - - /** This is for simple PLLs - set all parameters in one go. */ - .set_params = xc3028_set_params, - - /** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */ -// int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len); - -// int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency); // int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth); - // int (*get_status)(struct dvb_frontend *fe, u32 *status); }; -int xc2028_attach(struct i2c_client *c, struct dvb_frontend *fe) +int xc2028_attach(struct dvb_frontend *fe, struct i2c_adapter* i2c_adap, + u8 i2c_addr, struct device *dev, void *video_dev, + int (*tuner_callback) (void *dev, int command,int arg)) { - fe->tuner_priv = c; + struct xc2028_data *priv; - memcpy(&fe->ops.tuner_ops, &xc3028_dvb_tuner_ops, sizeof(fe->ops.tuner_ops)); + printk( KERN_INFO PREFIX "Xcv2028/3028 init called!\n"); - return 0; -} + if (NULL == dev) + return -ENODEV; + + if (NULL == video_dev) + return -ENODEV; + + if (!tuner_callback) { + printk( KERN_ERR PREFIX "No tuner callback!\n"); + return -EINVAL; + } + + list_for_each_entry(priv, &xc2028_list, xc2028_list) { + if (priv->dev == dev) { + dev = NULL; + priv->count++; + } + } + + if (dev) { + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + + fe->tuner_priv = priv; + + priv->bandwidth=BANDWIDTH_6_MHZ; + priv->need_load_generic=1; + priv->mode = T_UNINITIALIZED; + priv->i2c_props.addr = i2c_addr; + priv->i2c_props.adap = i2c_adap; + priv->dev = dev; + priv->video_dev = video_dev; + priv->tuner_callback = tuner_callback; + + mutex_init(&priv->lock); + list_add_tail(&priv->xc2028_list,&xc2028_list); + } + + memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops, + sizeof(xc2028_dvb_tuner_ops)); + + tuner_info("type set to %s\n", "XCeive xc2028/xc3028 tuner"); + return 0; +} EXPORT_SYMBOL(xc2028_attach); +MODULE_DESCRIPTION("Xceive xc2028/xc3028 tuner driver"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/video/tuner-xc2028.h b/linux/drivers/media/video/tuner-xc2028.h index 34ff4cba1..d5a18a37d 100644 --- a/linux/drivers/media/video/tuner-xc2028.h +++ b/linux/drivers/media/video/tuner-xc2028.h @@ -4,6 +4,11 @@ * This code is placed under the terms of the GNU General Public License v2 */ +#ifndef __TUNER_XC2028_H__ +#define __TUNER_XC2028_H__ + +#include "dvb_frontend.h" + /* xc2028 commands for callback */ #define XC2028_TUNER_RESET 0 #define XC2028_RESET_CLK 1 @@ -11,4 +16,21 @@ struct dvb_frontend; struct i2c_client; -int xc2028_attach(struct i2c_client *c, struct dvb_frontend *fe); +#if defined(CONFIG_TUNER_XC2028) || (defined(CONFIG_TUNER_XC2028_MODULE) && defined(MODULE)) +int xc2028_attach(struct dvb_frontend *fe, struct i2c_adapter* i2c_adap, + u8 i2c_addr, struct device *dev, void *video_dev, + int (*tuner_callback) (void *dev, int command,int arg)); + +#else +static inline int xc2028_attach(struct dvb_frontend *fe, + struct i2c_adapter* i2c_adap, + u8 i2c_addr, struct device *dev, void *video_dev, + int (*tuner_callback) (void *dev, int command,int arg)) +{ + printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", + __FUNCTION__); + return -EINVAL; +} +#endif + +#endif /* __TUNER_XC2028_H__ */ -- cgit v1.2.3 From 3bca88b5f0fc7fcf0e988206f23a790ae73555ad Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 24 Oct 2007 10:22:08 -0200 Subject: Improve firmware format From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-xc2028-types.h | 99 +++++ linux/drivers/media/video/tuner-xc2028.c | 463 +++++++++++++++++++------ linux/drivers/media/video/tuner-xc2028.h | 15 3 files changed, 466 insertions(+), 111 deletions(-) --- linux/drivers/media/video/tuner-xc2028-types.h | 99 ++++++ linux/drivers/media/video/tuner-xc2028.c | 463 +++++++++++++++++++------ linux/drivers/media/video/tuner-xc2028.h | 15 +- 3 files changed, 466 insertions(+), 111 deletions(-) create mode 100644 linux/drivers/media/video/tuner-xc2028-types.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-xc2028-types.h b/linux/drivers/media/video/tuner-xc2028-types.h new file mode 100644 index 000000000..80b19eb1b --- /dev/null +++ b/linux/drivers/media/video/tuner-xc2028-types.h @@ -0,0 +1,99 @@ +/* tuner-xc2028_types + * + * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org) + * This code is placed under the terms of the GNU General Public License v2 + */ + +/* xc3028 firmware types */ + +/* BASE firmware should be loaded before any other firmware */ +#define BASE (1<<0) + +/* F8MHZ marks BASE firmwares for 8 MHz Bandwidth */ +#define F8MHZ (1<<1) + +/* Multichannel Television Sound (MTS) + Those firmwares are capable of using xc2038 DSP to decode audio and + produce a baseband audio output on some pins of the chip. + There are MTS firmwares for the most used video standards. It should be + required to use MTS firmwares, depending on the way audio is routed into + the bridge chip + */ +#define MTS (1<<2) + +/* FIXME: I have no idea what's the difference between + D2620 and D2633 firmwares + */ +#define D2620 (1<<3) +#define D2633 (1<<4) + +/* DTV firmwares for 6, 7 and 8 MHz + DTV6 - 6MHz - ATSC/DVB-C/DVB-T/ISDB-T/DOCSIS + DTV8 - 8MHz - DVB-C/DVB-T + */ +#define DTV6_ATSC (1<<5) +#define DTV6_QAM (1<<6) +#define DTV7 (1<<7) +#define DTV78 (1<<8) +#define DTV8 (1<<9) + +/* There's a FM | BASE firmware + FM specific firmware (std=0) */ +#define FM (1<<10) + +/* Applies only for FM firmware + Makes it use RF input 1 (pin #2) instead of input 2 (pin #4) + */ +#define INPUT1 (1<<11) + + +/* LCD firmwares exist only for MTS STD/MN (PAL or NTSC/M) + and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr) + There are variants both with and without NOGD + */ +#define LCD (1<<12) + +/* NOGD firmwares exist only for MTS STD/MN (PAL or NTSC/M) + and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr) + */ +#define NOGD (1<<13) + +/* Old firmwares were broken into init0 and init1 */ +#define INIT1 (1<<14) + +/* Newer types to be moved to videodev2.h */ + +#define V4L2_STD_SECAM_K3 (0x02000000) + +/* Audio types */ + +#define V4L2_STD_A2_A (1L<<32) +#define V4L2_STD_A2_B (1L<<33) +#define V4L2_STD_NICAM_A (1L<<34) +#define V4L2_STD_NICAM_B (1L<<35) +#define V4L2_STD_AM (1L<<36) +#define V4L2_STD_BTSC (1L<<37) +#define V4L2_STD__EIAJ (1L<<38) + +#define V4L2_STD_A2 (V4L2_STD_A2_A | V4L2_STD_A2_B) +#define V4L2_STD_NICAM (V4L2_STD_NICAM_A | V4L2_STD_NICAM_B) + +/* To preserve backward compatibilty, + (std & V4L2_STD_AUDIO) = 0 means that ALL audio stds are supported + */ + +#define V4L2_STD_AUDIO (V4L2_STD_A2 | \ + V4L2_STD_NICAM | \ + V4L2_STD_AM | \ + V4L2_STD_BTSC | \ + V4L2_STD_EIAJ) + +/* Used standards with audio restrictions */ + +#define V4L2_STD_PAL_BG_A2_A (V4L2_STD_PAL_BG | V4L2_STD_A2_A) +#define V4L2_STD_PAL_BG_A2_B (V4L2_STD_PAL_BG | V4L2_STD_A2_B) +#define V4L2_STD_PAL_BG_NICAM_A (V4L2_STD_PAL_BG | V4L2_STD_NICAM_A) +#define V4L2_STD_PAL_BG_NICAM_B (V4L2_STD_PAL_BG | V4L2_STD_NICAM_B) +#define V4L2_STD_PAL_DK_A2 (V4L2_STD_PAL_DK | V4L2_STD_A2) +#define V4L2_STD_PAL_DK_NICAM (V4L2_STD_PAL_DK | V4L2_STD_NICAM) +#define V4L2_STD_SECAM_L_NICAM (V4L2_STD_SECAM_L | V4L2_STD_NICAM) +#define V4L2_STD_SECAM_L_AM (V4L2_STD_SECAM_L | V4L2_STD_AM) diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c index a94796e55..9b6e7c006 100644 --- a/linux/drivers/media/video/tuner-xc2028.c +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -23,6 +23,7 @@ #include "i2c-compat.h" #endif #include "tuner-xc2028.h" +#include "tuner-xc2028-types.h" #include #include "dvb_frontend.h" @@ -30,21 +31,13 @@ #define PREFIX "xc2028 " static LIST_HEAD(xc2028_list); - -/* Firmwares used on tm5600/tm6000 + xc2028/xc3028 */ - -/* Generic firmwares */ -static const char *firmware_INIT0 = "tm_xc3028_MTS_init0.fw"; -static const char *firmware_8MHZ_INIT0 = "tm_xc3028_8M_MTS_init0.fw"; -static const char *firmware_INIT1 = "tm_xc3028_68M_MTS_init1.fw"; - -/* Standard-specific firmwares */ -static const char *firmware_6M = "tm_xc3028_DTV_6M.fw"; -static const char *firmware_7M = "tm_xc3028_DTV_7M.fw"; -static const char *firmware_8M = "tm_xc3028_DTV_8M.fw"; -static const char *firmware_B = "tm_xc3028_B_PAL.fw"; -static const char *firmware_DK = "tm_xc3028_DK_PAL_MTS.fw"; -static const char *firmware_MN = "tm_xc3028_MN_BTSC.fw"; +/* struct for storing firmware table */ +struct firmware_description { + unsigned int type; + v4l2_std_id id; + unsigned char *ptr; + unsigned int size; +}; struct xc2028_data { struct list_head xc2028_list; @@ -54,7 +47,14 @@ struct xc2028_data { struct device *dev; void *video_dev; int count; - u32 frequency; + __u32 frequency; + + struct firmware_description *firm; + int firm_size; + + __u16 version; + + struct xc2028_ctrl ctrl; v4l2_std_id firm_type; /* video stds supported by current firmware */ @@ -62,6 +62,9 @@ struct xc2028_data { 6M, 7M or 8M */ int need_load_generic; /* The generic firmware were loaded? */ + + int max_len; /* Max firmware chunk */ + enum tuner_mode mode; struct i2c_client *i2c_client; @@ -114,92 +117,263 @@ static int xc2028_get_reg(struct xc2028_data *priv, u16 reg) return (buf[1])|(buf[0]<<8); } -static int load_firmware (struct dvb_frontend *fe, const char *name) +static void free_firmware (struct xc2028_data *priv) { - struct xc2028_data *priv = fe->tuner_priv; + int i; + + if (!priv->firm) + return; + + for (i=0;ifirm_size;i++) { + if (priv->firm[i].ptr) + kfree(priv->firm[i].ptr); + } + kfree(priv->firm); + + priv->firm=NULL; + priv->need_load_generic = 1; +} + +static int load_all_firmwares (struct dvb_frontend *fe) +{ + struct xc2028_data *priv = fe->tuner_priv; const struct firmware *fw=NULL; unsigned char *p, *endp; - int len=0, rc=0; - static const char firmware_ver[] = "tm6000/xcv v1"; + int rc=0, n, n_array; + char name[33]; tuner_info("%s called\n", __FUNCTION__); - tuner_info("Loading firmware %s\n", name); - rc = request_firmware(&fw, name, priv->dev); + tuner_info("Loading firmware %s\n", priv->ctrl.fname); + rc = request_firmware(&fw, priv->ctrl.fname, priv->dev); if (rc < 0) { if (rc==-ENOENT) - tuner_info("Error: firmware %s not found.\n", name); + tuner_info("Error: firmware %s not found.\n", + priv->ctrl.fname); else - tuner_info("Error %d while requesting firmware %s \n", rc, name); + tuner_info("Error %d while requesting firmware %s \n", + rc, priv->ctrl.fname); return rc; } p=fw->data; endp=p+fw->size; - if(fw->size==0) { + if(fw->sizesizesize,(int)sizeof(firmware_ver)-1); - rc=-EINVAL; - goto err; + + memcpy(name,p,sizeof(name)-1); + name[sizeof(name)-1]=0; + p+=sizeof(name)-1; + + priv->version = le16_to_cpu(*(__u16 *)p); + p += 2; + + tuner_info("firmware: %s, ver %d.%d\n", name, + priv->version>>8, priv->version&0xff); + + if (p+2>endp) + goto corrupt; + + n_array = le16_to_cpu(*(__u16 *)p); + p += 2; + + tuner_info("there are %d firmwares at %s\n", n_array, priv->ctrl.fname); + + priv->firm=kzalloc(sizeof(*priv->firm)*n_array,GFP_KERNEL); + + if (!fw) { + tuner_info("Not enough memory for loading firmware.\n"); + rc=-ENOMEM; + goto done; } - if (memcmp(p,firmware_ver,sizeof(firmware_ver)-1)) { - /* Firmware is incorrect */ - tuner_info("Error: firmware is not for tm5600/6000 + Xcv2028/3028!\n"); - rc=-EINVAL; - goto err; + priv->firm_size = n_array; + n=-1; + while (p= n_array) { + tuner_info("Too much firmwares at the file\n"); + goto corrupt; + } + + /* Checks if there's enough bytes to read */ + if (p+sizeof(type)+sizeof(id)+sizeof(size)>endp) { + tuner_info("Lost firmware!\n"); + goto corrupt; + } + + type = le32_to_cpu(*(__u32 *)p); + p += sizeof(type); + + id = le64_to_cpu(*(v4l2_std_id *)p); + p += sizeof(id); + + size = le32_to_cpu(*(v4l2_std_id *)p); + p += sizeof(size); + + if ((!size)||(size+p>endp)) { + tuner_info("Firmware type %x, id %lx corrupt\n", + type, (unsigned long) id); + goto corrupt; + } + + priv->firm[n].ptr=kzalloc(size,GFP_KERNEL); + if (!priv->firm[n].ptr) { + tuner_info("Not enough memory.\n"); + rc=-ENOMEM; + goto err; + } + tuner_info("Loading firmware type %x, id %lx, size=%d.\n", + type, (unsigned long) id, size); + + memcpy(priv->firm[n].ptr, p, size); + priv->firm[n].type = type; + priv->firm[n].id = id; + priv->firm[n].size = size; + + p += size; + } + + if (n+1 != priv->firm_size) { + tuner_info("Firmware file is incomplete!\n"); + goto corrupt; } - p+=sizeof(firmware_ver)-1; - while(ptuner_priv; + int i, rc; + unsigned char *p, *endp, buf[priv->max_len]; + + tuner_info("%s called\n", __FUNCTION__); + + if (!priv->firm) { + printk (KERN_ERR PREFIX "Error! firmware not loaded\n"); + return -EINVAL; + } + + if ((type == 0) && (*id == 0)) + *id=V4L2_STD_PAL; + + /* Seek for exact match */ + for (i=0;ifirm_size;i++) { + if ( (type == priv->firm[i].type) && + (*id == priv->firm[i].id)) + goto found; + } + + /* Seek for generic video standard match */ + for (i=0;ifirm_size;i++) { + if ( (type == priv->firm[i].type) && (*id & priv->firm[i].id)) + goto found; + } + + /*FIXME: Would make sense to seek for type "hint" match ? */ + + tuner_info ("Can't find firmware for type=%x, id=%lx\n", type, + (long int)*id); + return -EINVAL; + +found: + *id = priv->firm[i].id; + tuner_info ("Found firmware for type=%x, id=%lx\n", type, + (long int)*id); + + p = priv->firm[i].ptr; + + if (!p) { + printk(KERN_ERR PREFIX "Firmware pointer were freed!"); + return -EINVAL; + } + endp = p+priv->firm[i].size; + + while (pendp) { + tuner_info("missing bytes\n"); + return -EINVAL; + } + + + size = le16_to_cpu(*(__u16 *)p); + p += sizeof(size); + + if (size == 0xffff) + return 0; + + if (!size) { /* Special callback command received */ rc = priv->tuner_callback(priv->video_dev, - XC2028_TUNER_RESET, (*p)&0x7f); + XC2028_TUNER_RESET, 0); if (rc<0) { tuner_info("Error at RESET code %d\n", (*p)&0x7f); - goto err; + return -EINVAL; } - p++; continue; } - len=*p; - p++; - if (p+len+1>endp) { - /* Firmware is incorrect */ - tuner_info("Error: firmware is truncated!\n"); - rc=-EINVAL; - goto err; - } - if (len<=0) { - tuner_info("Error: firmware file is corrupted!\n"); - rc=-EINVAL; - goto err; + + /* Checks for a sleep command */ + if (size & 0x8000) { + msleep (size & 0x7fff); + continue; } - i2c_send(rc, priv, p, len); - if (rc<0) - goto err; - p+=len; + if ((size + p > endp)) { + tuner_info("missing bytes: need %d, have %d\n", + size, (int)(endp-p)); + return -EINVAL; + } - if (*p) - msleep(*p); + buf[0] = *p; p++; - } + size--; + /* Sends message chunks */ + while (size>0) { + int len = (sizemax_len-1)?size:priv->max_len-1; -err: - release_firmware(fw); + memcpy(buf+1, p, len); - return rc; + i2c_send(rc, priv, buf, len+1); + if (rc<0) { + tuner_info("%d returned from send\n",rc); + return -EINVAL; + } + + p += len; + size -= len; + } + } + return -EINVAL; } static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode, @@ -208,11 +382,21 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode, { struct xc2028_data *priv = fe->tuner_priv; int rc, version; - const char *name; - int change_digital_bandwidth; + v4l2_std_id std0=0; + unsigned int type0=0,type=0; + int change_digital_bandwidth; tuner_info("%s called\n", __FUNCTION__); + if (!priv->firm) { + if (!priv->ctrl.fname) + return -EINVAL; + + rc=load_all_firmwares(fe); + if (rc<0) + return rc; + } + tuner_info( "I am in mode %u and I should switch to mode %i\n", priv->mode, new_mode); @@ -225,23 +409,31 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode, change_digital_bandwidth = (priv->mode == T_DIGITAL_TV && bandwidth != priv->bandwidth) ? 1 : 0; tuner_info("old bandwidth %u, new bandwidth %u\n", priv->bandwidth, - bandwidth); + bandwidth); if (priv->need_load_generic) { - if (priv->bandwidth==8) - name = firmware_8MHZ_INIT0; - else - name = firmware_INIT0; - /* Reset is needed before loading firmware */ rc = priv->tuner_callback(priv->video_dev, XC2028_TUNER_RESET, 0); if (rc<0) return rc; - rc = load_firmware(fe,name); - if (rc<0) + type0=BASE; + + if (priv->ctrl.type == XC2028_FIRM_MTS) + type0 |= MTS; + + if (priv->bandwidth==8) + type0 |= F8MHZ; + + /* FIXME: How to load FM and FM|INPUT1 firmwares? */ + + rc = load_firmware(fe, type0, &std0); + if (rc<0) { + tuner_info("Error %d while loading generic firmware\n", + rc); return rc; + } priv->need_load_generic=0; priv->firm_type=0; @@ -253,49 +445,53 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode, tuner_info("I should change bandwidth %u\n", change_digital_bandwidth); - /* FIXME: t->std makes no sense here */ if (change_digital_bandwidth) { + + /*FIXME: Should allow selecting between D2620 and D2633 */ + type |= D2620; + + /* FIXME: When should select a DTV78 firmware? + */ switch(bandwidth) { - case BANDWIDTH_8_MHZ: - std = V4L2_STD_DTV_8MHZ; + case BANDWIDTH_8_MHZ: + type |= DTV8; break; - - case BANDWIDTH_7_MHZ: - std = V4L2_STD_DTV_7MHZ; + case BANDWIDTH_7_MHZ: + type |= DTV7; break; - - case BANDWIDTH_6_MHZ: - std = V4L2_STD_DTV_6MHZ; + case BANDWIDTH_6_MHZ: + /* FIXME: Should allow select also ATSC */ + type |= DTV6_QAM; break; - default: - tuner_info("error: bandwidth not supported.\n"); + default: + tuner_info("error: bandwidth not supported.\n"); }; priv->bandwidth = bandwidth; } + /* Load INIT1, if needed */ + tuner_info("Trying to load init1 firmware\n"); + type0 = BASE | INIT1 | priv->ctrl.type; + if (priv->ctrl.type == XC2028_FIRM_MTS) + type0 |= MTS; + + /* FIXME: Should handle errors - if INIT1 found */ + rc = load_firmware(fe, type0, &std0); + + /* FIXME: Should add support for FM radio + */ + + if (priv->ctrl.type == XC2028_FIRM_MTS) + type |= MTS; + + tuner_info("firmware standard to load: %08lx\n",(unsigned long) std); if (priv->firm_type & std) { - tuner_info("xc3028: no need to load a std-specific firmware.\n"); + tuner_info("no need to load a std-specific firmware.\n"); return 0; } - rc = load_firmware(fe,firmware_INIT1); - - if (std & V4L2_STD_MN) - name=firmware_MN; - else if (std & V4L2_STD_DTV_6MHZ) - name=firmware_6M; - else if (std & V4L2_STD_DTV_7MHZ) - name=firmware_7M; - else if (std & V4L2_STD_DTV_8MHZ) - name=firmware_8M; - else if (std & V4L2_STD_PAL_B) - name=firmware_B; - else - name=firmware_DK; - - tuner_info("loading firmware named %s.\n", name); - rc = load_firmware(fe, name); + rc = load_firmware(fe, type, &std); if (rc<0) return rc; @@ -353,12 +549,12 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */, tuner_info("%s called\n", __FUNCTION__); + mutex_lock(&priv->lock); + #if 1 /* HACK: It seems that specific firmware need to be reloaded when freq is changed */ - mutex_lock(&priv->lock); - priv->firm_type=0; /* Reset GPIO 1 */ @@ -379,7 +575,13 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */, div = (freq - offset + DIV/2)/DIV; /* CMD= Set frequency */ - send_seq(priv, {0x00, 0x02, 0x00, 0x00}); + + if (priv->version<0x0202) { + send_seq(priv, {0x00, 0x02, 0x00, 0x00}); + } else { + send_seq(priv, {0x80, 0x02, 0x00, 0x00}); + } + rc = priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1); if (rc<0) goto ret; @@ -450,8 +652,13 @@ static int xc2028_dvb_release(struct dvb_frontend *fe) priv->count--; - if (!priv->count) + if (!priv->count) { + if (priv->ctrl.fname) + kfree(priv->ctrl.fname); + + free_firmware(priv); kfree (priv); + } return 0; } @@ -467,6 +674,32 @@ static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency) return 0; } +static int xc2028_set_config (struct dvb_frontend *fe, void *priv_cfg) +{ + struct xc2028_data *priv = fe->tuner_priv; + struct xc2028_ctrl *p = priv_cfg; + + tuner_info("%s called\n", __FUNCTION__); + + priv->ctrl.type = p->type; + + if (p->fname) { + if (priv->ctrl.fname) + kfree(priv->ctrl.fname); + + priv->ctrl.fname = kmalloc(strlen(p->fname)+1, GFP_KERNEL); + if (!priv->ctrl.fname) + return -ENOMEM; + + free_firmware(priv); + strcpy(priv->ctrl.fname, p->fname); + } + + tuner_info("%s OK\n", __FUNCTION__); + + return 0; +} + static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = { .info = { .name = "Xceive XC3028", @@ -475,6 +708,7 @@ static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = { .frequency_step = 50000, }, + .set_config = xc2028_set_config, .set_analog_params = xc2028_set_tv_freq, .release = xc2028_dvb_release, .get_frequency = xc2028_get_frequency, @@ -527,6 +761,19 @@ int xc2028_attach(struct dvb_frontend *fe, struct i2c_adapter* i2c_adap, priv->dev = dev; priv->video_dev = video_dev; priv->tuner_callback = tuner_callback; + priv->max_len = 13; + +#if 0 + /* Without fname, xc2028/3028 won't work. So, this driver will only + work after calling TUNER_SET_CONFIG */ + + priv->ctrl.fname = kmalloc(sizeof(DEFAULT_FIRMWARE)+1, + GFP_KERNEL); + if (!priv->ctrl.fname) + return -ENOMEM; + + strcpy (priv->ctrl.fname, DEFAULT_FIRMWARE); +#endif mutex_init(&priv->lock); diff --git a/linux/drivers/media/video/tuner-xc2028.h b/linux/drivers/media/video/tuner-xc2028.h index d5a18a37d..f4856f07b 100644 --- a/linux/drivers/media/video/tuner-xc2028.h +++ b/linux/drivers/media/video/tuner-xc2028.h @@ -9,13 +9,22 @@ #include "dvb_frontend.h" +#define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw" + +enum xc2028_firm_type { + XC2028_FIRM_NORMAL, + XC2028_FIRM_MTS, +}; + +struct xc2028_ctrl { + enum xc2028_firm_type type; + char *fname; +}; + /* xc2028 commands for callback */ #define XC2028_TUNER_RESET 0 #define XC2028_RESET_CLK 1 -struct dvb_frontend; -struct i2c_client; - #if defined(CONFIG_TUNER_XC2028) || (defined(CONFIG_TUNER_XC2028_MODULE) && defined(MODULE)) int xc2028_attach(struct dvb_frontend *fe, struct i2c_adapter* i2c_adap, u8 i2c_addr, struct device *dev, void *video_dev, -- cgit v1.2.3 From 803132a3c8c06956bc3fc589693fb390dcf23368 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 24 Oct 2007 08:06:47 -0400 Subject: tuner: fix CONFIG_TUNER_TEA5761=m From: Adrian Bunk This patch fixes CONFIG_TUNER_TEA5761=m broken by commit ca805d57cf5ea7482ed3da28653f30621249ee45. Signed-off-by: Adrian Bunk Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-core.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) --- linux/drivers/media/video/tuner-core.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 3c8ffe423..4d1c2c7a2 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -35,7 +35,7 @@ /* standard i2c insmod options */ static unsigned short normal_i2c[] = { -#ifdef CONFIG_TUNER_TEA5761 +#if defined(CONFIG_TUNER_TEA5761) || (defined(CONFIG_TUNER_TEA5761_MODULE) && defined(MODULE)) 0x10, #endif 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ @@ -322,7 +322,6 @@ static void set_type(struct i2c_client *c, unsigned int type, } t->mode_mask = T_RADIO; break; -#ifdef CONFIG_TUNER_TEA5761 case TUNER_TEA5761: if (tea5761_attach(&t->fe, t->i2c.adapter, t->i2c.addr) == NULL) { t->type = TUNER_ABSENT; @@ -331,7 +330,6 @@ static void set_type(struct i2c_client *c, unsigned int type, } t->mode_mask = T_RADIO; break; -#endif case TUNER_PHILIPS_FMD1216ME_MK3: buffer[0] = 0x0b; buffer[1] = 0xdc; @@ -650,7 +648,6 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, /* autodetection code based on the i2c addr */ if (!no_autodetect) { switch (addr) { -#ifdef CONFIG_TUNER_TEA5761 case 0x10: if (tea5761_autodetection(t->i2c.adapter, t->i2c.addr) != EINVAL) { t->type = TUNER_TEA5761; @@ -662,7 +659,6 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, goto register_client; } break; -#endif case 0x42: case 0x43: case 0x4a: -- cgit v1.2.3 From b9cd19d4eca8dac90da1724311b50a428d88487e Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 25 Aug 2007 18:08:45 -0400 Subject: Move all tda8275/8275a tuning code from tda8290 module into tda827x module From: Michael Krufky Add analog tuning support to tda827x dvb_frontend tuner module. Convert tda8290 module back to native tuner interface. The tda8290 analog demodulator will be handled the same way as tda9887. The tuner.ko module (tuner-core) will pass commands to tda8290 via the tuner_operations interface. tda8290 will communicate with tda827x via the dvb_frontend interface, while passing a pointer to a private data structure. Signed-off-by: Michael Krufky Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/Kconfig | 1 linux/drivers/media/dvb/frontends/tda827x.c | 307 ++++++++++++++- linux/drivers/media/dvb/frontends/tda827x.h | 10 linux/drivers/media/video/tda8290.c | 566 +++++----------------------- linux/drivers/media/video/tda8290.h | 30 - linux/drivers/media/video/tuner-core.c | 16 6 files changed, 424 insertions(+), 506 deletions(-) --- linux/drivers/media/Kconfig | 1 + linux/drivers/media/dvb/frontends/tda827x.c | 307 ++++++++++++++- linux/drivers/media/dvb/frontends/tda827x.h | 10 + linux/drivers/media/video/tda8290.c | 568 ++++++---------------------- linux/drivers/media/video/tda8290.h | 30 +- linux/drivers/media/video/tuner-core.c | 16 +- 6 files changed, 425 insertions(+), 507 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/Kconfig b/linux/drivers/media/Kconfig index ee778ee71..a2b49dd5c 100644 --- a/linux/drivers/media/Kconfig +++ b/linux/drivers/media/Kconfig @@ -107,6 +107,7 @@ config TUNER_MT20XX config TUNER_TDA8290 tristate "TDA 8290+8275(a) tuner combo" depends on I2C + select DVB_TDA827X default m if VIDEO_TUNER_CUSTOMIZE help Say Y here to include support for Philips TDA8290+8275(a) tuner. diff --git a/linux/drivers/media/dvb/frontends/tda827x.c b/linux/drivers/media/dvb/frontends/tda827x.c index 256fc4bf5..3c71f07a6 100644 --- a/linux/drivers/media/dvb/frontends/tda827x.c +++ b/linux/drivers/media/dvb/frontends/tda827x.c @@ -19,12 +19,16 @@ */ #include -#include #include +#include +#include #include "tda827x.h" static int debug = 0; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + #define dprintk(args...) \ do { \ if (debug) printk(KERN_DEBUG "tda827x: " args); \ @@ -48,7 +52,7 @@ struct tda827x_data { u8 div1p5; }; -static const struct tda827x_data tda827x_dvbt[] = { +static const struct tda827x_data tda827x_table[] = { { .lomax = 62000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, { .lomax = 66000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, { .lomax = 76000000, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, @@ -106,21 +110,22 @@ static int tda827xo_set_params(struct dvb_frontend *fe, tuner_freq = params->frequency + if_freq; i = 0; - while (tda827x_dvbt[i].lomax < tuner_freq) { - if(tda827x_dvbt[i + 1].lomax == 0) + while (tda827x_table[i].lomax < tuner_freq) { + if (tda827x_table[i + 1].lomax == 0) break; i++; } - N = ((tuner_freq + 125000) / 250000) << (tda827x_dvbt[i].spd + 2); + N = ((tuner_freq + 125000) / 250000) << (tda827x_table[i].spd + 2); buf[0] = 0; buf[1] = (N>>8) | 0x40; buf[2] = N & 0xff; buf[3] = 0; buf[4] = 0x52; - buf[5] = (tda827x_dvbt[i].spd << 6) + (tda827x_dvbt[i].div1p5 << 5) + - (tda827x_dvbt[i].bs << 3) + tda827x_dvbt[i].bp; - buf[6] = (tda827x_dvbt[i].gc3 << 4) + 0x8f; + buf[5] = (tda827x_table[i].spd << 6) + (tda827x_table[i].div1p5 << 5) + + (tda827x_table[i].bs << 3) + + tda827x_table[i].bp; + buf[6] = (tda827x_table[i].gc3 << 4) + 0x8f; buf[7] = 0xbf; buf[8] = 0x2a; buf[9] = 0x05; @@ -140,7 +145,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe, msleep(500); /* correct CP value */ buf[0] = 0x30; - buf[1] = 0x50 + tda827x_dvbt[i].cp; + buf[1] = 0x50 + tda827x_table[i].cp; msg.len = 2; if (fe->ops.i2c_gate_ctrl) @@ -173,6 +178,100 @@ static int tda827xo_sleep(struct dvb_frontend *fe) /* ------------------------------------------------------------------ */ +static int tda827xo_set_analog_params(struct dvb_frontend *fe, + struct analog_parameters *params) +{ + unsigned char tuner_reg[8]; + unsigned char reg2[2]; + u32 N; + int i; + struct tda827x_priv *priv = fe->tuner_priv; + struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0 }; + unsigned int freq = params->frequency; + + if (params->mode == V4L2_TUNER_RADIO) + freq = freq / 1000; + + N = freq + priv->cfg->sgIF; + + i = 0; + while (tda827x_table[i].lomax < N * 62500) { + if (tda827x_table[i + 1].lomax == 0) + break; + i++; + } + + N = N << tda827x_table[i].spd; + + tuner_reg[0] = 0; + tuner_reg[1] = (unsigned char)(N>>8); + tuner_reg[2] = (unsigned char) N; + tuner_reg[3] = 0x40; + tuner_reg[4] = 0x52 + (priv->cfg->tda827x_lpsel << 5); + tuner_reg[5] = (tda827x_table[i].spd << 6) + + (tda827x_table[i].div1p5 << 5) + + (tda827x_table[i].bs << 3) + tda827x_table[i].bp; + tuner_reg[6] = 0x8f + (tda827x_table[i].gc3 << 4); + tuner_reg[7] = 0x8f; + + msg.buf = tuner_reg; + msg.len = 8; + i2c_transfer(priv->i2c_adap, &msg, 1); + + msg.buf = reg2; + msg.len = 2; + reg2[0] = 0x80; + reg2[1] = 0; + i2c_transfer(priv->i2c_adap, &msg, 1); + + reg2[0] = 0x60; + reg2[1] = 0xbf; + i2c_transfer(priv->i2c_adap, &msg, 1); + + reg2[0] = 0x30; + reg2[1] = tuner_reg[4] + 0x80; + i2c_transfer(priv->i2c_adap, &msg, 1); + + msleep(1); + reg2[0] = 0x30; + reg2[1] = tuner_reg[4] + 4; + i2c_transfer(priv->i2c_adap, &msg, 1); + + msleep(1); + reg2[0] = 0x30; + reg2[1] = tuner_reg[4]; + i2c_transfer(priv->i2c_adap, &msg, 1); + + msleep(550); + reg2[0] = 0x30; + reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_table[i].cp; + i2c_transfer(priv->i2c_adap, &msg, 1); + + reg2[0] = 0x60; + reg2[1] = 0x3f; + i2c_transfer(priv->i2c_adap, &msg, 1); + + reg2[0] = 0x80; + reg2[1] = 0x08; /* Vsync en */ + i2c_transfer(priv->i2c_adap, &msg, 1); + + priv->frequency = freq * 62500; + + return 0; +} + +static void tda827xo_agcf(struct dvb_frontend *fe) +{ + struct tda827x_priv *priv = fe->tuner_priv; + unsigned char data[] = { 0x80, 0x0c }; + struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, + .buf = data, .len = 2}; + + i2c_transfer(priv->i2c_adap, &msg, 1); +} + +/* ------------------------------------------------------------------ */ + struct tda827xa_data { u32 lomax; u8 svco; @@ -212,6 +311,35 @@ static const struct tda827xa_data tda827xa_dvbt[] = { { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0} }; +static struct tda827xa_data tda827xa_analog[] = { + { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3}, + { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, + { .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, + { .lomax = 97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, + { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1}, + { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 3}, + { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 3}, + { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1}, + { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3}, + { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3}, + { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, + { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1}, + { .lomax = 554000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, + { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, + { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, + { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, + { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, + { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, + { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, + { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0}, + { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0} +}; + static int tda827xa_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { @@ -368,6 +496,156 @@ static int tda827xa_sleep(struct dvb_frontend *fe) return 0; } +/* ------------------------------------------------------------------ */ + +static void tda827xa_lna_gain(struct dvb_frontend *fe, int high, + struct analog_parameters *params) +{ + struct tda827x_priv *priv = fe->tuner_priv; + unsigned char buf[] = {0x22, 0x01}; + int arg; + struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, + .buf = buf, .len = sizeof(buf) }; + + if (priv->cfg->config) { + if (high) + dprintk("setting LNA to high gain\n"); + else + dprintk("setting LNA to low gain\n"); + } + switch (*priv->cfg->config) { + case 0: /* no LNA */ + break; + case 1: /* switch is GPIO 0 of tda8290 */ + case 2: + /* turn Vsync on */ + if (params->std & V4L2_STD_MN) + arg = 1; + else + arg = 0; + if (priv->cfg->tuner_callback) + priv->cfg->tuner_callback(priv->i2c_adap->algo_data, + 1, arg); + buf[1] = high ? 0 : 1; + if (*priv->cfg->config == 2) + buf[1] = high ? 1 : 0; + i2c_transfer(priv->i2c_adap, &msg, 1); + break; + case 3: /* switch with GPIO of saa713x */ + if (priv->cfg->tuner_callback) + priv->cfg->tuner_callback(priv->i2c_adap->algo_data, + 0, high); + break; + } +} + +static int tda827xa_set_analog_params(struct dvb_frontend *fe, + struct analog_parameters *params) +{ + unsigned char tuner_reg[11]; + u32 N; + int i; + struct tda827x_priv *priv = fe->tuner_priv; + struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, + .buf = tuner_reg, .len = sizeof(tuner_reg) }; + unsigned int freq = params->frequency; + + tda827xa_lna_gain(fe, 1, params); + msleep(10); + + if (params->mode == V4L2_TUNER_RADIO) + freq = freq / 1000; + + N = freq + priv->cfg->sgIF; + + i = 0; + while (tda827xa_analog[i].lomax < N * 62500) { + if (tda827xa_analog[i + 1].lomax == 0) + break; + i++; + } + + N = N << tda827xa_analog[i].spd; + + tuner_reg[0] = 0; + tuner_reg[1] = (unsigned char)(N>>8); + tuner_reg[2] = (unsigned char) N; + tuner_reg[3] = 0; + tuner_reg[4] = 0x16; + tuner_reg[5] = (tda827xa_analog[i].spd << 5) + + (tda827xa_analog[i].svco << 3) + + tda827xa_analog[i].sbs; + tuner_reg[6] = 0x8b + (tda827xa_analog[i].gc3 << 4); + tuner_reg[7] = 0x1c; + tuner_reg[8] = 4; + tuner_reg[9] = 0x20; + tuner_reg[10] = 0x00; + msg.len = 11; + i2c_transfer(priv->i2c_adap, &msg, 1); + + tuner_reg[0] = 0x90; + tuner_reg[1] = 0xff; + tuner_reg[2] = 0xe0; + tuner_reg[3] = 0; + tuner_reg[4] = 0x99 + (priv->cfg->tda827x_lpsel << 1); + msg.len = 5; + i2c_transfer(priv->i2c_adap, &msg, 1); + + tuner_reg[0] = 0xa0; + tuner_reg[1] = 0xc0; + msg.len = 2; + i2c_transfer(priv->i2c_adap, &msg, 1); + + tuner_reg[0] = 0x30; + tuner_reg[1] = 0x10 + tda827xa_analog[i].scr; + i2c_transfer(priv->i2c_adap, &msg, 1); + + msg.flags = I2C_M_RD; + i2c_transfer(priv->i2c_adap, &msg, 1); + msg.flags = 0; + tuner_reg[1] >>= 4; + dprintk("AGC2 gain is: %d\n", tuner_reg[1]); + if (tuner_reg[1] < 1) + tda827xa_lna_gain(fe, 0, params); + + msleep(100); + tuner_reg[0] = 0x60; + tuner_reg[1] = 0x3c; + i2c_transfer(priv->i2c_adap, &msg, 1); + + msleep(163); + tuner_reg[0] = 0x50; + tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4); + i2c_transfer(priv->i2c_adap, &msg, 1); + + tuner_reg[0] = 0x80; + tuner_reg[1] = 0x28; + i2c_transfer(priv->i2c_adap, &msg, 1); + + tuner_reg[0] = 0xb0; + tuner_reg[1] = 0x01; + i2c_transfer(priv->i2c_adap, &msg, 1); + + tuner_reg[0] = 0xc0; + tuner_reg[1] = 0x19 + (priv->cfg->tda827x_lpsel << 1); + i2c_transfer(priv->i2c_adap, &msg, 1); + + priv->frequency = freq * 62500; + + return 0; +} + +static void tda827xa_agcf(struct dvb_frontend *fe) +{ + struct tda827x_priv *priv = fe->tuner_priv; + unsigned char data[] = {0x80, 0x2c}; + struct i2c_msg msg = {.addr = priv->i2c_addr, .flags = 0, + .buf = data, .len = 2}; + i2c_transfer(priv->i2c_adap, &msg, 1); +} + +/* ------------------------------------------------------------------ */ + static int tda827x_release(struct dvb_frontend *fe) { kfree(fe->tuner_priv); @@ -430,6 +708,7 @@ static struct dvb_tuner_ops tda827xo_tuner_ops = { .init = tda827x_initial_init, .sleep = tda827x_initial_sleep, .set_params = tda827xo_set_params, + .set_analog_params = tda827xo_set_analog_params, .get_frequency = tda827x_get_frequency, .get_bandwidth = tda827x_get_bandwidth, }; @@ -445,6 +724,7 @@ static struct dvb_tuner_ops tda827xa_tuner_ops = { .init = tda827x_init, .sleep = tda827xa_sleep, .set_params = tda827xa_set_params, + .set_analog_params = tda827xa_set_analog_params, .get_frequency = tda827x_get_frequency, .get_bandwidth = tda827x_get_bandwidth, }; @@ -465,9 +745,11 @@ static int tda827x_probe_version(struct dvb_frontend *fe) dprintk("tda827x tuner found\n"); fe->ops.tuner_ops.init = tda827x_init; fe->ops.tuner_ops.sleep = tda827xo_sleep; + priv->cfg->agcf = tda827xo_agcf; } else { dprintk("tda827xa tuner found\n"); memcpy(&fe->ops.tuner_ops, &tda827xa_tuner_ops, sizeof(struct dvb_tuner_ops)); + priv->cfg->agcf = tda827xa_agcf; } return 0; } @@ -487,17 +769,14 @@ struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr, priv->i2c_adap = i2c; priv->cfg = cfg; memcpy(&fe->ops.tuner_ops, &tda827xo_tuner_ops, sizeof(struct dvb_tuner_ops)); - fe->tuner_priv = priv; + dprintk("type set to %s\n", fe->ops.tuner_ops.info.name); + return fe; } - EXPORT_SYMBOL(tda827x_attach); -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); - MODULE_DESCRIPTION("DVB TDA827x driver"); MODULE_AUTHOR("Hartmut Hackmann "); MODULE_AUTHOR("Michael Krufky "); diff --git a/linux/drivers/media/dvb/frontends/tda827x.h b/linux/drivers/media/dvb/frontends/tda827x.h index 69e8263d6..06626f7af 100644 --- a/linux/drivers/media/dvb/frontends/tda827x.h +++ b/linux/drivers/media/dvb/frontends/tda827x.h @@ -29,9 +29,19 @@ struct tda827x_config { + /* saa7134 - provided callbacks */ void (*lna_gain) (struct dvb_frontend *fe, int high); int (*init) (struct dvb_frontend *fe); int (*sleep) (struct dvb_frontend *fe); + + /* interface to tda829x driver */ + unsigned char tda827x_lpsel; + unsigned int sgIF; + + unsigned int *config; + int (*tuner_callback) (void *dev, int command, int arg); + + void (*agcf)(struct dvb_frontend *fe); }; diff --git a/linux/drivers/media/video/tda8290.c b/linux/drivers/media/video/tda8290.c index e00b3516b..882872720 100644 --- a/linux/drivers/media/video/tda8290.c +++ b/linux/drivers/media/video/tda8290.c @@ -24,14 +24,19 @@ #include #include "compat.h" #include -#include "tuner-i2c.h" #include "tda8290.h" +#include "tda827x.h" #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "i2c-compat.h" #endif +#if 0 static int debug = 0; module_param(debug, int, 0644); +#else +static int tuner_debug = 0; +module_param_named(debug, tuner_debug, int, 0644); +#endif MODULE_PARM_DESC(debug, "enable verbose debug messages"); #define PREFIX "tda8290 " @@ -42,332 +47,18 @@ struct tda8290_priv { struct tuner_i2c_props i2c_props; unsigned char tda8290_easy_mode; - unsigned char tda827x_lpsel; + unsigned char tda827x_addr; unsigned char tda827x_ver; - unsigned int sgIF; - u32 frequency; - - unsigned int *lna_cfg; - int (*tuner_callback) (void *dev, int command,int arg); + struct tda827x_config cfg; }; -/* ---------------------------------------------------------------------- */ - -struct tda827x_data { - u32 lomax; - u8 spd; - u8 bs; - u8 bp; - u8 cp; - u8 gc3; - u8 div1p5; -}; - - /* Note lomax entry is lo / 62500 */ - -static struct tda827x_data tda827x_analog[] = { - { .lomax = 992, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, /* 62 MHz */ - { .lomax = 1056, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, /* 66 MHz */ - { .lomax = 1216, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, /* 76 MHz */ - { .lomax = 1344, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, /* 84 MHz */ - { .lomax = 1488, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 93 MHz */ - { .lomax = 1568, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 98 MHz */ - { .lomax = 1744, .spd = 3, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 109 MHz */ - { .lomax = 1968, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 123 MHz */ - { .lomax = 2128, .spd = 2, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 133 MHz */ - { .lomax = 2416, .spd = 2, .bs = 1, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 151 MHz */ - { .lomax = 2464, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 154 MHz */ - { .lomax = 2896, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 181 MHz */ - { .lomax = 2960, .spd = 2, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 185 MHz */ - { .lomax = 3472, .spd = 2, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 217 MHz */ - { .lomax = 3904, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 244 MHz */ - { .lomax = 4240, .spd = 1, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 265 MHz */ - { .lomax = 4832, .spd = 1, .bs = 1, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 302 MHz */ - { .lomax = 5184, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 324 MHz */ - { .lomax = 5920, .spd = 1, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 370 MHz */ - { .lomax = 7264, .spd = 1, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 454 MHz */ - { .lomax = 7888, .spd = 0, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 493 MHz */ - { .lomax = 8480, .spd = 0, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 530 MHz */ - { .lomax = 8864, .spd = 0, .bs = 1, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 554 MHz */ - { .lomax = 9664, .spd = 0, .bs = 1, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 604 MHz */ - { .lomax = 11088, .spd = 0, .bs = 2, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 696 MHz */ - { .lomax = 11840, .spd = 0, .bs = 2, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0}, /* 740 MHz */ - { .lomax = 13120, .spd = 0, .bs = 3, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 820 MHz */ - { .lomax = 13840, .spd = 0, .bs = 3, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0}, /* 865 MHz */ - { .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0} /* End */ -}; - -static void tda827x_set_analog_params(struct dvb_frontend *fe, - struct analog_parameters *params) -{ - unsigned char tuner_reg[8]; - unsigned char reg2[2]; - u32 N; - int i; - struct tda8290_priv *priv = fe->tuner_priv; - struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags = 0}; - unsigned int freq = params->frequency; - - if (params->mode == V4L2_TUNER_RADIO) - freq = freq / 1000; - - N = freq + priv->sgIF; - i = 0; - while (tda827x_analog[i].lomax < N) { - if(tda827x_analog[i + 1].lomax == 0) - break; - i++; - } - - N = N << tda827x_analog[i].spd; - - tuner_reg[0] = 0; - tuner_reg[1] = (unsigned char)(N>>8); - tuner_reg[2] = (unsigned char) N; - tuner_reg[3] = 0x40; - tuner_reg[4] = 0x52 + (priv->tda827x_lpsel << 5); - tuner_reg[5] = (tda827x_analog[i].spd << 6) + (tda827x_analog[i].div1p5 <<5) + - (tda827x_analog[i].bs <<3) + tda827x_analog[i].bp; - tuner_reg[6] = 0x8f + (tda827x_analog[i].gc3 << 4); - tuner_reg[7] = 0x8f; - - msg.buf = tuner_reg; - msg.len = 8; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - msg.buf= reg2; - msg.len = 2; - reg2[0] = 0x80; - reg2[1] = 0; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - reg2[0] = 0x60; - reg2[1] = 0xbf; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - reg2[0] = 0x30; - reg2[1] = tuner_reg[4] + 0x80; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - msleep(1); - reg2[0] = 0x30; - reg2[1] = tuner_reg[4] + 4; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - msleep(1); - reg2[0] = 0x30; - reg2[1] = tuner_reg[4]; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - msleep(550); - reg2[0] = 0x30; - reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_analog[i].cp ; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - reg2[0] = 0x60; - reg2[1] = 0x3f; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - reg2[0] = 0x80; - reg2[1] = 0x08; // Vsync en - i2c_transfer(priv->i2c_props.adap, &msg, 1); -} - -static void tda827x_agcf(struct dvb_frontend *fe) -{ - struct tda8290_priv *priv = fe->tuner_priv; - unsigned char data[] = {0x80, 0x0c}; - struct i2c_msg msg = {.addr = priv->tda827x_addr, .buf = data, - .flags = 0, .len = 2}; - i2c_transfer(priv->i2c_props.adap, &msg, 1); -} - -/* ---------------------------------------------------------------------- */ - -struct tda827xa_data { - u32 lomax; - u8 svco; - u8 spd; - u8 scr; - u8 sbs; - u8 gc3; -}; - -static struct tda827xa_data tda827xa_analog[] = { - { .lomax = 910, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3}, /* 56.875 MHz */ - { .lomax = 1076, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, /* 67.25 MHz */ - { .lomax = 1300, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, /* 81.25 MHz */ - { .lomax = 1560, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, /* 97.5 MHz */ - { .lomax = 1820, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1}, /* 113.75 MHz */ - { .lomax = 2152, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 134.5 MHz */ - { .lomax = 2464, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 154 MHz */ - { .lomax = 2600, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 162.5 MHz */ - { .lomax = 2928, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 183 MHz */ - { .lomax = 3120, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1}, /* 195 MHz */ - { .lomax = 3640, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 3}, /* 227.5 MHz */ - { .lomax = 4304, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 3}, /* 269 MHz */ - { .lomax = 5200, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1}, /* 325 MHz */ - { .lomax = 6240, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3}, /* 390 MHz */ - { .lomax = 7280, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3}, /* 455 MHz */ - { .lomax = 8320, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, /* 520 MHz */ - { .lomax = 8608, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1}, /* 538 MHz */ - { .lomax = 8864, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, /* 554 MHz */ - { .lomax = 9920, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, /* 620 MHz */ - { .lomax = 10400, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, /* 650 MHz */ - { .lomax = 11200, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, /* 700 MHz */ - { .lomax = 12480, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, /* 780 MHz */ - { .lomax = 13120, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, /* 820 MHz */ - { .lomax = 13920, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, /* 870 MHz */ - { .lomax = 14576, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0}, /* 911 MHz */ - { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0} /* End */ -}; - -static void tda827xa_lna_gain(struct dvb_frontend *fe, int high, - struct analog_parameters *params) -{ - struct tda8290_priv *priv = fe->tuner_priv; - unsigned char buf[] = {0x22, 0x01}; - int arg; - struct i2c_msg msg = {.addr = priv->i2c_props.addr, .flags = 0, .buf = buf, .len = sizeof(buf)}; - - if ((priv->lna_cfg == NULL) || (priv->tuner_callback == NULL)) - return; - - if (*priv->lna_cfg) { - if (high) - tuner_dbg("setting LNA to high gain\n"); - else - tuner_dbg("setting LNA to low gain\n"); - } - switch (*priv->lna_cfg) { - case 0: /* no LNA */ - break; - case 1: /* switch is GPIO 0 of tda8290 */ - case 2: - /* turn Vsync on */ - if (params->std & V4L2_STD_MN) - arg = 1; - else - arg = 0; - if (priv->tuner_callback) - priv->tuner_callback(priv->i2c_props.adap->algo_data, 1, arg); - buf[1] = high ? 0 : 1; - if (*priv->lna_cfg == 2) - buf[1] = high ? 1 : 0; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - break; - case 3: /* switch with GPIO of saa713x */ - if (priv->tuner_callback) - priv->tuner_callback(priv->i2c_props.adap->algo_data, 0, high); - break; - } -} - -static void tda827xa_set_analog_params(struct dvb_frontend *fe, - struct analog_parameters *params) -{ - unsigned char tuner_reg[11]; - u32 N; - int i; - struct tda8290_priv *priv = fe->tuner_priv; - struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags = 0, .buf = tuner_reg}; - unsigned int freq = params->frequency; - - tda827xa_lna_gain(fe, 1, params); - msleep(10); - - if (params->mode == V4L2_TUNER_RADIO) - freq = freq / 1000; - - N = freq + priv->sgIF; - i = 0; - while (tda827xa_analog[i].lomax < N) { - if(tda827xa_analog[i + 1].lomax == 0) - break; - i++; - } - - N = N << tda827xa_analog[i].spd; - - tuner_reg[0] = 0; - tuner_reg[1] = (unsigned char)(N>>8); - tuner_reg[2] = (unsigned char) N; - tuner_reg[3] = 0; - tuner_reg[4] = 0x16; - tuner_reg[5] = (tda827xa_analog[i].spd << 5) + (tda827xa_analog[i].svco << 3) + - tda827xa_analog[i].sbs; - tuner_reg[6] = 0x8b + (tda827xa_analog[i].gc3 << 4); - tuner_reg[7] = 0x1c; - tuner_reg[8] = 4; - tuner_reg[9] = 0x20; - tuner_reg[10] = 0x00; - msg.len = 11; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - tuner_reg[0] = 0x90; - tuner_reg[1] = 0xff; - tuner_reg[2] = 0xe0; - tuner_reg[3] = 0; - tuner_reg[4] = 0x99 + (priv->tda827x_lpsel << 1); - msg.len = 5; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - tuner_reg[0] = 0xa0; - tuner_reg[1] = 0xc0; - msg.len = 2; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - tuner_reg[0] = 0x30; - tuner_reg[1] = 0x10 + tda827xa_analog[i].scr; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - msg.flags = I2C_M_RD; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - msg.flags = 0; - tuner_reg[1] >>= 4; - tuner_dbg("AGC2 gain is: %d\n", tuner_reg[1]); - if (tuner_reg[1] < 1) - tda827xa_lna_gain(fe, 0, params); - - msleep(100); - tuner_reg[0] = 0x60; - tuner_reg[1] = 0x3c; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - msleep(163); - tuner_reg[0] = 0x50; - tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4); - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - tuner_reg[0] = 0x80; - tuner_reg[1] = 0x28; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - tuner_reg[0] = 0xb0; - tuner_reg[1] = 0x01; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - tuner_reg[0] = 0xc0; - tuner_reg[1] = 0x19 + (priv->tda827x_lpsel << 1); - i2c_transfer(priv->i2c_props.adap, &msg, 1); -} - -static void tda827xa_agcf(struct dvb_frontend *fe) -{ - struct tda8290_priv *priv = fe->tuner_priv; - unsigned char data[] = {0x80, 0x2c}; - struct i2c_msg msg = {.addr = priv->tda827x_addr, .buf = data, - .flags = 0, .len = 2}; - i2c_transfer(priv->i2c_props.adap, &msg, 1); -} - /*---------------------------------------------------------------------*/ -static void tda8290_i2c_bridge(struct dvb_frontend *fe, int close) +static void tda8290_i2c_bridge(struct tuner *t, int close) { - struct tda8290_priv *priv = fe->tuner_priv; + struct tda8290_priv *priv = t->priv; unsigned char enable[2] = { 0x21, 0xC0 }; unsigned char disable[2] = { 0x21, 0x00 }; @@ -385,58 +76,56 @@ static void tda8290_i2c_bridge(struct dvb_frontend *fe, int close) /*---------------------------------------------------------------------*/ -static void set_audio(struct dvb_frontend *fe, - struct analog_parameters *params) +static void set_audio(struct tuner *t) { - struct tda8290_priv *priv = fe->tuner_priv; + struct tda8290_priv *priv = t->priv; char* mode; - priv->tda827x_lpsel = 0; - if (params->std & V4L2_STD_MN) { - priv->sgIF = 92; + priv->cfg.tda827x_lpsel = 0; + if (t->std & V4L2_STD_MN) { + priv->cfg.sgIF = 92; priv->tda8290_easy_mode = 0x01; - priv->tda827x_lpsel = 1; + priv->cfg.tda827x_lpsel = 1; mode = "MN"; - } else if (params->std & V4L2_STD_B) { - priv->sgIF = 108; + } else if (t->std & V4L2_STD_B) { + priv->cfg.sgIF = 108; priv->tda8290_easy_mode = 0x02; mode = "B"; - } else if (params->std & V4L2_STD_GH) { - priv->sgIF = 124; + } else if (t->std & V4L2_STD_GH) { + priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x04; mode = "GH"; - } else if (params->std & V4L2_STD_PAL_I) { - priv->sgIF = 124; + } else if (t->std & V4L2_STD_PAL_I) { + priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x08; mode = "I"; - } else if (params->std & V4L2_STD_DK) { - priv->sgIF = 124; + } else if (t->std & V4L2_STD_DK) { + priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x10; mode = "DK"; - } else if (params->std & V4L2_STD_SECAM_L) { - priv->sgIF = 124; + } else if (t->std & V4L2_STD_SECAM_L) { + priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x20; mode = "L"; - } else if (params->std & V4L2_STD_SECAM_LC) { - priv->sgIF = 20; + } else if (t->std & V4L2_STD_SECAM_LC) { + priv->cfg.sgIF = 20; priv->tda8290_easy_mode = 0x40; mode = "LC"; } else { - priv->sgIF = 124; + priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x10; mode = "xx"; } - if (params->mode == V4L2_TUNER_RADIO) - priv->sgIF = 88; /* if frequency is 5.5 MHz */ + if (t->mode == V4L2_TUNER_RADIO) + priv->cfg.sgIF = 88; /* if frequency is 5.5 MHz */ tuner_dbg("setting tda8290 to system %s\n", mode); } -static int tda8290_set_params(struct dvb_frontend *fe, - struct analog_parameters *params) +static void tda8290_set_freq(struct tuner *t, unsigned int freq) { - struct tda8290_priv *priv = fe->tuner_priv; + struct tda8290_priv *priv = t->priv; unsigned char soft_reset[] = { 0x00, 0x00 }; unsigned char easy_mode[] = { 0x01, priv->tda8290_easy_mode }; unsigned char expert_mode[] = { 0x01, 0x80 }; @@ -459,10 +148,16 @@ static int tda8290_set_params(struct dvb_frontend *fe, pll_stat; int i; - set_audio(fe, params); + struct analog_parameters params = { + .frequency = freq, + .mode = t->mode, + .audmode = t->audmode, + .std = t->std + }; + + set_audio(t); - if (priv->lna_cfg) - tuner_dbg("tda827xa config is 0x%02x\n", *priv->lna_cfg); + tuner_dbg("tda827xa config is 0x%02x\n", t->config); tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2); tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2); tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2); @@ -478,11 +173,11 @@ static int tda8290_set_params(struct dvb_frontend *fe, tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2); tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2); - tda8290_i2c_bridge(fe, 1); - if (priv->tda827x_ver != 0) - tda827xa_set_analog_params(fe, params); - else - tda827x_set_analog_params(fe, params); + tda8290_i2c_bridge(t, 1); + + if (t->fe.ops.tuner_ops.set_analog_params) + t->fe.ops.tuner_ops.set_analog_params(&t->fe, ¶ms); + for (i = 0; i < 3; i++) { tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); @@ -511,10 +206,8 @@ static int tda8290_set_params(struct dvb_frontend *fe, if ((agc_stat > 115) || !(pll_stat & 0x80)) { tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n", agc_stat, pll_stat & 0x80); - if (priv->tda827x_ver != 0) - tda827xa_agcf(fe); - else - tda827x_agcf(fe); + if (priv->cfg.agcf) + priv->cfg.agcf(&t->fe); msleep(100); tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); @@ -543,94 +236,61 @@ static int tda8290_set_params(struct dvb_frontend *fe, } } - tda8290_i2c_bridge(fe, 0); + tda8290_i2c_bridge(t, 0); tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2); - - priv->frequency = (V4L2_TUNER_RADIO == params->mode) ? - params->frequency * 125 / 2 : params->frequency * 62500; - - return 0; } /*---------------------------------------------------------------------*/ -static int tda8290_has_signal(struct dvb_frontend *fe) +static int tda8290_has_signal(struct tuner *t) { - struct tda8290_priv *priv = fe->tuner_priv; - int ret; + struct tda8290_priv *priv = t->priv; unsigned char i2c_get_afc[1] = { 0x1B }; unsigned char afc = 0; - /* for now, report based on afc status */ tuner_i2c_xfer_send(&priv->i2c_props, i2c_get_afc, ARRAY_SIZE(i2c_get_afc)); tuner_i2c_xfer_recv(&priv->i2c_props, &afc, 1); - - ret = (afc & 0x80) ? 65535 : 0; - - tuner_dbg("AFC status: %d\n", ret); - - return ret; -} - -static int tda8290_get_status(struct dvb_frontend *fe, u32 *status) -{ - *status = 0; - - if (tda8290_has_signal(fe)) - *status = TUNER_STATUS_LOCKED; - - return 0; -} - -static int tda8290_get_rf_strength(struct dvb_frontend *fe, u16 *strength) -{ - *strength = tda8290_has_signal(fe); - - return 0; + return (afc & 0x80)? 65535:0; } /*---------------------------------------------------------------------*/ -static int tda8290_standby(struct dvb_frontend *fe) +static void tda8290_standby(struct tuner *t) { - struct tda8290_priv *priv = fe->tuner_priv; + struct tda8290_priv *priv = t->priv; unsigned char cb1[] = { 0x30, 0xD0 }; unsigned char tda8290_standby[] = { 0x00, 0x02 }; unsigned char tda8290_agc_tri[] = { 0x02, 0x20 }; struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2}; - tda8290_i2c_bridge(fe, 1); + tda8290_i2c_bridge(t, 1); if (priv->tda827x_ver != 0) cb1[1] = 0x90; i2c_transfer(priv->i2c_props.adap, &msg, 1); - tda8290_i2c_bridge(fe, 0); + tda8290_i2c_bridge(t, 0); tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2); tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2); - - return 0; } - -static void tda8290_init_if(struct dvb_frontend *fe) +static void tda8290_init_if(struct tuner *t) { - struct tda8290_priv *priv = fe->tuner_priv; + struct tda8290_priv *priv = t->priv; unsigned char set_VS[] = { 0x30, 0x6F }; unsigned char set_GP00_CF[] = { 0x20, 0x01 }; unsigned char set_GP01_CF[] = { 0x20, 0x0B }; - if ((priv->lna_cfg) && - ((*priv->lna_cfg == 1) || (*priv->lna_cfg == 2))) + if ((t->config == 1) || (t->config == 2)) tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2); else tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2); tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2); } -static void tda8290_init_tuner(struct dvb_frontend *fe) +static void tda8290_init_tuner(struct tuner *t) { - struct tda8290_priv *priv = fe->tuner_priv; + struct tda8290_priv *priv = t->priv; unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf, 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 }; unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b, @@ -640,41 +300,31 @@ static void tda8290_init_tuner(struct dvb_frontend *fe) if (priv->tda827x_ver != 0) msg.buf = tda8275a_init; - tda8290_i2c_bridge(fe, 1); + tda8290_i2c_bridge(t, 1); i2c_transfer(priv->i2c_props.adap, &msg, 1); - tda8290_i2c_bridge(fe, 0); + tda8290_i2c_bridge(t, 0); } /*---------------------------------------------------------------------*/ -static int tda8290_release(struct dvb_frontend *fe) +static void tda8290_release(struct tuner *t) { - kfree(fe->tuner_priv); - fe->tuner_priv = NULL; + if (t->fe.ops.tuner_ops.release) + t->fe.ops.tuner_ops.release(&t->fe); - return 0; -} - -static int tda8290_get_frequency(struct dvb_frontend *fe, u32 *frequency) -{ - struct tda8290_priv *priv = fe->tuner_priv; - *frequency = priv->frequency; - return 0; + kfree(t->priv); + t->priv = NULL; } -static struct dvb_tuner_ops tda8290_tuner_ops = { - .sleep = tda8290_standby, - .set_analog_params = tda8290_set_params, - .release = tda8290_release, - .get_frequency = tda8290_get_frequency, - .get_status = tda8290_get_status, - .get_rf_strength = tda8290_get_rf_strength, +static struct tuner_operations tda8290_tuner_ops = { + .set_tv_freq = tda8290_set_freq, + .set_radio_freq = tda8290_set_freq, + .has_signal = tda8290_has_signal, + .standby = tda8290_standby, + .release = tda8290_release, }; -struct dvb_frontend *tda8290_attach(struct dvb_frontend *fe, - struct i2c_adapter* i2c_adap, - u8 i2c_addr, - struct tda8290_config *cfg) +int tda8290_attach(struct tuner *t) { struct tda8290_priv *priv = NULL; u8 data; @@ -684,17 +334,15 @@ struct dvb_frontend *tda8290_attach(struct dvb_frontend *fe, priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); if (priv == NULL) - return NULL; - fe->tuner_priv = priv; - - priv->i2c_props.addr = i2c_addr; - priv->i2c_props.adap = i2c_adap; - if (cfg) { - priv->lna_cfg = cfg->lna_cfg; - priv->tuner_callback = cfg->tuner_callback; - } + return -ENOMEM; + t->priv = priv; - tda8290_i2c_bridge(fe, 1); + priv->i2c_props.addr = t->i2c.addr; + priv->i2c_props.adap = t->i2c.adapter; + priv->cfg.config = &t->config; + priv->cfg.tuner_callback = t->tuner_callback; + + tda8290_i2c_bridge(t, 1); /* probe for tuner chip */ tuners_found = 0; tuner_addrs = 0; @@ -710,7 +358,7 @@ struct dvb_frontend *tda8290_attach(struct dvb_frontend *fe, behind the bridge and we choose the highest address that doesn't give a response now */ - tda8290_i2c_bridge(fe, 0); + tda8290_i2c_bridge(t, 0); if(tuners_found > 1) for (i = 0; i < tuners_found; i++) { msg.addr = tuner_addrs & 0xff; @@ -731,45 +379,45 @@ struct dvb_frontend *tda8290_attach(struct dvb_frontend *fe, priv->tda827x_addr = tuner_addrs; msg.addr = tuner_addrs; - tda8290_i2c_bridge(fe, 1); + tda8290_i2c_bridge(t, 1); + ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); if( ret != 1) tuner_warn("TDA827x access failed!\n"); - memcpy(&fe->ops.tuner_ops, &tda8290_tuner_ops, - sizeof(struct dvb_tuner_ops)); - if ((data & 0x3c) == 0) { - strlcpy(fe->ops.tuner_ops.info.name, "tda8290+75", - sizeof(fe->ops.tuner_ops.info.name)); - fe->ops.tuner_ops.info.frequency_min = 55000000; - fe->ops.tuner_ops.info.frequency_max = 860000000; - fe->ops.tuner_ops.info.frequency_step = 250000; + strlcpy(t->i2c.name, "tda8290+75", sizeof(t->i2c.name)); priv->tda827x_ver = 0; } else { - strlcpy(fe->ops.tuner_ops.info.name, "tda8290+75a", - sizeof(fe->ops.tuner_ops.info.name)); - fe->ops.tuner_ops.info.frequency_min = 44000000; - fe->ops.tuner_ops.info.frequency_max = 906000000; - fe->ops.tuner_ops.info.frequency_step = 62500; + strlcpy(t->i2c.name, "tda8290+75a", sizeof(t->i2c.name)); priv->tda827x_ver = 2; } + tda827x_attach(&t->fe, priv->tda827x_addr, + priv->i2c_props.adap, &priv->cfg); - priv->tda827x_lpsel = 0; -#if 0 + /* FIXME: tda827x module doesn't probe the tuner until + * tda827x_initial_sleep is called + */ + if (t->fe.ops.tuner_ops.sleep) + t->fe.ops.tuner_ops.sleep(&t->fe); + + memcpy(&t->ops, &tda8290_tuner_ops, sizeof(struct tuner_operations)); + + tuner_info("type set to %s\n", t->i2c.name); + + priv->cfg.tda827x_lpsel = 0; t->mode = V4L2_TUNER_ANALOG_TV; -#endif - tda8290_init_tuner(fe); - tda8290_init_if(fe); - return fe; + tda8290_init_tuner(t); + tda8290_init_if(t); + return 0; } -int tda8290_probe(struct i2c_adapter* i2c_adap, u8 i2c_addr) +int tda8290_probe(struct tuner *t) { struct tuner_i2c_props i2c_props = { - .adap = i2c_adap, - .addr = i2c_addr + .adap = t->i2c.adapter, + .addr = t->i2c.addr }; unsigned char soft_reset[] = { 0x00, 0x00 }; diff --git a/linux/drivers/media/video/tda8290.h b/linux/drivers/media/video/tda8290.h index 107b24b05..9b63e62b3 100644 --- a/linux/drivers/media/video/tda8290.h +++ b/linux/drivers/media/video/tda8290.h @@ -18,36 +18,24 @@ #define __TDA8290_H__ #include -#include "dvb_frontend.h" - -struct tda8290_config -{ - unsigned int *lna_cfg; - int (*tuner_callback) (void *dev, int command,int arg); -}; +#include "tuner-driver.h" #if defined(CONFIG_TUNER_TDA8290) || (defined(CONFIG_TUNER_TDA8290_MODULE) && defined(MODULE)) -extern int tda8290_probe(struct i2c_adapter* i2c_adap, u8 i2c_addr); +extern int tda8290_probe(struct tuner *t); -extern struct dvb_frontend *tda8290_attach(struct dvb_frontend *fe, - struct i2c_adapter* i2c_adap, - u8 i2c_addr, - struct tda8290_config *cfg); +extern int tda8290_attach(struct tuner *t); #else -static inline int tda8290_probe(struct i2c_adapter* i2c_adap, u8 i2c_addr) +static inline int tda8290_probe(struct tuner *t) { - printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", - __FUNCTION__); + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); return -EINVAL; } -static inline struct dvb_frontend *tda8290_attach(struct dvb_frontend *fe, - struct i2c_adapter* i2c_adap, - u8 i2c_addr, - struct tda8290_config *cfg) +static inline int tda8290_attach(struct tuner *t) { - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); - return NULL; + printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", + __FUNCTION__); + return -EINVAL; } #endif diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 4d1c2c7a2..b02a18cd7 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -245,15 +245,6 @@ static void tuner_i2c_address_check(struct tuner *t) tuner_warn("====================== WARNING! ======================\n"); } -static void attach_tda8290(struct tuner *t) -{ - struct tda8290_config cfg = { - .lna_cfg = &t->config, - .tuner_callback = t->tuner_callback - }; - tda8290_attach(&t->fe, t->i2c.adapter, t->i2c.addr, &cfg); -} - static void attach_simple_tuner(struct tuner *t) { struct simple_tuner_config cfg = { @@ -311,7 +302,7 @@ static void set_type(struct i2c_client *c, unsigned int type, break; case TUNER_PHILIPS_TDA8290: { - attach_tda8290(t); + tda8290_attach(t); break; } case TUNER_TEA5767: @@ -370,7 +361,8 @@ static void set_type(struct i2c_client *c, unsigned int type, break; } - if (fe_tuner_ops->set_analog_params) { + if ((fe_tuner_ops->set_analog_params) && + ((NULL == t->ops.set_tv_freq) && (NULL == t->ops.set_radio_freq))) { strlcpy(t->i2c.name, fe_tuner_ops->info.name, sizeof(t->i2c.name)); t->ops.set_tv_freq = fe_set_freq; @@ -665,7 +657,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, case 0x4b: /* If chip is not tda8290, don't register. since it can be tda9887*/ - if (tda8290_probe(t->i2c.adapter, t->i2c.addr) == 0) { + if (tda8290_probe(t) == 0) { tuner_dbg("chip at addr %x is a tda8290\n", addr); } else { /* Default is being tda9887 */ -- cgit v1.2.3 From a13ef5b4f0fa3617da1cc100fc809baf91ace7e3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 21 Oct 2007 23:28:50 -0400 Subject: tda827x: fix GPL export on attach function From: Michael Krufky EXPORT_SYMBOL should have been EXPORT_SYMBOL_GPL Signed-off-by: Michael Krufky Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/tda827x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- linux/drivers/media/dvb/frontends/tda827x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/tda827x.c b/linux/drivers/media/dvb/frontends/tda827x.c index 3c71f07a6..6de1aea02 100644 --- a/linux/drivers/media/dvb/frontends/tda827x.c +++ b/linux/drivers/media/dvb/frontends/tda827x.c @@ -775,7 +775,7 @@ struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr, return fe; } -EXPORT_SYMBOL(tda827x_attach); +EXPORT_SYMBOL_GPL(tda827x_attach); MODULE_DESCRIPTION("DVB TDA827x driver"); MODULE_AUTHOR("Hartmut Hackmann "); -- cgit v1.2.3 From d9d95216cef86d580d36f7a13cc80bcb4973c4c8 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 22 Oct 2007 08:56:38 -0400 Subject: tda8290: add support for NXP TDA18271 tuner and TDA8295 analog demod From: Michael Krufky Add basic support for NXP TDA8295 analog demod and TDA18271 tuner silicon. TDA8295 + TDA8275a not yet tested. TDA8290 + TDA18271 not yet supported. Digital mode of TDA18271 not yet tested & needs more work. Signed-off-by: Michael Krufky Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/CARDLIST.tuner | 1 linux/drivers/media/Kconfig | 3 linux/drivers/media/dvb/frontends/Kconfig | 7 linux/drivers/media/dvb/frontends/Makefile | 1 linux/drivers/media/dvb/frontends/tda18271.c | 1062 +++++++++++++++++++++++++ linux/drivers/media/dvb/frontends/tda18271.h | 40 linux/drivers/media/video/tda8290.c | 339 +++++++ linux/drivers/media/video/tda8290.h | 8 linux/drivers/media/video/tuner-core.c | 5 linux/drivers/media/video/tuner-types.c | 3 linux/drivers/media/video/tveeprom.c | 2 linux/include/media/tuner.h | 2 v4l/versions.txt | 2 13 files changed, 1467 insertions(+), 8 deletions(-) --- linux/drivers/media/Kconfig | 3 +- linux/drivers/media/dvb/frontends/Kconfig | 7 + linux/drivers/media/dvb/frontends/Makefile | 1 + linux/drivers/media/dvb/frontends/tda18271.c | 1062 ++++++++++++++++++++++++++ linux/drivers/media/dvb/frontends/tda18271.h | 40 + linux/drivers/media/video/tda8290.c | 339 +++++++- linux/drivers/media/video/tda8290.h | 8 + linux/drivers/media/video/tuner-core.c | 5 + linux/drivers/media/video/tuner-types.c | 3 + linux/drivers/media/video/tveeprom.c | 2 +- 10 files changed, 1462 insertions(+), 8 deletions(-) create mode 100644 linux/drivers/media/dvb/frontends/tda18271.c create mode 100644 linux/drivers/media/dvb/frontends/tda18271.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/Kconfig b/linux/drivers/media/Kconfig index a2b49dd5c..416d85c65 100644 --- a/linux/drivers/media/Kconfig +++ b/linux/drivers/media/Kconfig @@ -105,9 +105,10 @@ config TUNER_MT20XX Say Y here to include support for the MT2032 / MT2050 tuner. config TUNER_TDA8290 - tristate "TDA 8290+8275(a) tuner combo" + tristate "TDA 8290/8295 + 8275(a)/18271 tuner combo" depends on I2C select DVB_TDA827X + select DVB_TDA18271 default m if VIDEO_TUNER_CUSTOMIZE help Say Y here to include support for Philips TDA8290+8275(a) tuner. diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index 59b9ed1f1..57178d6e1 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -316,6 +316,13 @@ config DVB_TDA827X help A DVB-T silicon tuner module. Say Y when you want to support this tuner. +config DVB_TDA18271 + tristate "NXP TDA18271 silicon tuner" + depends on I2C + default m if DVB_FE_CUSTOMISE + help + A silicon tuner module. Say Y when you want to support this tuner. + config DVB_TUNER_QT1010 tristate "Quantek QT1010 silicon tuner" depends on DVB_CORE && I2C diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile index 4b8ad1f13..457effcda 100644 --- a/linux/drivers/media/dvb/frontends/Makefile +++ b/linux/drivers/media/dvb/frontends/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_DVB_ISL6421) += isl6421.o obj-$(CONFIG_DVB_TDA10086) += tda10086.o obj-$(CONFIG_DVB_TDA826X) += tda826x.o obj-$(CONFIG_DVB_TDA827X) += tda827x.o +obj-$(CONFIG_DVB_TDA18271) += tda18271.o obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o obj-$(CONFIG_DVB_TUNER_MT2266) += mt2266.o obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o diff --git a/linux/drivers/media/dvb/frontends/tda18271.c b/linux/drivers/media/dvb/frontends/tda18271.c new file mode 100644 index 000000000..83e89a54f --- /dev/null +++ b/linux/drivers/media/dvb/frontends/tda18271.c @@ -0,0 +1,1062 @@ +/* + tda18271.c - driver for the Philips / NXP TDA18271 silicon tuner + + Copyright (C) 2007 Michael Krufky (mkrufky@linuxtv.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include + +#include "tda18271.h" + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + +#define tuner_dbg(fmt, arg...) do {\ + if (debug > 0) \ + printk(KERN_DEBUG fmt, ##arg); } while (0) + +#define tuner_extra_dbg(fmt, arg...) do {\ + if (debug > 1) \ + printk(KERN_DEBUG fmt, ##arg); } while (0) + +#define R_ID 0x00 /* ID byte */ +#define R_TM 0x01 /* Thermo byte */ +#define R_PL 0x02 /* Power level byte */ +#define R_EP1 0x03 /* Easy Prog byte 1 */ +#define R_EP2 0x04 /* Easy Prog byte 2 */ +#define R_EP3 0x05 /* Easy Prog byte 3 */ +#define R_EP4 0x06 /* Easy Prog byte 4 */ +#define R_EP5 0x07 /* Easy Prog byte 5 */ +#define R_CPD 0x08 /* Cal Post-Divider byte */ +#define R_CD1 0x09 /* Cal Divider byte 1 */ +#define R_CD2 0x0a /* Cal Divider byte 2 */ +#define R_CD3 0x0b /* Cal Divider byte 3 */ +#define R_MPD 0x0c /* Main Post-Divider byte */ +#define R_MD1 0x0d /* Main Divider byte 1 */ +#define R_MD2 0x0e /* Main Divider byte 2 */ +#define R_MD3 0x0f /* Main Divider byte 3 */ +#define R_EB1 0x10 /* Extended byte 1 */ +#define R_EB2 0x11 /* Extended byte 2 */ +#define R_EB3 0x12 /* Extended byte 3 */ +#define R_EB4 0x13 /* Extended byte 4 */ +#define R_EB5 0x14 /* Extended byte 5 */ +#define R_EB6 0x15 /* Extended byte 6 */ +#define R_EB7 0x16 /* Extended byte 7 */ +#define R_EB8 0x17 /* Extended byte 8 */ +#define R_EB9 0x18 /* Extended byte 9 */ +#define R_EB10 0x19 /* Extended byte 10 */ +#define R_EB11 0x1a /* Extended byte 11 */ +#define R_EB12 0x1b /* Extended byte 12 */ +#define R_EB13 0x1c /* Extended byte 13 */ +#define R_EB14 0x1d /* Extended byte 14 */ +#define R_EB15 0x1e /* Extended byte 15 */ +#define R_EB16 0x1f /* Extended byte 16 */ +#define R_EB17 0x20 /* Extended byte 17 */ +#define R_EB18 0x21 /* Extended byte 18 */ +#define R_EB19 0x22 /* Extended byte 19 */ +#define R_EB20 0x23 /* Extended byte 20 */ +#define R_EB21 0x24 /* Extended byte 21 */ +#define R_EB22 0x25 /* Extended byte 22 */ +#define R_EB23 0x26 /* Extended byte 23 */ + +struct tda18271_pll_map { + u32 lomax; + u8 pd; /* post div */ + u8 d; /* div */ +}; + +static struct tda18271_pll_map tda18271_main_pll[] = { + { .lomax = 32000, .pd = 0x5f, .d = 0xf0 }, + { .lomax = 35000, .pd = 0x5e, .d = 0xe0 }, + { .lomax = 37000, .pd = 0x5d, .d = 0xd0 }, + { .lomax = 41000, .pd = 0x5c, .d = 0xc0 }, + { .lomax = 44000, .pd = 0x5b, .d = 0xb0 }, + { .lomax = 49000, .pd = 0x5a, .d = 0xa0 }, + { .lomax = 54000, .pd = 0x59, .d = 0x90 }, + { .lomax = 61000, .pd = 0x58, .d = 0x80 }, + { .lomax = 65000, .pd = 0x4f, .d = 0x78 }, + { .lomax = 70000, .pd = 0x4e, .d = 0x70 }, + { .lomax = 75000, .pd = 0x4d, .d = 0x68 }, + { .lomax = 82000, .pd = 0x4c, .d = 0x60 }, + { .lomax = 89000, .pd = 0x4b, .d = 0x58 }, + { .lomax = 98000, .pd = 0x4a, .d = 0x50 }, + { .lomax = 109000, .pd = 0x49, .d = 0x48 }, + { .lomax = 123000, .pd = 0x48, .d = 0x40 }, + { .lomax = 131000, .pd = 0x3f, .d = 0x3c }, + { .lomax = 141000, .pd = 0x3e, .d = 0x38 }, + { .lomax = 151000, .pd = 0x3d, .d = 0x34 }, + { .lomax = 164000, .pd = 0x3c, .d = 0x30 }, + { .lomax = 179000, .pd = 0x3b, .d = 0x2c }, + { .lomax = 197000, .pd = 0x3a, .d = 0x28 }, + { .lomax = 219000, .pd = 0x39, .d = 0x24 }, + { .lomax = 246000, .pd = 0x38, .d = 0x20 }, + { .lomax = 263000, .pd = 0x2f, .d = 0x1e }, + { .lomax = 282000, .pd = 0x2e, .d = 0x1c }, + { .lomax = 303000, .pd = 0x2d, .d = 0x1a }, + { .lomax = 329000, .pd = 0x2c, .d = 0x18 }, + { .lomax = 359000, .pd = 0x2b, .d = 0x16 }, + { .lomax = 395000, .pd = 0x2a, .d = 0x14 }, + { .lomax = 438000, .pd = 0x29, .d = 0x12 }, + { .lomax = 493000, .pd = 0x28, .d = 0x10 }, + { .lomax = 526000, .pd = 0x1f, .d = 0x0f }, + { .lomax = 564000, .pd = 0x1e, .d = 0x0e }, + { .lomax = 607000, .pd = 0x1d, .d = 0x0d }, + { .lomax = 658000, .pd = 0x1c, .d = 0x0c }, + { .lomax = 718000, .pd = 0x1b, .d = 0x0b }, + { .lomax = 790000, .pd = 0x1a, .d = 0x0a }, + { .lomax = 877000, .pd = 0x19, .d = 0x09 }, + { .lomax = 987000, .pd = 0x18, .d = 0x08 }, + { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */ +}; + +static struct tda18271_pll_map tda18271_cal_pll[] = { + { .lomax = 33000, .pd = 0xdd, .d = 0xd0 }, + { .lomax = 36000, .pd = 0xdc, .d = 0xc0 }, + { .lomax = 40000, .pd = 0xdb, .d = 0xb0 }, + { .lomax = 44000, .pd = 0xda, .d = 0xa0 }, + { .lomax = 49000, .pd = 0xd9, .d = 0x90 }, + { .lomax = 55000, .pd = 0xd8, .d = 0x80 }, + { .lomax = 63000, .pd = 0xd3, .d = 0x70 }, + { .lomax = 67000, .pd = 0xcd, .d = 0x68 }, + { .lomax = 73000, .pd = 0xcc, .d = 0x60 }, + { .lomax = 80000, .pd = 0xcb, .d = 0x58 }, + { .lomax = 88000, .pd = 0xca, .d = 0x50 }, + { .lomax = 98000, .pd = 0xc9, .d = 0x48 }, + { .lomax = 110000, .pd = 0xc8, .d = 0x40 }, + { .lomax = 126000, .pd = 0xc3, .d = 0x38 }, + { .lomax = 135000, .pd = 0xbd, .d = 0x34 }, + { .lomax = 147000, .pd = 0xbc, .d = 0x30 }, + { .lomax = 160000, .pd = 0xbb, .d = 0x2c }, + { .lomax = 176000, .pd = 0xba, .d = 0x28 }, + { .lomax = 196000, .pd = 0xb9, .d = 0x24 }, + { .lomax = 220000, .pd = 0xb8, .d = 0x20 }, + { .lomax = 252000, .pd = 0xb3, .d = 0x1c }, + { .lomax = 271000, .pd = 0xad, .d = 0x1a }, + { .lomax = 294000, .pd = 0xac, .d = 0x18 }, + { .lomax = 321000, .pd = 0xab, .d = 0x16 }, + { .lomax = 353000, .pd = 0xaa, .d = 0x14 }, + { .lomax = 392000, .pd = 0xa9, .d = 0x12 }, + { .lomax = 441000, .pd = 0xa8, .d = 0x10 }, + { .lomax = 505000, .pd = 0xa3, .d = 0x0e }, + { .lomax = 543000, .pd = 0x9d, .d = 0x0d }, + { .lomax = 589000, .pd = 0x9c, .d = 0x0c }, + { .lomax = 642000, .pd = 0x9b, .d = 0x0b }, + { .lomax = 707000, .pd = 0x9a, .d = 0x0a }, + { .lomax = 785000, .pd = 0x99, .d = 0x09 }, + { .lomax = 883000, .pd = 0x98, .d = 0x08 }, + { .lomax = 1010000, .pd = 0x93, .d = 0x07 }, + { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */ +}; + +struct tda18271_map { + u32 rfmax; + u8 val; +}; + +static struct tda18271_map tda18271_bp_filter[] = { + { .rfmax = 62000, .val = 0x00 }, + { .rfmax = 84000, .val = 0x01 }, + { .rfmax = 100000, .val = 0x02 }, + { .rfmax = 140000, .val = 0x03 }, + { .rfmax = 170000, .val = 0x04 }, + { .rfmax = 180000, .val = 0x05 }, + { .rfmax = 865000, .val = 0x06 }, + { .rfmax = 0, .val = 0x00 }, /* end */ +}; + +static struct tda18271_map tda18271_km[] = { + { .rfmax = 61100, .val = 0x74 }, + { .rfmax = 350000, .val = 0x40 }, + { .rfmax = 720000, .val = 0x30 }, + { .rfmax = 865000, .val = 0x40 }, + { .rfmax = 0, .val = 0x00 }, /* end */ +}; + +static struct tda18271_map tda18271_rf_band[] = { + { .rfmax = 47900, .val = 0x00 }, + { .rfmax = 61100, .val = 0x01 }, +/* { .rfmax = 152600, .val = 0x02 }, */ + { .rfmax = 121200, .val = 0x02 }, + { .rfmax = 164700, .val = 0x03 }, + { .rfmax = 203500, .val = 0x04 }, + { .rfmax = 457800, .val = 0x05 }, + { .rfmax = 865000, .val = 0x06 }, + { .rfmax = 0, .val = 0x00 }, /* end */ +}; + +static struct tda18271_map tda18271_gain_taper[] = { + { .rfmax = 45400, .val = 0x1f }, + { .rfmax = 45800, .val = 0x1e }, + { .rfmax = 46200, .val = 0x1d }, + { .rfmax = 46700, .val = 0x1c }, + { .rfmax = 47100, .val = 0x1b }, + { .rfmax = 47500, .val = 0x1a }, + { .rfmax = 47900, .val = 0x19 }, + { .rfmax = 49600, .val = 0x17 }, + { .rfmax = 51200, .val = 0x16 }, + { .rfmax = 52900, .val = 0x15 }, + { .rfmax = 54500, .val = 0x14 }, + { .rfmax = 56200, .val = 0x13 }, + { .rfmax = 57800, .val = 0x12 }, + { .rfmax = 59500, .val = 0x11 }, + { .rfmax = 61100, .val = 0x10 }, + { .rfmax = 67600, .val = 0x0d }, + { .rfmax = 74200, .val = 0x0c }, + { .rfmax = 80700, .val = 0x0b }, + { .rfmax = 87200, .val = 0x0a }, + { .rfmax = 93800, .val = 0x09 }, + { .rfmax = 100300, .val = 0x08 }, + { .rfmax = 106900, .val = 0x07 }, + { .rfmax = 113400, .val = 0x06 }, + { .rfmax = 119900, .val = 0x05 }, + { .rfmax = 126500, .val = 0x04 }, + { .rfmax = 133000, .val = 0x03 }, + { .rfmax = 139500, .val = 0x02 }, + { .rfmax = 146100, .val = 0x01 }, + { .rfmax = 152600, .val = 0x00 }, + { .rfmax = 154300, .val = 0x1f }, + { .rfmax = 156100, .val = 0x1e }, + { .rfmax = 157800, .val = 0x1d }, + { .rfmax = 159500, .val = 0x1c }, + { .rfmax = 161200, .val = 0x1b }, + { .rfmax = 163000, .val = 0x1a }, + { .rfmax = 164700, .val = 0x19 }, + { .rfmax = 170200, .val = 0x17 }, + { .rfmax = 175800, .val = 0x16 }, + { .rfmax = 181300, .val = 0x15 }, + { .rfmax = 186900, .val = 0x14 }, + { .rfmax = 192400, .val = 0x13 }, + { .rfmax = 198000, .val = 0x12 }, + { .rfmax = 203500, .val = 0x11 }, + { .rfmax = 216200, .val = 0x14 }, + { .rfmax = 228900, .val = 0x13 }, + { .rfmax = 241600, .val = 0x12 }, + { .rfmax = 254400, .val = 0x11 }, + { .rfmax = 267100, .val = 0x10 }, + { .rfmax = 279800, .val = 0x0f }, + { .rfmax = 292500, .val = 0x0e }, + { .rfmax = 305200, .val = 0x0d }, + { .rfmax = 317900, .val = 0x0c }, + { .rfmax = 330700, .val = 0x0b }, + { .rfmax = 343400, .val = 0x0a }, + { .rfmax = 356100, .val = 0x09 }, + { .rfmax = 368800, .val = 0x08 }, + { .rfmax = 381500, .val = 0x07 }, + { .rfmax = 394200, .val = 0x06 }, + { .rfmax = 406900, .val = 0x05 }, + { .rfmax = 419700, .val = 0x04 }, + { .rfmax = 432400, .val = 0x03 }, + { .rfmax = 445100, .val = 0x02 }, + { .rfmax = 457800, .val = 0x01 }, + { .rfmax = 476300, .val = 0x19 }, + { .rfmax = 494800, .val = 0x18 }, + { .rfmax = 513300, .val = 0x17 }, + { .rfmax = 531800, .val = 0x16 }, + { .rfmax = 550300, .val = 0x15 }, + { .rfmax = 568900, .val = 0x14 }, + { .rfmax = 587400, .val = 0x13 }, + { .rfmax = 605900, .val = 0x12 }, + { .rfmax = 624400, .val = 0x11 }, + { .rfmax = 642900, .val = 0x10 }, + { .rfmax = 661400, .val = 0x0f }, + { .rfmax = 679900, .val = 0x0e }, + { .rfmax = 698400, .val = 0x0d }, + { .rfmax = 716900, .val = 0x0c }, + { .rfmax = 735400, .val = 0x0b }, + { .rfmax = 753900, .val = 0x0a }, + { .rfmax = 772500, .val = 0x09 }, + { .rfmax = 791000, .val = 0x08 }, + { .rfmax = 809500, .val = 0x07 }, + { .rfmax = 828000, .val = 0x06 }, + { .rfmax = 846500, .val = 0x05 }, + { .rfmax = 865000, .val = 0x04 }, + { .rfmax = 0, .val = 0x00 }, /* end */ +}; + +static struct tda18271_map tda18271_rf_cal[] = { + { .rfmax = 41000, .val = 0x1e }, + { .rfmax = 43000, .val = 0x30 }, + { .rfmax = 45000, .val = 0x43 }, + { .rfmax = 46000, .val = 0x4d }, + { .rfmax = 47000, .val = 0x54 }, + { .rfmax = 47900, .val = 0x64 }, + { .rfmax = 49100, .val = 0x20 }, + { .rfmax = 50000, .val = 0x22 }, + { .rfmax = 51000, .val = 0x2a }, + { .rfmax = 53000, .val = 0x32 }, + { .rfmax = 55000, .val = 0x35 }, + { .rfmax = 56000, .val = 0x3c }, + { .rfmax = 57000, .val = 0x3f }, + { .rfmax = 58000, .val = 0x48 }, + { .rfmax = 59000, .val = 0x4d }, + { .rfmax = 60000, .val = 0x58 }, + { .rfmax = 61100, .val = 0x5f }, + { .rfmax = 0, .val = 0x00 }, /* end */ +}; + +/*---------------------------------------------------------------------*/ + +#define TDA18271_NUM_REGS 39 + +#define TDA18271_ANALOG 0 +#define TDA18271_DIGITAL 1 + +struct tda18271_priv { + u8 i2c_addr; + struct i2c_adapter *i2c_adap; + unsigned char tda18271_regs[TDA18271_NUM_REGS]; + int mode; + + u32 frequency; + u32 bandwidth; +}; + +/*---------------------------------------------------------------------*/ + +static void tda18271_dump_regs(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + + tuner_dbg("=== TDA18271 REG DUMP ===\n"); + tuner_dbg("ID_BYTE = 0x%x\n", 0xff & regs[R_ID]); + tuner_dbg("THERMO_BYTE = 0x%x\n", 0xff & regs[R_TM]); + tuner_dbg("POWER_LEVEL_BYTE = 0x%x\n", 0xff & regs[R_PL]); + tuner_dbg("EASY_PROG_BYTE_1 = 0x%x\n", 0xff & regs[R_EP1]); + tuner_dbg("EASY_PROG_BYTE_2 = 0x%x\n", 0xff & regs[R_EP2]); + tuner_dbg("EASY_PROG_BYTE_3 = 0x%x\n", 0xff & regs[R_EP3]); + tuner_dbg("EASY_PROG_BYTE_4 = 0x%x\n", 0xff & regs[R_EP4]); + tuner_dbg("EASY_PROG_BYTE_5 = 0x%x\n", 0xff & regs[R_EP5]); + tuner_dbg("CAL_POST_DIV_BYTE = 0x%x\n", 0xff & regs[R_CPD]); + tuner_dbg("CAL_DIV_BYTE_1 = 0x%x\n", 0xff & regs[R_CD1]); + tuner_dbg("CAL_DIV_BYTE_2 = 0x%x\n", 0xff & regs[R_CD2]); + tuner_dbg("CAL_DIV_BYTE_3 = 0x%x\n", 0xff & regs[R_CD3]); + tuner_dbg("MAIN_POST_DIV_BYTE = 0x%x\n", 0xff & regs[R_MPD]); + tuner_dbg("MAIN_DIV_BYTE_1 = 0x%x\n", 0xff & regs[R_MD1]); + tuner_dbg("MAIN_DIV_BYTE_2 = 0x%x\n", 0xff & regs[R_MD2]); + tuner_dbg("MAIN_DIV_BYTE_3 = 0x%x\n", 0xff & regs[R_MD3]); +} + +static void tda18271_read_regs(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + unsigned char buf = 0x00; + int ret; + struct i2c_msg msg[] = { + { .addr = priv->i2c_addr, .flags = 0, + .buf = &buf, .len = 1 }, + { .addr = priv->i2c_addr, .flags = I2C_M_RD, + .buf = regs, .len = 16 } + }; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + /* read all registers */ + ret = i2c_transfer(priv->i2c_adap, msg, 2); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + if (ret != 2) + printk("ERROR: %s: i2c_transfer returned: %d\n", + __FUNCTION__, ret); + + if (debug > 1) + tda18271_dump_regs(fe); +} + +static void tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + unsigned char buf[TDA18271_NUM_REGS+1]; + struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, + .buf = buf, .len = len+1 }; + int i, ret; + + BUG_ON((len == 0) || (idx+len > sizeof(buf))); + + buf[0] = idx; + for (i = 1; i <= len; i++) { + buf[i] = regs[idx-1+i]; + } + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + /* write registers */ + ret = i2c_transfer(priv->i2c_adap, &msg, 1); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + if (ret != 1) + printk(KERN_WARNING "ERROR: %s: i2c_transfer returned: %d\n", + __FUNCTION__, ret); +} + +/*---------------------------------------------------------------------*/ + +static void tda18271_init_regs(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + + tda18271_read_regs(fe); + + /* test IR_CAL_OK to see if we need init */ + if ((regs[R_EP1] & 0x08) != 0) + return; + + printk(KERN_INFO "tda18271: initializing registers\n"); + + /* initialize registers */ + regs[R_ID] = 0x83; + regs[R_TM] = 0x08; + regs[R_PL] = 0x80; + regs[R_EP1] = 0xc6; + regs[R_EP2] = 0xdf; + regs[R_EP3] = 0x16; + regs[R_EP4] = 0x60; + regs[R_EP5] = 0x80; + regs[R_CPD] = 0x80; + regs[R_CD1] = 0x00; + regs[R_CD2] = 0x00; + regs[R_CD3] = 0x00; + regs[R_MPD] = 0x00; + regs[R_MD1] = 0x00; + regs[R_MD2] = 0x00; + regs[R_MD3] = 0x00; + regs[R_EB1] = 0xff; + regs[R_EB2] = 0x01; + regs[R_EB3] = 0x84; + regs[R_EB4] = 0x41; + regs[R_EB5] = 0x01; + regs[R_EB6] = 0x84; + regs[R_EB7] = 0x40; + regs[R_EB8] = 0x07; + regs[R_EB9] = 0x00; + regs[R_EB10] = 0x00; + regs[R_EB11] = 0x96; + regs[R_EB12] = 0x0f; + regs[R_EB13] = 0xc1; + regs[R_EB14] = 0x00; + regs[R_EB15] = 0x8f; + regs[R_EB16] = 0x00; + regs[R_EB17] = 0x00; + regs[R_EB18] = 0x00; + regs[R_EB19] = 0x00; + regs[R_EB20] = 0x20; + regs[R_EB21] = 0x33; + regs[R_EB22] = 0x48; + regs[R_EB23] = 0xb0; + + tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS); + /* setup AGC1 & AGC2 */ + regs[R_EB17] = 0x00; + tda18271_write_regs(fe, R_EB17, 1); + regs[R_EB17] = 0x03; + tda18271_write_regs(fe, R_EB17, 1); + regs[R_EB17] = 0x43; + tda18271_write_regs(fe, R_EB17, 1); + regs[R_EB17] = 0x4c; + tda18271_write_regs(fe, R_EB17, 1); + + regs[R_EB20] = 0xa0; + tda18271_write_regs(fe, R_EB20, 1); + regs[R_EB20] = 0xa7; + tda18271_write_regs(fe, R_EB20, 1); + regs[R_EB20] = 0xe7; + tda18271_write_regs(fe, R_EB20, 1); + regs[R_EB20] = 0xec; + tda18271_write_regs(fe, R_EB20, 1); + + /* image rejection calibration */ + + /* low-band */ + regs[R_EP3] = 0x1f; + regs[R_EP4] = 0x66; + regs[R_EP5] = 0x81; + regs[R_CPD] = 0xcc; + regs[R_CD1] = 0x6c; + regs[R_CD2] = 0x00; + regs[R_CD3] = 0x00; + regs[R_MPD] = 0xcd; + regs[R_MD1] = 0x77; + regs[R_MD2] = 0x08; + regs[R_MD3] = 0x00; + + tda18271_write_regs(fe, R_EP3, 11); + msleep(5); /* pll locking */ + + regs[R_EP1] = 0xc6; + tda18271_write_regs(fe, R_EP1, 1); + msleep(5); /* wanted low measurement */ + + regs[R_EP3] = 0x1f; + regs[R_EP4] = 0x66; + regs[R_EP5] = 0x85; + regs[R_CPD] = 0xcb; + regs[R_CD1] = 0x66; + regs[R_CD2] = 0x70; + regs[R_CD3] = 0x00; + + tda18271_write_regs(fe, R_EP3, 7); + msleep(5); /* pll locking */ + + regs[R_EP2] = 0xdf; + tda18271_write_regs(fe, R_EP2, 1); + msleep(30); /* image low optimization completion */ + + /* mid-band */ + regs[R_EP3] = 0x1f; + regs[R_EP4] = 0x66; + regs[R_EP5] = 0x82; + regs[R_CPD] = 0xa8; + regs[R_CD1] = 0x66; + regs[R_CD2] = 0x00; + regs[R_CD3] = 0x00; + regs[R_MPD] = 0xa9; + regs[R_MD1] = 0x73; + regs[R_MD2] = 0x1a; + regs[R_MD3] = 0x00; + + tda18271_write_regs(fe, R_EP3, 11); + msleep(5); /* pll locking */ + + regs[R_EP1] = 0xc6; + tda18271_write_regs(fe, R_EP1, 1); + msleep(5); /* wanted mid measurement */ + + regs[R_EP3] = 0x1f; + regs[R_EP4] = 0x66; + regs[R_EP5] = 0x86; + regs[R_CPD] = 0xa8; + regs[R_CD1] = 0x66; + regs[R_CD2] = 0xa0; + regs[R_CD3] = 0x00; + + tda18271_write_regs(fe, R_EP3, 7); + msleep(5); /* pll locking */ + + regs[R_EP2] = 0xdf; + tda18271_write_regs(fe, R_EP2, 1); + msleep(30); /* image mid optimization completion */ + + /* high-band */ + regs[R_EP3] = 0x1f; + regs[R_EP4] = 0x66; + regs[R_EP5] = 0x83; + regs[R_CPD] = 0x98; + regs[R_CD1] = 0x65; + regs[R_CD2] = 0x00; + regs[R_CD3] = 0x00; + regs[R_MPD] = 0x99; + regs[R_MD1] = 0x71; + regs[R_MD2] = 0xcd; + regs[R_MD3] = 0x00; + + tda18271_write_regs(fe, R_EP3, 11); + msleep(5); /* pll locking */ + + regs[R_EP1] = 0xc6; + tda18271_write_regs(fe, R_EP1, 1); + msleep(5); /* wanted high measurement */ + + regs[R_EP3] = 0x1f; + regs[R_EP4] = 0x66; + regs[R_EP5] = 0x87; + regs[R_CPD] = 0x98; + regs[R_CD1] = 0x65; + regs[R_CD2] = 0x50; + regs[R_CD3] = 0x00; + + tda18271_write_regs(fe, R_EP3, 7); + msleep(5); /* pll locking */ + + regs[R_EP2] = 0xdf; + + tda18271_write_regs(fe, R_EP2, 1); + msleep(30); /* image high optimization completion */ + + regs[R_EP4] = 0x64; + tda18271_write_regs(fe, R_EP4, 1); + + regs[R_EP1] = 0xc6; + tda18271_write_regs(fe, R_EP1, 1); +} + +static int tda18271_tune(struct dvb_frontend *fe, + u32 ifc, u32 freq, u32 bw, u8 std) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + u32 div, N = 0; + int i; + +#if 0 + /* FIXME: FM Radio support */ + if (t->mode == V4L2_TUNER_RADIO) + freq = freq / 1000; +#endif + + tuner_dbg("%s: freq = %d, ifc = %d\n", __FUNCTION__, freq, ifc); + + tda18271_init_regs(fe); + /* RF tracking filter calibration */ + + /* calculate BP_Filter */ + i = 0; + while ((tda18271_bp_filter[i].rfmax * 1000) < freq) { + if (tda18271_bp_filter[i + 1].rfmax == 0) + break; + i++; + } + tuner_extra_dbg("bp filter = 0x%x, i = %d\n", + tda18271_bp_filter[i].val, i); + + regs[R_EP1] &= ~0x07; /* clear bp filter bits */ + regs[R_EP1] |= tda18271_bp_filter[i].val; + tda18271_write_regs(fe, R_EP1, 1); + + regs[R_EB4] &= 0x07; + regs[R_EB4] |= 0x60; + tda18271_write_regs(fe, R_EB4, 1); + + regs[R_EB7] = 0x60; + tda18271_write_regs(fe, R_EB7, 1); + + regs[R_EB14] = 0x00; + tda18271_write_regs(fe, R_EB14, 1); + + regs[R_EB20] = 0xcc; + tda18271_write_regs(fe, R_EB20, 1); + + /* set CAL mode to RF tracking filter calibration */ + regs[R_EB4] |= 0x03; + + /* calculate CAL PLL */ + + switch (priv->mode) { + case TDA18271_ANALOG: + N = freq - 1250000; + break; + case TDA18271_DIGITAL: + N = freq + bw / 2; + break; + } + + i = 0; + while ((tda18271_cal_pll[i].lomax * 1000) < N) { + if (tda18271_cal_pll[i + 1].lomax == 0) + break; + i++; + } + tuner_extra_dbg("cal pll, pd = 0x%x, d = 0x%x, i = %d\n", + tda18271_cal_pll[i].pd, tda18271_cal_pll[i].d, i); + + regs[R_CPD] = tda18271_cal_pll[i].pd; + + div = ((tda18271_cal_pll[i].d * (N / 1000)) << 7) / 125; + regs[R_CD1] = 0xff & (div >> 16); + regs[R_CD2] = 0xff & (div >> 8); + regs[R_CD3] = 0xff & div; + + /* calculate MAIN PLL */ + + switch (priv->mode) { + case TDA18271_ANALOG: + N = freq - 250000; + break; + case TDA18271_DIGITAL: + N = freq + bw / 2 + 1000000; + break; + } + + i = 0; + while ((tda18271_main_pll[i].lomax * 1000) < N) { + if (tda18271_main_pll[i + 1].lomax == 0) + break; + i++; + } + tuner_extra_dbg("main pll, pd = 0x%x, d = 0x%x, i = %d\n", + tda18271_main_pll[i].pd, tda18271_main_pll[i].d, i); + + regs[R_MPD] = (0x7f & tda18271_main_pll[i].pd); + + switch (priv->mode) { + case TDA18271_ANALOG: + regs[R_MPD] &= ~0x08; + break; + case TDA18271_DIGITAL: + regs[R_MPD] |= 0x08; + break; + } + + div = ((tda18271_main_pll[i].d * (N / 1000)) << 7) / 125; + regs[R_MD1] = 0xff & (div >> 16); + regs[R_MD2] = 0xff & (div >> 8); + regs[R_MD3] = 0xff & div; + + tda18271_write_regs(fe, R_EP3, 11); + msleep(5); /* RF tracking filter calibration initialization */ + + /* search for K,M,CO for RF Calibration */ + i = 0; + while ((tda18271_km[i].rfmax * 1000) < freq) { + if (tda18271_km[i + 1].rfmax == 0) + break; + i++; + } + tuner_extra_dbg("km = 0x%x, i = %d\n", tda18271_km[i].val, i); + + regs[R_EB13] &= 0x83; + regs[R_EB13] |= tda18271_km[i].val; + tda18271_write_regs(fe, R_EB13, 1); + + /* search for RF_BAND */ + i = 0; + while ((tda18271_rf_band[i].rfmax * 1000) < freq) { + if (tda18271_rf_band[i + 1].rfmax == 0) + break; + i++; + } + tuner_extra_dbg("rf band = 0x%x, i = %d\n", + tda18271_rf_band[i].val, i); + + regs[R_EP2] &= ~0xe0; /* clear rf band bits */ + regs[R_EP2] |= (tda18271_rf_band[i].val << 5); + + /* search for Gain_Taper */ + i = 0; + while ((tda18271_gain_taper[i].rfmax * 1000) < freq) { + if (tda18271_gain_taper[i + 1].rfmax == 0) + break; + i++; + } + tuner_extra_dbg("gain taper = 0x%x, i = %d\n", + tda18271_gain_taper[i].val, i); + + regs[R_EP2] &= ~0x1f; /* clear gain taper bits */ + regs[R_EP2] |= tda18271_gain_taper[i].val; + + tda18271_write_regs(fe, R_EP2, 1); + tda18271_write_regs(fe, R_EP1, 1); + tda18271_write_regs(fe, R_EP2, 1); + tda18271_write_regs(fe, R_EP1, 1); + + regs[R_EB4] &= 0x07; + regs[R_EB4] |= 0x40; + tda18271_write_regs(fe, R_EB4, 1); + + regs[R_EB7] = 0x40; + tda18271_write_regs(fe, R_EB7, 1); + msleep(10); + + regs[R_EB20] = 0xec; + tda18271_write_regs(fe, R_EB20, 1); + msleep(60); /* RF tracking filter calibration completion */ + + regs[R_EP4] &= ~0x03; /* set cal mode to normal */ + tda18271_write_regs(fe, R_EP4, 1); + + tda18271_write_regs(fe, R_EP1, 1); + + /* RF tracking filer correction for VHF_Low band */ + i = 0; + while ((tda18271_rf_cal[i].rfmax * 1000) < freq) { + if (tda18271_rf_cal[i].rfmax == 0) + break; + i++; + } + tuner_extra_dbg("rf cal = 0x%x, i = %d\n", tda18271_rf_cal[i].val, i); + + /* VHF_Low band only */ + if (tda18271_rf_cal[i].rfmax != 0) { + regs[R_EB14] = tda18271_rf_cal[i].val; + tda18271_write_regs(fe, R_EB14, 1); + } + + /* Channel Configuration */ + + switch (priv->mode) { + case TDA18271_ANALOG: + regs[R_EB22] = 0x2c; + break; + case TDA18271_DIGITAL: + regs[R_EB22] = 0x37; + break; + } + tda18271_write_regs(fe, R_EB22, 1); + + regs[R_EP1] |= 0x40; /* set dis power level on */ + + /* set standard */ + regs[R_EP3] &= ~0x1f; /* clear std bits */ + + /* see table 22 */ + regs[R_EP3] |= std; + + /* TO DO: * + * ================ * + * FM radio, 0x18 * + * ATSC 6MHz, 0x1c * + * DVB-T 6MHz, 0x1c * + * DVB-T 7MHz, 0x1d * + * DVB-T 8MHz, 0x1e * + * QAM 6MHz, 0x1d * + * QAM 8MHz, 0x1f */ + + regs[R_EP4] &= ~0x03; /* set cal mode to normal */ + + regs[R_EP4] &= ~0x1c; /* clear if level bits */ + switch (priv->mode) { + case TDA18271_ANALOG: + regs[R_MPD] &= ~0x80; /* IF notch = 0 */ + break; + case TDA18271_DIGITAL: + regs[R_EP4] |= 0x04; + regs[R_MPD] |= 0x80; + break; + } + + regs[R_EP4] &= ~0x80; /* turn this bit on only for fm */ + + /* FIXME: image rejection validity EP5[2:0] */ + + /* calculate MAIN PLL */ + N = freq + ifc; + + i = 0; + while ((tda18271_main_pll[i].lomax * 1000) < N) { + if (tda18271_main_pll[i + 1].lomax == 0) + break; + i++; + } + tuner_extra_dbg("main pll, pd = 0x%x, d = 0x%x, i = %d\n", + tda18271_main_pll[i].pd, tda18271_main_pll[i].d, i); + + regs[R_MPD] = (0x7f & tda18271_main_pll[i].pd); + switch (priv->mode) { + case TDA18271_ANALOG: + regs[R_MPD] &= ~0x08; + break; + case TDA18271_DIGITAL: + regs[R_MPD] |= 0x08; + break; + } + + div = ((tda18271_main_pll[i].d * (N / 1000)) << 7) / 125; + regs[R_MD1] = 0xff & (div >> 16); + regs[R_MD2] = 0xff & (div >> 8); + regs[R_MD3] = 0xff & div; + + tda18271_write_regs(fe, R_TM, 15); + msleep(5); +#if 0 + tda18271_read_regs(fe); +#endif + return 0; +} + +/* ------------------------------------------------------------------ */ + +static int tda18271_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct tda18271_priv *priv = fe->tuner_priv; + u8 std; + u32 bw, sgIF = 0; + + u32 freq = params->frequency; + + priv->mode = TDA18271_DIGITAL; + + /* see table 22 */ + if (fe->ops.info.type == FE_ATSC) { + switch (params->u.vsb.modulation) { + case VSB_8: + case VSB_16: + std = 0x1b; /* device-specific (spec says 0x1c) */ + sgIF = 5380000; + break; + case QAM_64: + case QAM_256: + std = 0x18; /* device-specific (spec says 0x1d) */ + sgIF = 4000000; + break; + default: + printk(KERN_WARNING "%s: modulation not set!\n", + __FUNCTION__); + return -EINVAL; + } + freq += 1750000; /* Adjust to center (+1.75MHZ) */ + bw = 6000000; + } else if (fe->ops.info.type == FE_OFDM) { + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + std = 0x1c; + bw = 6000000; + break; + case BANDWIDTH_7_MHZ: + std = 0x1d; + bw = 7000000; + break; + case BANDWIDTH_8_MHZ: + std = 0x1e; + bw = 8000000; + break; + default: + printk(KERN_WARNING "%s: bandwidth not set!\n", + __FUNCTION__); + return -EINVAL; + } + } else { + printk(KERN_WARNING "%s: modulation type not supported!\n", + __FUNCTION__); + return -EINVAL; + } + + return tda18271_tune(fe, sgIF, freq, bw, std); +} + +static int tda18271_set_analog_params(struct dvb_frontend *fe, + struct analog_parameters *params) +{ + struct tda18271_priv *priv = fe->tuner_priv; + u8 std; + unsigned int sgIF; + char *mode; + + priv->mode = TDA18271_ANALOG; + + /* see table 22 */ + if (params->std & V4L2_STD_MN) { + std = 0x0d; + sgIF = 92; + mode = "MN"; + } else if (params->std & V4L2_STD_B) { + std = 0x0e; + sgIF = 108; + mode = "B"; + } else if (params->std & V4L2_STD_GH) { + std = 0x0f; + sgIF = 124; + mode = "GH"; + } else if (params->std & V4L2_STD_PAL_I) { + std = 0x0f; + sgIF = 124; + mode = "I"; + } else if (params->std & V4L2_STD_DK) { + std = 0x0f; + sgIF = 124; + mode = "DK"; + } else if (params->std & V4L2_STD_SECAM_L) { + std = 0x0f; + sgIF = 124; + mode = "L"; + } else if (params->std & V4L2_STD_SECAM_LC) { + std = 0x0f; + sgIF = 20; + mode = "LC"; + } else { + std = 0x0f; + sgIF = 124; + mode = "xx"; + } + + if (params->mode == V4L2_TUNER_RADIO) + sgIF = 88; /* if frequency is 5.5 MHz */ + + tuner_dbg("setting tda18271 to system %s\n", mode); + + return tda18271_tune(fe, sgIF * 62500, params->frequency * 62500, + 0, std); +} + +static int tda18271_release(struct dvb_frontend *fe) +{ + kfree(fe->tuner_priv); + fe->tuner_priv = NULL; + return 0; +} + +static int tda18271_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct tda18271_priv *priv = fe->tuner_priv; + *frequency = priv->frequency; + return 0; +} + +static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) +{ + struct tda18271_priv *priv = fe->tuner_priv; + *bandwidth = priv->bandwidth; + return 0; +} + +static struct dvb_tuner_ops tda18271_tuner_ops = { + .info = { + .name = "NXP TDA18271HD", + .frequency_min = 45000000, + .frequency_max = 864000000, + .frequency_step = 62500 + }, + .set_params = tda18271_set_params, + .set_analog_params = tda18271_set_analog_params, + .release = tda18271_release, + .get_frequency = tda18271_get_frequency, + .get_bandwidth = tda18271_get_bandwidth, +}; + +struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, + struct i2c_adapter *i2c) +{ + struct tda18271_priv *priv = NULL; + + tuner_dbg("%s:\n", __FUNCTION__); + priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL); + if (priv == NULL) + return NULL; + + priv->i2c_addr = addr; + priv->i2c_adap = i2c; + + memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops, + sizeof(struct dvb_tuner_ops)); + + fe->tuner_priv = priv; + + return fe; +} +EXPORT_SYMBOL_GPL(tda18271_attach); +MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver"); +MODULE_AUTHOR("Michael Krufky "); +MODULE_LICENSE("GPL"); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/linux/drivers/media/dvb/frontends/tda18271.h b/linux/drivers/media/dvb/frontends/tda18271.h new file mode 100644 index 000000000..a8a19a719 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/tda18271.h @@ -0,0 +1,40 @@ +/* + tda18271.h - header for the Philips / NXP TDA18271 silicon tuner + + Copyright (C) 2007 Michael Krufky (mkrufky@linuxtv.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __TDA18271_H__ +#define __TDA18271_H__ + +#include +#include "dvb_frontend.h" + +#if defined(CONFIG_DVB_TDA18271) || (defined(CONFIG_DVB_TDA18271_MODULE) && defined(MODULE)) +extern struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, + struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, + u8 addr, + struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif + +#endif /* __TDA18271_H__ */ diff --git a/linux/drivers/media/video/tda8290.c b/linux/drivers/media/video/tda8290.c index 882872720..701ea6a96 100644 --- a/linux/drivers/media/video/tda8290.c +++ b/linux/drivers/media/video/tda8290.c @@ -26,6 +26,7 @@ #include #include "tda8290.h" #include "tda827x.h" +#include "tda18271.h" #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "i2c-compat.h" #endif @@ -34,7 +35,7 @@ static int debug = 0; module_param(debug, int, 0644); #else -static int tuner_debug = 0; +static int tuner_debug; module_param_named(debug, tuner_debug, int, 0644); #endif MODULE_PARM_DESC(debug, "enable verbose debug messages"); @@ -74,6 +75,54 @@ static void tda8290_i2c_bridge(struct tuner *t, int close) } } +#if 1 +static void tda8295_i2c_bridge(struct tuner *t, int close) +{ + struct tda8290_priv *priv = t->priv; + + unsigned char enable[2] = { 0x45, 0xc1 }; + unsigned char disable[2] = { 0x46, 0x00 }; + unsigned char buf[3] = { 0x45, 0x01, 0x00 }; + unsigned char *msg; + if (close) { + msg = enable; + tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); + /* let the bridge stabilize */ + msleep(20); + } else { + msg = disable; + tuner_i2c_xfer_send(&priv->i2c_props, msg, 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &msg[1], 1); + + buf[2] = msg[1]; + buf[2] &= ~0x04; + tuner_i2c_xfer_send(&priv->i2c_props, buf, 3); + msleep(5); + + msg[1] |= 0x04; + tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); + } +} +#else +static void tda8295_i2c_bridge(struct tuner *t, int close) +{ + struct tda8290_priv *priv = t->priv; + + unsigned char buf[] = { 0x45, 0x00 }; + + tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1); + + buf[1] &= 0x3f; + if (close) + buf[1] |= 0xc0; + else + buf[1] |= 0x80; + + tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); +} +#endif + /*---------------------------------------------------------------------*/ static void set_audio(struct tuner *t) @@ -242,6 +291,153 @@ static void tda8290_set_freq(struct tuner *t, unsigned int freq) /*---------------------------------------------------------------------*/ +static void tda8295_power(struct tuner *t, int enable) +{ + struct tda8290_priv *priv = t->priv; + unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */ + + tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1); + + if (enable) + buf[1] = 0x01; + else + buf[1] = 0x03; + + tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); +} + +static void tda8295_set_easy_mode(struct tuner *t, int enable) +{ + struct tda8290_priv *priv = t->priv; + unsigned char buf[] = { 0x01, 0x00 }; + + tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1); + + if (enable) + buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */ + else + buf[1] = 0x00; /* reset active bit */ + + tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); +} + +static void tda8295_set_video_std(struct tuner *t) +{ + struct tda8290_priv *priv = t->priv; + unsigned char buf[] = { 0x00, priv->tda8290_easy_mode }; + + tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); + + tda8295_set_easy_mode(t, 1); + msleep(20); + tda8295_set_easy_mode(t, 0); +} + +/*---------------------------------------------------------------------*/ + +static void tda8295_agc1_out(struct tuner *t, int enable) +{ + struct tda8290_priv *priv = t->priv; + unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */ + + tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1); + + if (enable) + buf[1] &= ~0x40; + else + buf[1] |= 0x40; + + tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); +} + +static void tda8295_agc2_out(struct tuner *t, int enable) +{ + struct tda8290_priv *priv = t->priv; + unsigned char set_gpio_cf[] = { 0x44, 0x00 }; + unsigned char set_gpio_val[] = { 0x46, 0x00 }; + + tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_cf[0], 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_cf[1], 1); + tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_val[0], 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_val[1], 1); + + set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */ + + if (enable) { + set_gpio_cf[1] |= 0x01; /* config GPIO_0 as Open Drain Out */ + set_gpio_val[1] &= 0xfe; /* set GPIO_0 pin low */ + } + tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_cf, 2); + tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_val, 2); +} + +static int tda8295_has_signal(struct tuner *t) +{ + struct tda8290_priv *priv = t->priv; + + unsigned char hvpll_stat = 0x26; + unsigned char ret; + + tuner_i2c_xfer_send(&priv->i2c_props, &hvpll_stat, 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &ret, 1); + return (ret & 0x01) ? 65535 : 0; +} + +/*---------------------------------------------------------------------*/ + +static void tda8295_set_freq(struct tuner *t, unsigned int freq) +{ + struct tda8290_priv *priv = t->priv; + u16 ifc; + + unsigned char blanking_mode[] = { 0x1d, 0x00 }; + + struct analog_parameters params = { + .frequency = freq, + .mode = t->mode, + .audmode = t->audmode, + .std = t->std + }; + + set_audio(t); + + ifc = priv->cfg.sgIF; /* FIXME */ + + tuner_dbg("%s: ifc = %u, freq = %d\n", __FUNCTION__, ifc, freq); + + tda8295_power(t, 1); + tda8295_agc1_out(t, 1); + + tuner_i2c_xfer_send(&priv->i2c_props, &blanking_mode[0], 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &blanking_mode[1], 1); + + tda8295_set_video_std(t); + + blanking_mode[1] = 0x03; + tuner_i2c_xfer_send(&priv->i2c_props, blanking_mode, 2); + msleep(20); + + tda8295_i2c_bridge(t, 1); + + if (t->fe.ops.tuner_ops.set_analog_params) + t->fe.ops.tuner_ops.set_analog_params(&t->fe, ¶ms); + + if (priv->cfg.agcf) + priv->cfg.agcf(&t->fe); + + if (tda8295_has_signal(t)) + tuner_dbg("tda8295 is locked\n"); + else + tuner_dbg("tda8295 not locked, no signal?\n"); + + tda8295_i2c_bridge(t, 0); +} + +/*---------------------------------------------------------------------*/ + static int tda8290_has_signal(struct tuner *t) { struct tda8290_priv *priv = t->priv; @@ -273,6 +469,13 @@ static void tda8290_standby(struct tuner *t) tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2); } +static void tda8295_standby(struct tuner *t) +{ + tda8295_agc1_out(t, 0); /* Put AGC in tri-state */ + + tda8295_power(t, 0); +} + static void tda8290_init_if(struct tuner *t) { struct tda8290_priv *priv = t->priv; @@ -288,6 +491,35 @@ static void tda8290_init_if(struct tuner *t) tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2); } +static void tda8295_init_if(struct tuner *t) +{ + struct tda8290_priv *priv = t->priv; + + static unsigned char set_adc_ctl[] = { 0x33, 0x14 }; + static unsigned char set_adc_ctl2[] = { 0x34, 0x00 }; + static unsigned char set_pll_reg6[] = { 0x3e, 0x63 }; + static unsigned char set_pll_reg0[] = { 0x38, 0x23 }; + static unsigned char set_pll_reg7[] = { 0x3f, 0x01 }; + static unsigned char set_pll_reg10[] = { 0x42, 0x61 }; + static unsigned char set_gpio_reg0[] = { 0x44, 0x0b }; + + tda8295_power(t, 1); + + tda8295_set_easy_mode(t, 0); + tda8295_set_video_std(t); + + tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl, 2); + tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl2, 2); + tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg6, 2); + tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg0, 2); + tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg7, 2); + tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg10, 2); + tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_reg0, 2); + + tda8295_agc1_out(t, 0); + tda8295_agc2_out(t, 0); +} + static void tda8290_init_tuner(struct tuner *t) { struct tda8290_priv *priv = t->priv; @@ -307,7 +539,7 @@ static void tda8290_init_tuner(struct tuner *t) /*---------------------------------------------------------------------*/ -static void tda8290_release(struct tuner *t) +static void tda829x_release(struct tuner *t) { if (t->fe.ops.tuner_ops.release) t->fe.ops.tuner_ops.release(&t->fe); @@ -321,7 +553,15 @@ static struct tuner_operations tda8290_tuner_ops = { .set_radio_freq = tda8290_set_freq, .has_signal = tda8290_has_signal, .standby = tda8290_standby, - .release = tda8290_release, + .release = tda829x_release, +}; + +static struct tuner_operations tda8295_tuner_ops = { + .set_tv_freq = tda8295_set_freq, + .set_radio_freq = tda8295_set_freq, + .has_signal = tda8295_has_signal, + .standby = tda8295_standby, + .release = tda829x_release, }; int tda8290_attach(struct tuner *t) @@ -412,6 +652,95 @@ int tda8290_attach(struct tuner *t) tda8290_init_if(t); return 0; } +EXPORT_SYMBOL_GPL(tda8290_attach); + +int tda8295_attach(struct tuner *t) +{ + struct tda8290_priv *priv = NULL; + u8 data; + int i, ret, tuners_found; + u32 tuner_addrs; + struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 }; + + priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + t->priv = priv; + + priv->i2c_props.addr = t->i2c.addr; + priv->i2c_props.adap = t->i2c.adapter; + + tda8295_i2c_bridge(t, 1); + /* probe for tuner chip */ + tuners_found = 0; + tuner_addrs = 0; + for (i = 0x60; i <= 0x63; i++) { + msg.addr = i; + ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); + if (ret == 1) { + tuners_found++; + tuner_addrs = (tuner_addrs << 8) + i; + } + } + /* if there is more than one tuner, we expect the right one is + behind the bridge and we choose the highest address that doesn't + give a response now + */ + tda8295_i2c_bridge(t, 0); + if (tuners_found > 1) + for (i = 0; i < tuners_found; i++) { + msg.addr = tuner_addrs & 0xff; + ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); + if (ret == 1) + tuner_addrs = tuner_addrs >> 8; + else + break; + } + if (tuner_addrs == 0) { + tuner_addrs = 0x60; + tuner_info("could not clearly identify tuner address, " + "defaulting to %x\n", tuner_addrs); + } else { + tuner_addrs = tuner_addrs & 0xff; + tuner_info("setting tuner address to %x\n", tuner_addrs); + } + priv->tda827x_addr = tuner_addrs; + msg.addr = tuner_addrs; + + tda8295_i2c_bridge(t, 1); + ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); + tda8295_i2c_bridge(t, 0); + if (ret != 1) + tuner_warn("TDA827x access failed!\n"); + if ((data & 0x3c) == 0) { + strlcpy(t->i2c.name, "tda8295+18271", sizeof(t->i2c.name)); + tda18271_attach(&t->fe, priv->tda827x_addr, + priv->i2c_props.adap); + priv->tda827x_ver = 4; + } else { + strlcpy(t->i2c.name, "tda8295+75a", sizeof(t->i2c.name)); + tda827x_attach(&t->fe, priv->tda827x_addr, + priv->i2c_props.adap, &priv->cfg); + + /* FIXME: tda827x module doesn't probe the tuner until + * tda827x_initial_sleep is called + */ + if (t->fe.ops.tuner_ops.sleep) + t->fe.ops.tuner_ops.sleep(&t->fe); + priv->tda827x_ver = 2; + } + priv->tda827x_ver |= 1; /* signifies 8295 vs 8290 */ + tuner_info("type set to %s\n", t->i2c.name); + + memcpy(&t->ops, &tda8295_tuner_ops, sizeof(struct tuner_operations)); + + priv->cfg.tda827x_lpsel = 0; + t->mode = V4L2_TUNER_ANALOG_TV; + + tda8295_init_if(t); + return 0; +} +EXPORT_SYMBOL_GPL(tda8295_attach); int tda8290_probe(struct tuner *t) { @@ -443,12 +772,10 @@ int tda8290_probe(struct tuner *t) tuner_i2c_xfer_send(&i2c_props, restore_9886, 3); return -1; } - EXPORT_SYMBOL_GPL(tda8290_probe); -EXPORT_SYMBOL_GPL(tda8290_attach); MODULE_DESCRIPTION("Philips TDA8290 + TDA8275 / TDA8275a tuner driver"); -MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann"); +MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky"); MODULE_LICENSE("GPL"); /* diff --git a/linux/drivers/media/video/tda8290.h b/linux/drivers/media/video/tda8290.h index 9b63e62b3..dbbcb0f00 100644 --- a/linux/drivers/media/video/tda8290.h +++ b/linux/drivers/media/video/tda8290.h @@ -24,6 +24,7 @@ extern int tda8290_probe(struct tuner *t); extern int tda8290_attach(struct tuner *t); +extern int tda8295_attach(struct tuner *t); #else static inline int tda8290_probe(struct tuner *t) { @@ -37,6 +38,13 @@ static inline int tda8290_attach(struct tuner *t) __FUNCTION__); return -EINVAL; } + +static inline int tda8295_attach(struct tuner *t) +{ + printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", + __FUNCTION__); + return -EINVAL; +} #endif #endif /* __TDA8290_H__ */ diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index b02a18cd7..e528435f5 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -305,6 +305,11 @@ static void set_type(struct i2c_client *c, unsigned int type, tda8290_attach(t); break; } + case TUNER_PHILIPS_TDA8295: + { + tda8295_attach(t); + break; + } case TUNER_TEA5767: if (tea5767_attach(&t->fe, t->i2c.adapter, t->i2c.addr) == NULL) { t->type = TUNER_ABSENT; diff --git a/linux/drivers/media/video/tuner-types.c b/linux/drivers/media/video/tuner-types.c index ff8b72854..c1746464e 100644 --- a/linux/drivers/media/video/tuner-types.c +++ b/linux/drivers/media/video/tuner-types.c @@ -1523,6 +1523,9 @@ struct tunertype tuners[] = { .name = "Philips TEA5761 FM Radio", /* see tea5767.c for details */ }, + [TUNER_PHILIPS_TDA8295] = { /* Philips PAL|NTSC */ + .name = "tda8295+18271", + /* see tda8290.c for details */ }, }; unsigned const int tuner_count = ARRAY_SIZE(tuners); diff --git a/linux/drivers/media/video/tveeprom.c b/linux/drivers/media/video/tveeprom.c index cfc752271..c3a67eba2 100644 --- a/linux/drivers/media/video/tveeprom.c +++ b/linux/drivers/media/video/tveeprom.c @@ -261,7 +261,7 @@ hauppauge_tuner[] = { TUNER_ABSENT, "LG TAPQ_H702F"}, { TUNER_ABSENT, "TCL M09WPP_4N_E"}, { TUNER_ABSENT, "MaxLinear MXL5005_v2"}, - { TUNER_ABSENT, "Philips 18271_8295"}, + { TUNER_PHILIPS_TDA8295, "Philips 18271_8295"}, }; static struct HAUPPAUGE_AUDIOIC -- cgit v1.2.3 From e49bb6b1caf8169505d2d84a8181d77c6d3f9acf Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 21 Oct 2007 12:40:56 -0400 Subject: tuner: move analog_tuner_ops into dvb_frontend_ops From: Michael Krufky Signed-off-by: Michael Krufky Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-core/dvb_frontend.h | 3 linux/drivers/media/video/tda8290.c | 8 +- linux/drivers/media/video/tda9887.c | 4 - linux/drivers/media/video/tuner-core.c | 91 +++++++++++++----------- linux/drivers/media/video/tuner-driver.h | 4 - 5 files changed, 63 insertions(+), 47 deletions(-) --- linux/drivers/media/dvb/dvb-core/dvb_frontend.h | 3 + linux/drivers/media/video/tda8290.c | 8 +-- linux/drivers/media/video/tda9887.c | 4 +- linux/drivers/media/video/tuner-core.c | 91 ++++++++++++++----------- linux/drivers/media/video/tuner-driver.h | 4 +- 5 files changed, 63 insertions(+), 47 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h index d6e90cec7..86ca54413 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -64,6 +64,8 @@ struct dvb_tuner_info { u32 bandwidth_step; }; +struct analog_tuner_ops; + struct analog_parameters { unsigned int frequency; unsigned int mode; @@ -148,6 +150,7 @@ struct dvb_frontend_ops { int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire); struct dvb_tuner_ops tuner_ops; + struct analog_tuner_ops *analog_demod_ops; }; #define MAX_EVENT 8 diff --git a/linux/drivers/media/video/tda8290.c b/linux/drivers/media/video/tda8290.c index 701ea6a96..6bc67eebd 100644 --- a/linux/drivers/media/video/tda8290.c +++ b/linux/drivers/media/video/tda8290.c @@ -548,7 +548,7 @@ static void tda829x_release(struct tuner *t) t->priv = NULL; } -static struct tuner_operations tda8290_tuner_ops = { +static struct analog_tuner_ops tda8290_tuner_ops = { .set_tv_freq = tda8290_set_freq, .set_radio_freq = tda8290_set_freq, .has_signal = tda8290_has_signal, @@ -556,7 +556,7 @@ static struct tuner_operations tda8290_tuner_ops = { .release = tda829x_release, }; -static struct tuner_operations tda8295_tuner_ops = { +static struct analog_tuner_ops tda8295_tuner_ops = { .set_tv_freq = tda8295_set_freq, .set_radio_freq = tda8295_set_freq, .has_signal = tda8295_has_signal, @@ -641,7 +641,7 @@ int tda8290_attach(struct tuner *t) if (t->fe.ops.tuner_ops.sleep) t->fe.ops.tuner_ops.sleep(&t->fe); - memcpy(&t->ops, &tda8290_tuner_ops, sizeof(struct tuner_operations)); + t->fe.ops.analog_demod_ops = &tda8290_tuner_ops; tuner_info("type set to %s\n", t->i2c.name); @@ -732,7 +732,7 @@ int tda8295_attach(struct tuner *t) priv->tda827x_ver |= 1; /* signifies 8295 vs 8290 */ tuner_info("type set to %s\n", t->i2c.name); - memcpy(&t->ops, &tda8295_tuner_ops, sizeof(struct tuner_operations)); + t->fe.ops.analog_demod_ops = &tda8295_tuner_ops; priv->cfg.tda827x_lpsel = 0; t->mode = V4L2_TUNER_ANALOG_TV; diff --git a/linux/drivers/media/video/tda9887.c b/linux/drivers/media/video/tda9887.c index 5baceca55..41488e4f4 100644 --- a/linux/drivers/media/video/tda9887.c +++ b/linux/drivers/media/video/tda9887.c @@ -621,7 +621,7 @@ static void tda9887_release(struct tuner *t) t->priv = NULL; } -static struct tuner_operations tda9887_tuner_ops = { +static struct analog_tuner_ops tda9887_tuner_ops = { .set_tv_freq = tda9887_set_freq, .set_radio_freq = tda9887_set_freq, .standby = tda9887_standby, @@ -647,7 +647,7 @@ int tda9887_tuner_init(struct tuner *t) tda9887_info("tda988[5/6/7] found @ 0x%x (%s)\n", t->i2c.addr, t->i2c.driver->driver.name); - memcpy(&t->ops, &tda9887_tuner_ops, sizeof(struct tuner_operations)); + t->fe.ops.analog_demod_ops = &tda9887_tuner_ops; return 0; } diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index e528435f5..23abb715b 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -147,16 +147,28 @@ static int fe_has_signal(struct tuner *t) return strength; } +static void tuner_status(struct tuner *t); + +static struct analog_tuner_ops tuner_core_ops = { + .set_tv_freq = fe_set_freq, + .set_radio_freq = fe_set_freq, + .standby = fe_standby, + .release = fe_release, + .has_signal = fe_has_signal, + .tuner_status = tuner_status +}; + /* 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); + struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; if (t->type == UNSET) { tuner_warn ("tuner type not set\n"); return; } - if (NULL == t->ops.set_tv_freq) { + if ((NULL == ops) || (NULL == ops->set_tv_freq)) { tuner_warn ("Tuner has no way to set tv freq\n"); return; } @@ -171,18 +183,19 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) else freq = tv_range[1] * 16; } - t->ops.set_tv_freq(t, freq); + ops->set_tv_freq(t, freq); } static void set_radio_freq(struct i2c_client *c, unsigned int freq) { struct tuner *t = i2c_get_clientdata(c); + struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; if (t->type == UNSET) { tuner_warn ("tuner type not set\n"); return; } - if (NULL == t->ops.set_radio_freq) { + if ((NULL == ops) || (NULL == ops->set_radio_freq)) { tuner_warn ("tuner has no way to set radio frequency\n"); return; } @@ -198,7 +211,7 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq) freq = radio_range[1] * 16000; } - t->ops.set_radio_freq(t, freq); + ops->set_radio_freq(t, freq); } static void set_freq(struct i2c_client *c, unsigned long freq) @@ -260,6 +273,7 @@ static void set_type(struct i2c_client *c, unsigned int type, { struct tuner *t = i2c_get_clientdata(c); struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; + struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; unsigned char buffer[4]; if (type == UNSET || type == TUNER_ABSENT) { @@ -289,8 +303,8 @@ static void set_type(struct i2c_client *c, unsigned int type, #endif /* discard private data, in case set_type() was previously called */ - if (t->ops.release) - t->ops.release(t); + if ((ops) && (ops->release)) + ops->release(t); else { kfree(t->priv); t->priv = NULL; @@ -366,15 +380,12 @@ static void set_type(struct i2c_client *c, unsigned int type, break; } - if ((fe_tuner_ops->set_analog_params) && - ((NULL == t->ops.set_tv_freq) && (NULL == t->ops.set_radio_freq))) { + if (((NULL == ops) || + ((NULL == ops->set_tv_freq) && (NULL == ops->set_radio_freq))) && + (fe_tuner_ops->set_analog_params)) { strlcpy(t->i2c.name, fe_tuner_ops->info.name, sizeof(t->i2c.name)); - t->ops.set_tv_freq = fe_set_freq; - t->ops.set_radio_freq = fe_set_freq; - t->ops.standby = fe_standby; - t->ops.release = fe_release; - t->ops.has_signal = fe_has_signal; + t->fe.ops.analog_demod_ops = &tuner_core_ops; } tuner_info("type set to %s\n", t->i2c.name); @@ -560,6 +571,7 @@ static void tuner_status(struct tuner *t) { unsigned long freq, freq_fraction; struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; + struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; const char *p; switch (t->mode) { @@ -589,11 +601,11 @@ static void tuner_status(struct tuner *t) if (tuner_status & TUNER_STATUS_STEREO) tuner_info("Stereo: yes\n"); } - if (t->ops.has_signal) { - tuner_info("Signal strength: %d\n", t->ops.has_signal(t)); + if ((ops) && (ops->has_signal)) { + tuner_info("Signal strength: %d\n", ops->has_signal(t)); } - if (t->ops.is_stereo) { - tuner_info("Stereo: %s\n", t->ops.is_stereo(t) ? "yes" : "no"); + if ((ops) && (ops->is_stereo)) { + tuner_info("Stereo: %s\n", ops->is_stereo(t) ? "yes" : "no"); } } @@ -625,7 +637,6 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, t->type = UNSET; t->audmode = V4L2_TUNER_MODE_STEREO; t->mode_mask = T_UNINITIALIZED; - t->ops.tuner_status = tuner_status; if (show_i2c) { unsigned char buffer[16]; @@ -750,6 +761,7 @@ static int tuner_probe(struct i2c_adapter *adap) static int tuner_detach(struct i2c_client *client) { struct tuner *t = i2c_get_clientdata(client); + struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; int err; err = i2c_detach_client(&t->i2c); @@ -762,8 +774,8 @@ static int tuner_detach(struct i2c_client *client) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) MOD_DEC_USE_COUNT; #endif - if (t->ops.release) - t->ops.release(t); + if ((ops) && (ops->release)) + ops->release(t); else { kfree(t->priv); #if 0 @@ -783,6 +795,8 @@ MOD_DEC_USE_COUNT; static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, char *cmd) { + struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; + if (mode == t->mode) return 0; @@ -790,8 +804,8 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, if (check_mode(t, cmd) == EINVAL) { t->mode = T_STANDBY; - if (t->ops.standby) - t->ops.standby(t); + if ((ops) && (ops->standby)) + ops->standby(t); return EINVAL; } return 0; @@ -820,6 +834,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct tuner *t = i2c_get_clientdata(client); struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; + struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; if (tuner_debug>1) v4l_i2c_print_ioctl(&(t->i2c),cmd); @@ -846,8 +861,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL) return 0; t->mode = T_STANDBY; - if (t->ops.standby) - t->ops.standby(t); + if ((ops) && (ops->standby)) + ops->standby(t); break; #ifdef CONFIG_VIDEO_V4L1 case VIDIOCSAUDIO: @@ -915,8 +930,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) else vt->flags &= ~VIDEO_TUNER_STEREO_ON; } else { - if (t->ops.is_stereo) { - if (t->ops.is_stereo(t)) + if ((ops) && (ops->is_stereo)) { + if (ops->is_stereo(t)) vt->flags |= VIDEO_TUNER_STEREO_ON; else @@ -924,8 +939,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) ~VIDEO_TUNER_STEREO_ON; } } - if (t->ops.has_signal) - vt->signal = t->ops.has_signal(t); + if ((ops) && (ops->has_signal)) + vt->signal = ops->has_signal(t); vt->flags |= VIDEO_TUNER_LOW; /* Allow freqs at 62.5 Hz */ @@ -955,8 +970,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) fe_tuner_ops->get_status(&t->fe, &tuner_status); va->mode = (tuner_status & TUNER_STATUS_STEREO) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; - } else if (t->ops.is_stereo) - va->mode = t->ops.is_stereo(t) + } else if ((ops) && (ops->is_stereo)) + va->mode = ops->is_stereo(t) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; } return 0; @@ -1046,8 +1061,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) switch_v4l2(); tuner->type = t->mode; - if (t->ops.get_afc) - tuner->afc=t->ops.get_afc(t); + if ((ops) && (ops->get_afc)) + tuner->afc = ops->get_afc(t); if (t->mode == V4L2_TUNER_ANALOG_TV) tuner->capability |= V4L2_TUNER_CAP_NORM; if (t->mode != V4L2_TUNER_RADIO) { @@ -1066,13 +1081,13 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) tuner->rxsubchans = (tuner_status & TUNER_STATUS_STEREO) ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; } else { - if (t->ops.is_stereo) { - tuner->rxsubchans = t->ops.is_stereo(t) ? + if ((ops) && (ops->is_stereo)) { + tuner->rxsubchans = ops->is_stereo(t) ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; } } - if (t->ops.has_signal) - tuner->signal = t->ops.has_signal(t); + if ((ops) && (ops->has_signal)) + tuner->signal = ops->has_signal(t); tuner->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; tuner->audmode = t->audmode; @@ -1097,8 +1112,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } case VIDIOC_LOG_STATUS: - if (t->ops.tuner_status) - t->ops.tuner_status(t); + if ((ops) && (ops->tuner_status)) + ops->tuner_status(t); break; } diff --git a/linux/drivers/media/video/tuner-driver.h b/linux/drivers/media/video/tuner-driver.h index 9da949b25..430141337 100644 --- a/linux/drivers/media/video/tuner-driver.h +++ b/linux/drivers/media/video/tuner-driver.h @@ -31,7 +31,7 @@ extern unsigned const int tuner_count; struct tuner; -struct tuner_operations { +struct analog_tuner_ops { void (*set_tv_freq)(struct tuner *t, unsigned int freq); void (*set_radio_freq)(struct tuner *t, unsigned int freq); int (*has_signal)(struct tuner *t); @@ -66,8 +66,6 @@ struct tuner { unsigned int config; int (*tuner_callback) (void *dev, int command,int arg); - - struct tuner_operations ops; }; /* ------------------------------------------------------------------------ */ -- cgit v1.2.3 From af382f57965a976afc138a6d59f64a7ee1ae4485 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 21 Oct 2007 13:35:21 -0400 Subject: tuner: clear analog_demod_ops on release From: Michael Krufky Clear analog_demod_ops on release. Fix test for analog_demod_ops after tuner attach. Signed-off-by: Michael Krufky Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-core.c | 4 ++++ 1 file changed, 4 insertions(+) --- linux/drivers/media/video/tuner-core.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 23abb715b..b6de9fecb 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -126,6 +126,8 @@ static void fe_release(struct tuner *t) if (fe_tuner_ops->release) fe_tuner_ops->release(&t->fe); + + t->fe.ops.analog_demod_ops = NULL; } static void fe_standby(struct tuner *t) @@ -380,6 +382,8 @@ static void set_type(struct i2c_client *c, unsigned int type, break; } + ops = t->fe.ops.analog_demod_ops; + if (((NULL == ops) || ((NULL == ops->set_tv_freq) && (NULL == ops->set_radio_freq))) && (fe_tuner_ops->set_analog_params)) { -- cgit v1.2.3 From 7546de2f97f5d0ce1c30c79aa289f39ae014681b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 21 Oct 2007 14:22:25 -0400 Subject: tuner: move analog_demod_priv into struct dvb_frontend From: Michael Krufky Signed-off-by: Michael Krufky Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-core/dvb_frontend.h | 1 linux/drivers/media/video/tda8290.c | 40 ++++++++++++------------ linux/drivers/media/video/tda9887.c | 14 ++++---- linux/drivers/media/video/tuner-core.c | 11 ------ linux/drivers/media/video/tuner-driver.h | 1 5 files changed, 29 insertions(+), 38 deletions(-) --- linux/drivers/media/dvb/dvb-core/dvb_frontend.h | 1 + linux/drivers/media/video/tda8290.c | 40 ++++++++++++------------- linux/drivers/media/video/tda9887.c | 14 ++++----- linux/drivers/media/video/tuner-core.c | 11 +------ linux/drivers/media/video/tuner-driver.h | 1 - 5 files changed, 29 insertions(+), 38 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h index 86ca54413..204994a60 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -175,6 +175,7 @@ struct dvb_frontend { void* tuner_priv; void* frontend_priv; void* sec_priv; + void* analog_demod_priv; }; extern int dvb_register_frontend(struct dvb_adapter* dvb, diff --git a/linux/drivers/media/video/tda8290.c b/linux/drivers/media/video/tda8290.c index 6bc67eebd..2d6b55ead 100644 --- a/linux/drivers/media/video/tda8290.c +++ b/linux/drivers/media/video/tda8290.c @@ -59,7 +59,7 @@ struct tda8290_priv { static void tda8290_i2c_bridge(struct tuner *t, int close) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char enable[2] = { 0x21, 0xC0 }; unsigned char disable[2] = { 0x21, 0x00 }; @@ -78,7 +78,7 @@ static void tda8290_i2c_bridge(struct tuner *t, int close) #if 1 static void tda8295_i2c_bridge(struct tuner *t, int close) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char enable[2] = { 0x45, 0xc1 }; unsigned char disable[2] = { 0x46, 0x00 }; @@ -127,7 +127,7 @@ static void tda8295_i2c_bridge(struct tuner *t, int close) static void set_audio(struct tuner *t) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; char* mode; priv->cfg.tda827x_lpsel = 0; @@ -174,7 +174,7 @@ static void set_audio(struct tuner *t) static void tda8290_set_freq(struct tuner *t, unsigned int freq) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char soft_reset[] = { 0x00, 0x00 }; unsigned char easy_mode[] = { 0x01, priv->tda8290_easy_mode }; unsigned char expert_mode[] = { 0x01, 0x80 }; @@ -293,7 +293,7 @@ static void tda8290_set_freq(struct tuner *t, unsigned int freq) static void tda8295_power(struct tuner *t, int enable) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */ tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); @@ -309,7 +309,7 @@ static void tda8295_power(struct tuner *t, int enable) static void tda8295_set_easy_mode(struct tuner *t, int enable) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char buf[] = { 0x01, 0x00 }; tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); @@ -325,7 +325,7 @@ static void tda8295_set_easy_mode(struct tuner *t, int enable) static void tda8295_set_video_std(struct tuner *t) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char buf[] = { 0x00, priv->tda8290_easy_mode }; tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); @@ -339,7 +339,7 @@ static void tda8295_set_video_std(struct tuner *t) static void tda8295_agc1_out(struct tuner *t, int enable) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */ tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); @@ -355,7 +355,7 @@ static void tda8295_agc1_out(struct tuner *t, int enable) static void tda8295_agc2_out(struct tuner *t, int enable) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char set_gpio_cf[] = { 0x44, 0x00 }; unsigned char set_gpio_val[] = { 0x46, 0x00 }; @@ -376,7 +376,7 @@ static void tda8295_agc2_out(struct tuner *t, int enable) static int tda8295_has_signal(struct tuner *t) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char hvpll_stat = 0x26; unsigned char ret; @@ -390,7 +390,7 @@ static int tda8295_has_signal(struct tuner *t) static void tda8295_set_freq(struct tuner *t, unsigned int freq) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; u16 ifc; unsigned char blanking_mode[] = { 0x1d, 0x00 }; @@ -440,7 +440,7 @@ static void tda8295_set_freq(struct tuner *t, unsigned int freq) static int tda8290_has_signal(struct tuner *t) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char i2c_get_afc[1] = { 0x1B }; unsigned char afc = 0; @@ -454,7 +454,7 @@ static int tda8290_has_signal(struct tuner *t) static void tda8290_standby(struct tuner *t) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char cb1[] = { 0x30, 0xD0 }; unsigned char tda8290_standby[] = { 0x00, 0x02 }; unsigned char tda8290_agc_tri[] = { 0x02, 0x20 }; @@ -478,7 +478,7 @@ static void tda8295_standby(struct tuner *t) static void tda8290_init_if(struct tuner *t) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char set_VS[] = { 0x30, 0x6F }; unsigned char set_GP00_CF[] = { 0x20, 0x01 }; @@ -493,7 +493,7 @@ static void tda8290_init_if(struct tuner *t) static void tda8295_init_if(struct tuner *t) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; static unsigned char set_adc_ctl[] = { 0x33, 0x14 }; static unsigned char set_adc_ctl2[] = { 0x34, 0x00 }; @@ -522,7 +522,7 @@ static void tda8295_init_if(struct tuner *t) static void tda8290_init_tuner(struct tuner *t) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf, 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 }; unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b, @@ -544,8 +544,8 @@ static void tda829x_release(struct tuner *t) if (t->fe.ops.tuner_ops.release) t->fe.ops.tuner_ops.release(&t->fe); - kfree(t->priv); - t->priv = NULL; + kfree(t->fe.analog_demod_priv); + t->fe.analog_demod_priv = NULL; } static struct analog_tuner_ops tda8290_tuner_ops = { @@ -575,7 +575,7 @@ int tda8290_attach(struct tuner *t) priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); if (priv == NULL) return -ENOMEM; - t->priv = priv; + t->fe.analog_demod_priv = priv; priv->i2c_props.addr = t->i2c.addr; priv->i2c_props.adap = t->i2c.adapter; @@ -665,7 +665,7 @@ int tda8295_attach(struct tuner *t) priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); if (priv == NULL) return -ENOMEM; - t->priv = priv; + t->fe.analog_demod_priv = priv; priv->i2c_props.addr = t->i2c.addr; priv->i2c_props.adap = t->i2c.adapter; diff --git a/linux/drivers/media/video/tda9887.c b/linux/drivers/media/video/tda9887.c index 41488e4f4..394e13504 100644 --- a/linux/drivers/media/video/tda9887.c +++ b/linux/drivers/media/video/tda9887.c @@ -523,7 +523,7 @@ static int tda9887_set_config(struct tuner *t, char *buf) static int tda9887_status(struct tuner *t) { - struct tda9887_priv *priv = t->priv; + struct tda9887_priv *priv = t->fe.analog_demod_priv; unsigned char buf[1]; int rc; @@ -536,7 +536,7 @@ static int tda9887_status(struct tuner *t) static void tda9887_configure(struct tuner *t) { - struct tda9887_priv *priv = t->priv; + struct tda9887_priv *priv = t->fe.analog_demod_priv; int rc; memset(priv->data,0,sizeof(priv->data)); @@ -583,13 +583,13 @@ static void tda9887_configure(struct tuner *t) static void tda9887_tuner_status(struct tuner *t) { - struct tda9887_priv *priv = t->priv; + struct tda9887_priv *priv = t->fe.analog_demod_priv; tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", priv->data[1], priv->data[2], priv->data[3]); } static int tda9887_get_afc(struct tuner *t) { - struct tda9887_priv *priv = t->priv; + struct tda9887_priv *priv = t->fe.analog_demod_priv; static int AFC_BITS_2_kHz[] = { -12500, -37500, -62500, -97500, -112500, -137500, -162500, -187500, @@ -617,8 +617,8 @@ static void tda9887_set_freq(struct tuner *t, unsigned int freq) static void tda9887_release(struct tuner *t) { - kfree(t->priv); - t->priv = NULL; + kfree(t->fe.analog_demod_priv); + t->fe.analog_demod_priv = NULL; } static struct analog_tuner_ops tda9887_tuner_ops = { @@ -637,7 +637,7 @@ int tda9887_tuner_init(struct tuner *t) priv = kzalloc(sizeof(struct tda9887_priv), GFP_KERNEL); if (priv == NULL) return -ENOMEM; - t->priv = priv; + t->fe.analog_demod_priv = priv; priv->i2c_props.addr = t->i2c.addr; priv->i2c_props.adap = t->i2c.adapter; diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index b6de9fecb..d743581bf 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -307,10 +307,6 @@ static void set_type(struct i2c_client *c, unsigned int type, /* discard private data, in case set_type() was previously called */ if ((ops) && (ops->release)) ops->release(t); - else { - kfree(t->priv); - t->priv = NULL; - } switch (t->type) { case TUNER_MT2032: @@ -780,12 +776,7 @@ MOD_DEC_USE_COUNT; #endif if ((ops) && (ops->release)) ops->release(t); - else { - kfree(t->priv); -#if 0 - t->priv = NULL; -#endif - } + kfree(t); return 0; } diff --git a/linux/drivers/media/video/tuner-driver.h b/linux/drivers/media/video/tuner-driver.h index 430141337..db6be5d52 100644 --- a/linux/drivers/media/video/tuner-driver.h +++ b/linux/drivers/media/video/tuner-driver.h @@ -57,7 +57,6 @@ struct tuner { v4l2_std_id std; int using_v4l2; - void *priv; struct dvb_frontend fe; -- cgit v1.2.3 From 1dc24f728097d312f26ea779561fba5da19de63b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 21 Oct 2007 23:12:16 -0400 Subject: dvb_frontend: codingstyle cleanups From: Michael Krufky thanks to checkpatch.pl Signed-off-by: Michael Krufky Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-core/dvb_frontend.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) --- linux/drivers/media/dvb/dvb-core/dvb_frontend.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h index 204994a60..d99fe67ae 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -171,19 +171,19 @@ struct dvb_fe_events { struct dvb_frontend { struct dvb_frontend_ops ops; struct dvb_adapter *dvb; - void* demodulator_priv; - void* tuner_priv; - void* frontend_priv; - void* sec_priv; - void* analog_demod_priv; + void *demodulator_priv; + void *tuner_priv; + void *frontend_priv; + void *sec_priv; + void *analog_demod_priv; }; -extern int dvb_register_frontend(struct dvb_adapter* dvb, - struct dvb_frontend* fe); +extern int dvb_register_frontend(struct dvb_adapter *dvb, + struct dvb_frontend *fe); -extern int dvb_unregister_frontend(struct dvb_frontend* fe); +extern int dvb_unregister_frontend(struct dvb_frontend *fe); -extern void dvb_frontend_detach(struct dvb_frontend* fe); +extern void dvb_frontend_detach(struct dvb_frontend *fe); extern void dvb_frontend_reinitialise(struct dvb_frontend *fe); -- cgit v1.2.3 From 45eba30725ae74b83dcb73a3cb79db3bbe2f53b1 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 21 Oct 2007 18:39:50 -0400 Subject: tuner: convert analog tuner demod sub-modules to dvb_frontend interface From: Michael Krufky Convert tda9887 and tda8290/5 to dvb_frontend interface Signed-off-by: Michael Krufky Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tda8290.c | 168 ++++++++++++++++--------------- linux/drivers/media/video/tda9887.c | 78 ++++++++------ linux/drivers/media/video/tuner-core.c | 79 +++++++------- linux/drivers/media/video/tuner-driver.h | 16 +- 4 files changed, 188 insertions(+), 153 deletions(-) --- linux/drivers/media/video/tda8290.c | 168 ++++++++++++++++--------------- linux/drivers/media/video/tda9887.c | 78 ++++++++------ linux/drivers/media/video/tuner-core.c | 79 ++++++++------- linux/drivers/media/video/tuner-driver.h | 16 +-- 4 files changed, 188 insertions(+), 153 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tda8290.c b/linux/drivers/media/video/tda8290.c index 2d6b55ead..aed23ce1f 100644 --- a/linux/drivers/media/video/tda8290.c +++ b/linux/drivers/media/video/tda8290.c @@ -53,13 +53,15 @@ struct tda8290_priv { unsigned char tda827x_ver; struct tda827x_config cfg; + + struct tuner *t; }; /*---------------------------------------------------------------------*/ -static void tda8290_i2c_bridge(struct tuner *t, int close) +static void tda8290_i2c_bridge(struct dvb_frontend *fe, int close) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char enable[2] = { 0x21, 0xC0 }; unsigned char disable[2] = { 0x21, 0x00 }; @@ -76,9 +78,9 @@ static void tda8290_i2c_bridge(struct tuner *t, int close) } #if 1 -static void tda8295_i2c_bridge(struct tuner *t, int close) +static void tda8295_i2c_bridge(struct dvb_frontend *fe, int close) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char enable[2] = { 0x45, 0xc1 }; unsigned char disable[2] = { 0x46, 0x00 }; @@ -104,9 +106,9 @@ static void tda8295_i2c_bridge(struct tuner *t, int close) } } #else -static void tda8295_i2c_bridge(struct tuner *t, int close) +static void tda8295_i2c_bridge(struct dvb_frontend *fe, int close) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char buf[] = { 0x45, 0x00 }; @@ -125,9 +127,10 @@ static void tda8295_i2c_bridge(struct tuner *t, int close) /*---------------------------------------------------------------------*/ -static void set_audio(struct tuner *t) +static void set_audio(struct dvb_frontend *fe) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; + struct tuner *t = priv->t; char* mode; priv->cfg.tda827x_lpsel = 0; @@ -172,9 +175,11 @@ static void set_audio(struct tuner *t) tuner_dbg("setting tda8290 to system %s\n", mode); } -static void tda8290_set_freq(struct tuner *t, unsigned int freq) +static void tda8290_set_freq(struct dvb_frontend *fe, unsigned int freq) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; + struct tuner *t = priv->t; + unsigned char soft_reset[] = { 0x00, 0x00 }; unsigned char easy_mode[] = { 0x01, priv->tda8290_easy_mode }; unsigned char expert_mode[] = { 0x01, 0x80 }; @@ -204,7 +209,7 @@ static void tda8290_set_freq(struct tuner *t, unsigned int freq) .std = t->std }; - set_audio(t); + set_audio(fe); tuner_dbg("tda827xa config is 0x%02x\n", t->config); tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2); @@ -222,10 +227,10 @@ static void tda8290_set_freq(struct tuner *t, unsigned int freq) tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2); tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2); - tda8290_i2c_bridge(t, 1); + tda8290_i2c_bridge(fe, 1); - if (t->fe.ops.tuner_ops.set_analog_params) - t->fe.ops.tuner_ops.set_analog_params(&t->fe, ¶ms); + if (fe->ops.tuner_ops.set_analog_params) + fe->ops.tuner_ops.set_analog_params(fe, ¶ms); for (i = 0; i < 3; i++) { tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); @@ -256,7 +261,7 @@ static void tda8290_set_freq(struct tuner *t, unsigned int freq) tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n", agc_stat, pll_stat & 0x80); if (priv->cfg.agcf) - priv->cfg.agcf(&t->fe); + priv->cfg.agcf(fe); msleep(100); tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); @@ -285,15 +290,15 @@ static void tda8290_set_freq(struct tuner *t, unsigned int freq) } } - tda8290_i2c_bridge(t, 0); + tda8290_i2c_bridge(fe, 0); tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2); } /*---------------------------------------------------------------------*/ -static void tda8295_power(struct tuner *t, int enable) +static void tda8295_power(struct dvb_frontend *fe, int enable) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */ tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); @@ -307,9 +312,9 @@ static void tda8295_power(struct tuner *t, int enable) tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); } -static void tda8295_set_easy_mode(struct tuner *t, int enable) +static void tda8295_set_easy_mode(struct dvb_frontend *fe, int enable) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char buf[] = { 0x01, 0x00 }; tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); @@ -323,23 +328,23 @@ static void tda8295_set_easy_mode(struct tuner *t, int enable) tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); } -static void tda8295_set_video_std(struct tuner *t) +static void tda8295_set_video_std(struct dvb_frontend *fe) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char buf[] = { 0x00, priv->tda8290_easy_mode }; tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); - tda8295_set_easy_mode(t, 1); + tda8295_set_easy_mode(fe, 1); msleep(20); - tda8295_set_easy_mode(t, 0); + tda8295_set_easy_mode(fe, 0); } /*---------------------------------------------------------------------*/ -static void tda8295_agc1_out(struct tuner *t, int enable) +static void tda8295_agc1_out(struct dvb_frontend *fe, int enable) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */ tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); @@ -353,9 +358,9 @@ static void tda8295_agc1_out(struct tuner *t, int enable) tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); } -static void tda8295_agc2_out(struct tuner *t, int enable) +static void tda8295_agc2_out(struct dvb_frontend *fe, int enable) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char set_gpio_cf[] = { 0x44, 0x00 }; unsigned char set_gpio_val[] = { 0x46, 0x00 }; @@ -374,9 +379,9 @@ static void tda8295_agc2_out(struct tuner *t, int enable) tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_val, 2); } -static int tda8295_has_signal(struct tuner *t) +static int tda8295_has_signal(struct dvb_frontend *fe) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char hvpll_stat = 0x26; unsigned char ret; @@ -388,9 +393,10 @@ static int tda8295_has_signal(struct tuner *t) /*---------------------------------------------------------------------*/ -static void tda8295_set_freq(struct tuner *t, unsigned int freq) +static void tda8295_set_freq(struct dvb_frontend *fe, unsigned int freq) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; + struct tuner *t = priv->t; u16 ifc; unsigned char blanking_mode[] = { 0x1d, 0x00 }; @@ -402,45 +408,45 @@ static void tda8295_set_freq(struct tuner *t, unsigned int freq) .std = t->std }; - set_audio(t); + set_audio(fe); ifc = priv->cfg.sgIF; /* FIXME */ tuner_dbg("%s: ifc = %u, freq = %d\n", __FUNCTION__, ifc, freq); - tda8295_power(t, 1); - tda8295_agc1_out(t, 1); + tda8295_power(fe, 1); + tda8295_agc1_out(fe, 1); tuner_i2c_xfer_send(&priv->i2c_props, &blanking_mode[0], 1); tuner_i2c_xfer_recv(&priv->i2c_props, &blanking_mode[1], 1); - tda8295_set_video_std(t); + tda8295_set_video_std(fe); blanking_mode[1] = 0x03; tuner_i2c_xfer_send(&priv->i2c_props, blanking_mode, 2); msleep(20); - tda8295_i2c_bridge(t, 1); + tda8295_i2c_bridge(fe, 1); - if (t->fe.ops.tuner_ops.set_analog_params) - t->fe.ops.tuner_ops.set_analog_params(&t->fe, ¶ms); + if (fe->ops.tuner_ops.set_analog_params) + fe->ops.tuner_ops.set_analog_params(fe, ¶ms); if (priv->cfg.agcf) - priv->cfg.agcf(&t->fe); + priv->cfg.agcf(fe); - if (tda8295_has_signal(t)) + if (tda8295_has_signal(fe)) tuner_dbg("tda8295 is locked\n"); else tuner_dbg("tda8295 not locked, no signal?\n"); - tda8295_i2c_bridge(t, 0); + tda8295_i2c_bridge(fe, 0); } /*---------------------------------------------------------------------*/ -static int tda8290_has_signal(struct tuner *t) +static int tda8290_has_signal(struct dvb_frontend *fe) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char i2c_get_afc[1] = { 0x1B }; unsigned char afc = 0; @@ -452,33 +458,35 @@ static int tda8290_has_signal(struct tuner *t) /*---------------------------------------------------------------------*/ -static void tda8290_standby(struct tuner *t) +static void tda8290_standby(struct dvb_frontend *fe) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; + unsigned char cb1[] = { 0x30, 0xD0 }; unsigned char tda8290_standby[] = { 0x00, 0x02 }; unsigned char tda8290_agc_tri[] = { 0x02, 0x20 }; struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2}; - tda8290_i2c_bridge(t, 1); + tda8290_i2c_bridge(fe, 1); if (priv->tda827x_ver != 0) cb1[1] = 0x90; i2c_transfer(priv->i2c_props.adap, &msg, 1); - tda8290_i2c_bridge(t, 0); + tda8290_i2c_bridge(fe, 0); tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2); tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2); } -static void tda8295_standby(struct tuner *t) +static void tda8295_standby(struct dvb_frontend *fe) { - tda8295_agc1_out(t, 0); /* Put AGC in tri-state */ + tda8295_agc1_out(fe, 0); /* Put AGC in tri-state */ - tda8295_power(t, 0); + tda8295_power(fe, 0); } -static void tda8290_init_if(struct tuner *t) +static void tda8290_init_if(struct dvb_frontend *fe) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; + struct tuner *t = priv->t; unsigned char set_VS[] = { 0x30, 0x6F }; unsigned char set_GP00_CF[] = { 0x20, 0x01 }; @@ -491,9 +499,9 @@ static void tda8290_init_if(struct tuner *t) tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2); } -static void tda8295_init_if(struct tuner *t) +static void tda8295_init_if(struct dvb_frontend *fe) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; static unsigned char set_adc_ctl[] = { 0x33, 0x14 }; static unsigned char set_adc_ctl2[] = { 0x34, 0x00 }; @@ -503,10 +511,10 @@ static void tda8295_init_if(struct tuner *t) static unsigned char set_pll_reg10[] = { 0x42, 0x61 }; static unsigned char set_gpio_reg0[] = { 0x44, 0x0b }; - tda8295_power(t, 1); + tda8295_power(fe, 1); - tda8295_set_easy_mode(t, 0); - tda8295_set_video_std(t); + tda8295_set_easy_mode(fe, 0); + tda8295_set_video_std(fe); tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl, 2); tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl2, 2); @@ -516,13 +524,13 @@ static void tda8295_init_if(struct tuner *t) tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg10, 2); tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_reg0, 2); - tda8295_agc1_out(t, 0); - tda8295_agc2_out(t, 0); + tda8295_agc1_out(fe, 0); + tda8295_agc2_out(fe, 0); } -static void tda8290_init_tuner(struct tuner *t) +static void tda8290_init_tuner(struct dvb_frontend *fe) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf, 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 }; unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b, @@ -532,20 +540,20 @@ static void tda8290_init_tuner(struct tuner *t) if (priv->tda827x_ver != 0) msg.buf = tda8275a_init; - tda8290_i2c_bridge(t, 1); + tda8290_i2c_bridge(fe, 1); i2c_transfer(priv->i2c_props.adap, &msg, 1); - tda8290_i2c_bridge(t, 0); + tda8290_i2c_bridge(fe, 0); } /*---------------------------------------------------------------------*/ -static void tda829x_release(struct tuner *t) +static void tda829x_release(struct dvb_frontend *fe) { - if (t->fe.ops.tuner_ops.release) - t->fe.ops.tuner_ops.release(&t->fe); + if (fe->ops.tuner_ops.release) + fe->ops.tuner_ops.release(fe); - kfree(t->fe.analog_demod_priv); - t->fe.analog_demod_priv = NULL; + kfree(fe->analog_demod_priv); + fe->analog_demod_priv = NULL; } static struct analog_tuner_ops tda8290_tuner_ops = { @@ -581,8 +589,9 @@ int tda8290_attach(struct tuner *t) priv->i2c_props.adap = t->i2c.adapter; priv->cfg.config = &t->config; priv->cfg.tuner_callback = t->tuner_callback; + priv->t = t; - tda8290_i2c_bridge(t, 1); + tda8290_i2c_bridge(&t->fe, 1); /* probe for tuner chip */ tuners_found = 0; tuner_addrs = 0; @@ -598,7 +607,7 @@ int tda8290_attach(struct tuner *t) behind the bridge and we choose the highest address that doesn't give a response now */ - tda8290_i2c_bridge(t, 0); + tda8290_i2c_bridge(&t->fe, 0); if(tuners_found > 1) for (i = 0; i < tuners_found; i++) { msg.addr = tuner_addrs & 0xff; @@ -619,7 +628,7 @@ int tda8290_attach(struct tuner *t) priv->tda827x_addr = tuner_addrs; msg.addr = tuner_addrs; - tda8290_i2c_bridge(t, 1); + tda8290_i2c_bridge(&t->fe, 1); ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); if( ret != 1) @@ -648,8 +657,8 @@ int tda8290_attach(struct tuner *t) priv->cfg.tda827x_lpsel = 0; t->mode = V4L2_TUNER_ANALOG_TV; - tda8290_init_tuner(t); - tda8290_init_if(t); + tda8290_init_tuner(&t->fe); + tda8290_init_if(&t->fe); return 0; } EXPORT_SYMBOL_GPL(tda8290_attach); @@ -669,8 +678,9 @@ int tda8295_attach(struct tuner *t) priv->i2c_props.addr = t->i2c.addr; priv->i2c_props.adap = t->i2c.adapter; + priv->t = t; - tda8295_i2c_bridge(t, 1); + tda8295_i2c_bridge(&t->fe, 1); /* probe for tuner chip */ tuners_found = 0; tuner_addrs = 0; @@ -686,7 +696,7 @@ int tda8295_attach(struct tuner *t) behind the bridge and we choose the highest address that doesn't give a response now */ - tda8295_i2c_bridge(t, 0); + tda8295_i2c_bridge(&t->fe, 0); if (tuners_found > 1) for (i = 0; i < tuners_found; i++) { msg.addr = tuner_addrs & 0xff; @@ -707,9 +717,9 @@ int tda8295_attach(struct tuner *t) priv->tda827x_addr = tuner_addrs; msg.addr = tuner_addrs; - tda8295_i2c_bridge(t, 1); + tda8295_i2c_bridge(&t->fe, 1); ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); - tda8295_i2c_bridge(t, 0); + tda8295_i2c_bridge(&t->fe, 0); if (ret != 1) tuner_warn("TDA827x access failed!\n"); if ((data & 0x3c) == 0) { @@ -737,7 +747,7 @@ int tda8295_attach(struct tuner *t) priv->cfg.tda827x_lpsel = 0; t->mode = V4L2_TUNER_ANALOG_TV; - tda8295_init_if(t); + tda8295_init_if(&t->fe); return 0; } EXPORT_SYMBOL_GPL(tda8295_attach); diff --git a/linux/drivers/media/video/tda9887.c b/linux/drivers/media/video/tda9887.c index 394e13504..1edb1299f 100644 --- a/linux/drivers/media/video/tda9887.c +++ b/linux/drivers/media/video/tda9887.c @@ -25,17 +25,19 @@ */ #define tda9887_info(fmt, arg...) do {\ - printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.name, \ - i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) + printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c.name, \ + i2c_adapter_id(priv->t->i2c.adapter), priv->t->i2c.addr , ##arg); } while (0) #define tda9887_dbg(fmt, arg...) do {\ if (tuner_debug) \ - printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.name, \ - i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) + printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c.name, \ + i2c_adapter_id(priv->t->i2c.adapter), priv->t->i2c.addr , ##arg); } while (0) struct tda9887_priv { struct tuner_i2c_props i2c_props; unsigned char data[4]; + + struct tuner *t; }; /* ---------------------------------------------------------------------- */ @@ -266,8 +268,10 @@ static struct tvnorm radio_mono = { /* ---------------------------------------------------------------------- */ -static void dump_read_message(struct tuner *t, unsigned char *buf) +static void dump_read_message(struct dvb_frontend *fe, unsigned char *buf) { + struct tda9887_priv *priv = fe->analog_demod_priv; + static char *afc[16] = { "- 12.5 kHz", "- 37.5 kHz", @@ -294,8 +298,10 @@ static void dump_read_message(struct tuner *t, unsigned char *buf) tda9887_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low"); } -static void dump_write_message(struct tuner *t, unsigned char *buf) +static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf) { + struct tda9887_priv *priv = fe->analog_demod_priv; + static char *sound[4] = { "AM/TV", "FM/radio", @@ -390,9 +396,12 @@ static void dump_write_message(struct tuner *t, unsigned char *buf) /* ---------------------------------------------------------------------- */ -static int tda9887_set_tvnorm(struct tuner *t, char *buf) +static int tda9887_set_tvnorm(struct dvb_frontend *fe) { + struct tda9887_priv *priv = fe->analog_demod_priv; + struct tuner *t = priv->t; struct tvnorm *norm = NULL; + char *buf = priv->data; int i; if (t->mode == V4L2_TUNER_RADIO) { @@ -437,8 +446,11 @@ module_param(qss, int, 0644); module_param(adjust, int, 0644); #endif -static int tda9887_set_insmod(struct tuner *t, char *buf) +static int tda9887_set_insmod(struct dvb_frontend *fe) { + struct tda9887_priv *priv = fe->analog_demod_priv; + char *buf = priv->data; + if (UNSET != port1) { if (port1) buf[1] |= cOutputPort1Inactive; @@ -466,8 +478,12 @@ static int tda9887_set_insmod(struct tuner *t, char *buf) return 0; } -static int tda9887_set_config(struct tuner *t, char *buf) +static int tda9887_set_config(struct dvb_frontend *fe) { + struct tda9887_priv *priv = fe->analog_demod_priv; + struct tuner *t = priv->t; + char *buf = priv->data; + if (t->tda9887_config & TDA9887_PORT1_ACTIVE) buf[1] &= ~cOutputPort1Inactive; if (t->tda9887_config & TDA9887_PORT1_INACTIVE) @@ -521,26 +537,27 @@ static int tda9887_set_config(struct tuner *t, char *buf) /* ---------------------------------------------------------------------- */ -static int tda9887_status(struct tuner *t) +static int tda9887_status(struct dvb_frontend *fe) { - struct tda9887_priv *priv = t->fe.analog_demod_priv; + struct tda9887_priv *priv = fe->analog_demod_priv; unsigned char buf[1]; int rc; memset(buf,0,sizeof(buf)); if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,buf,1))) tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc); - dump_read_message(t, buf); + dump_read_message(fe, buf); return 0; } -static void tda9887_configure(struct tuner *t) +static void tda9887_configure(struct dvb_frontend *fe) { - struct tda9887_priv *priv = t->fe.analog_demod_priv; + struct tda9887_priv *priv = fe->analog_demod_priv; + struct tuner *t = priv->t; int rc; memset(priv->data,0,sizeof(priv->data)); - tda9887_set_tvnorm(t,priv->data); + tda9887_set_tvnorm(fe); /* A note on the port settings: These settings tend to depend on the specifics of the board. @@ -558,8 +575,8 @@ static void tda9887_configure(struct tuner *t) priv->data[1] |= cOutputPort1Inactive; priv->data[1] |= cOutputPort2Inactive; - tda9887_set_config(t,priv->data); - tda9887_set_insmod(t,priv->data); + tda9887_set_config(fe); + tda9887_set_insmod(fe); if (t->mode == T_STANDBY) { priv->data[1] |= cForcedMuteAudioON; @@ -568,28 +585,28 @@ static void tda9887_configure(struct tuner *t) tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", priv->data[1],priv->data[2],priv->data[3]); if (tuner_debug > 1) - dump_write_message(t, priv->data); + dump_write_message(fe, priv->data); if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,priv->data,4))) tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); if (tuner_debug > 2) { msleep_interruptible(1000); - tda9887_status(t); + tda9887_status(fe); } } /* ---------------------------------------------------------------------- */ -static void tda9887_tuner_status(struct tuner *t) +static void tda9887_tuner_status(struct dvb_frontend *fe) { - struct tda9887_priv *priv = t->fe.analog_demod_priv; + struct tda9887_priv *priv = fe->analog_demod_priv; tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", priv->data[1], priv->data[2], priv->data[3]); } -static int tda9887_get_afc(struct tuner *t) +static int tda9887_get_afc(struct dvb_frontend *fe) { - struct tda9887_priv *priv = t->fe.analog_demod_priv; + struct tda9887_priv *priv = fe->analog_demod_priv; static int AFC_BITS_2_kHz[] = { -12500, -37500, -62500, -97500, -112500, -137500, -162500, -187500, @@ -605,20 +622,20 @@ static int tda9887_get_afc(struct tuner *t) return afc; } -static void tda9887_standby(struct tuner *t) +static void tda9887_standby(struct dvb_frontend *fe) { - tda9887_configure(t); + tda9887_configure(fe); } -static void tda9887_set_freq(struct tuner *t, unsigned int freq) +static void tda9887_set_freq(struct dvb_frontend *fe, unsigned int freq) { - tda9887_configure(t); + tda9887_configure(fe); } -static void tda9887_release(struct tuner *t) +static void tda9887_release(struct dvb_frontend *fe) { - kfree(t->fe.analog_demod_priv); - t->fe.analog_demod_priv = NULL; + kfree(fe->analog_demod_priv); + fe->analog_demod_priv = NULL; } static struct analog_tuner_ops tda9887_tuner_ops = { @@ -641,6 +658,7 @@ int tda9887_tuner_init(struct tuner *t) priv->i2c_props.addr = t->i2c.addr; priv->i2c_props.adap = t->i2c.adapter; + priv->t = t; strlcpy(t->i2c.name, "tda9887", sizeof(t->i2c.name)); diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index d743581bf..7c52d616a 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -102,9 +102,10 @@ static struct i2c_client client_template; /* ---------------------------------------------------------------------- */ -static void fe_set_freq(struct tuner *t, unsigned int freq) +static void fe_set_freq(struct dvb_frontend *fe, unsigned int freq) { - struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; + struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops; + struct tuner *t = fe->analog_demod_priv; struct analog_parameters params = { .frequency = freq, @@ -117,39 +118,38 @@ static void fe_set_freq(struct tuner *t, unsigned int freq) tuner_warn("Tuner frontend module has no way to set freq\n"); return; } - fe_tuner_ops->set_analog_params(&t->fe, ¶ms); + fe_tuner_ops->set_analog_params(fe, ¶ms); } -static void fe_release(struct tuner *t) +static void fe_release(struct dvb_frontend *fe) { - struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; - - if (fe_tuner_ops->release) - fe_tuner_ops->release(&t->fe); + if (fe->ops.tuner_ops.release) + fe->ops.tuner_ops.release(fe); - t->fe.ops.analog_demod_ops = NULL; + fe->ops.analog_demod_ops = NULL; + /* DO NOT kfree(t->fe.analog_demod_priv) */ + fe->analog_demod_priv = NULL; } -static void fe_standby(struct tuner *t) +static void fe_standby(struct dvb_frontend *fe) { - struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; + struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops; if (fe_tuner_ops->sleep) - fe_tuner_ops->sleep(&t->fe); + fe_tuner_ops->sleep(fe); } -static int fe_has_signal(struct tuner *t) +static int fe_has_signal(struct dvb_frontend *fe) { - struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; u16 strength = 0; - if (fe_tuner_ops->get_rf_strength) - fe_tuner_ops->get_rf_strength(&t->fe, &strength); + if (fe->ops.tuner_ops.get_rf_strength) + fe->ops.tuner_ops.get_rf_strength(fe, &strength); return strength; } -static void tuner_status(struct tuner *t); +static void tuner_status(struct dvb_frontend *fe); static struct analog_tuner_ops tuner_core_ops = { .set_tv_freq = fe_set_freq, @@ -185,7 +185,7 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) else freq = tv_range[1] * 16; } - ops->set_tv_freq(t, freq); + ops->set_tv_freq(&t->fe, freq); } static void set_radio_freq(struct i2c_client *c, unsigned int freq) @@ -213,7 +213,7 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq) freq = radio_range[1] * 16000; } - ops->set_radio_freq(t, freq); + ops->set_radio_freq(&t->fe, freq); } static void set_freq(struct i2c_client *c, unsigned long freq) @@ -306,7 +306,7 @@ static void set_type(struct i2c_client *c, unsigned int type, /* discard private data, in case set_type() was previously called */ if ((ops) && (ops->release)) - ops->release(t); + ops->release(&t->fe); switch (t->type) { case TUNER_MT2032: @@ -386,6 +386,7 @@ static void set_type(struct i2c_client *c, unsigned int type, strlcpy(t->i2c.name, fe_tuner_ops->info.name, sizeof(t->i2c.name)); t->fe.ops.analog_demod_ops = &tuner_core_ops; + t->fe.analog_demod_priv = t; } tuner_info("type set to %s\n", t->i2c.name); @@ -567,8 +568,9 @@ static int tuner_fixup_std(struct tuner *t) return 0; } -static void tuner_status(struct tuner *t) +static void tuner_status(struct dvb_frontend *fe) { + struct tuner *t = fe->analog_demod_priv; unsigned long freq, freq_fraction; struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; @@ -602,10 +604,11 @@ static void tuner_status(struct tuner *t) tuner_info("Stereo: yes\n"); } if ((ops) && (ops->has_signal)) { - tuner_info("Signal strength: %d\n", ops->has_signal(t)); + tuner_info("Signal strength: %d\n", ops->has_signal(fe)); } if ((ops) && (ops->is_stereo)) { - tuner_info("Stereo: %s\n", ops->is_stereo(t) ? "yes" : "no"); + tuner_info("Stereo: %s\n", ops->is_stereo(fe) ? + "yes" : "no"); } } @@ -775,7 +778,7 @@ static int tuner_detach(struct i2c_client *client) MOD_DEC_USE_COUNT; #endif if ((ops) && (ops->release)) - ops->release(t); + ops->release(&t->fe); kfree(t); return 0; @@ -800,7 +803,7 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, if (check_mode(t, cmd) == EINVAL) { t->mode = T_STANDBY; if ((ops) && (ops->standby)) - ops->standby(t); + ops->standby(&t->fe); return EINVAL; } return 0; @@ -857,7 +860,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; t->mode = T_STANDBY; if ((ops) && (ops->standby)) - ops->standby(t); + ops->standby(&t->fe); break; #ifdef CONFIG_VIDEO_V4L1 case VIDIOCSAUDIO: @@ -926,7 +929,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) vt->flags &= ~VIDEO_TUNER_STEREO_ON; } else { if ((ops) && (ops->is_stereo)) { - if (ops->is_stereo(t)) + if (ops->is_stereo(&t->fe)) vt->flags |= VIDEO_TUNER_STEREO_ON; else @@ -935,7 +938,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) } } if ((ops) && (ops->has_signal)) - vt->signal = ops->has_signal(t); + vt->signal = ops->has_signal(&t->fe); vt->flags |= VIDEO_TUNER_LOW; /* Allow freqs at 62.5 Hz */ @@ -966,7 +969,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) va->mode = (tuner_status & TUNER_STATUS_STEREO) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; } else if ((ops) && (ops->is_stereo)) - va->mode = ops->is_stereo(t) + va->mode = ops->is_stereo(&t->fe) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; } return 0; @@ -1057,7 +1060,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) tuner->type = t->mode; if ((ops) && (ops->get_afc)) - tuner->afc = ops->get_afc(t); + tuner->afc = ops->get_afc(&t->fe); if (t->mode == V4L2_TUNER_ANALOG_TV) tuner->capability |= V4L2_TUNER_CAP_NORM; if (t->mode != V4L2_TUNER_RADIO) { @@ -1073,16 +1076,20 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) u32 tuner_status; fe_tuner_ops->get_status(&t->fe, &tuner_status); - tuner->rxsubchans = (tuner_status & TUNER_STATUS_STEREO) ? - V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; + tuner->rxsubchans = + (tuner_status & TUNER_STATUS_STEREO) ? + V4L2_TUNER_SUB_STEREO : + V4L2_TUNER_SUB_MONO; } else { if ((ops) && (ops->is_stereo)) { - tuner->rxsubchans = ops->is_stereo(t) ? - V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; + tuner->rxsubchans = + ops->is_stereo(&t->fe) ? + V4L2_TUNER_SUB_STEREO : + V4L2_TUNER_SUB_MONO; } } if ((ops) && (ops->has_signal)) - tuner->signal = ops->has_signal(t); + tuner->signal = ops->has_signal(&t->fe); tuner->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; tuner->audmode = t->audmode; @@ -1108,7 +1115,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) } case VIDIOC_LOG_STATUS: if ((ops) && (ops->tuner_status)) - ops->tuner_status(t); + ops->tuner_status(&t->fe); break; } diff --git a/linux/drivers/media/video/tuner-driver.h b/linux/drivers/media/video/tuner-driver.h index db6be5d52..e9d7dc061 100644 --- a/linux/drivers/media/video/tuner-driver.h +++ b/linux/drivers/media/video/tuner-driver.h @@ -32,14 +32,14 @@ extern unsigned const int tuner_count; struct tuner; struct analog_tuner_ops { - void (*set_tv_freq)(struct tuner *t, unsigned int freq); - void (*set_radio_freq)(struct tuner *t, unsigned int freq); - int (*has_signal)(struct tuner *t); - int (*is_stereo)(struct tuner *t); - int (*get_afc)(struct tuner *t); - void (*tuner_status)(struct tuner *t); - void (*standby)(struct tuner *t); - void (*release)(struct tuner *t); + void (*set_tv_freq)(struct dvb_frontend *fe, unsigned int freq); + void (*set_radio_freq)(struct dvb_frontend *fe, unsigned int freq); + int (*has_signal)(struct dvb_frontend *fe); + int (*is_stereo)(struct dvb_frontend *fe); + int (*get_afc)(struct dvb_frontend *fe); + void (*tuner_status)(struct dvb_frontend *fe); + void (*standby)(struct dvb_frontend *fe); + void (*release)(struct dvb_frontend *fe); }; struct tuner { -- cgit v1.2.3 From dc6f31feaba49df7cf93fe4b1aac2665f2e3e692 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 22 Oct 2007 00:44:03 -0400 Subject: tuner: clean up ops checking in tuner_status function From: Michael Krufky Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-core.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) --- linux/drivers/media/video/tuner-core.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 7c52d616a..ccddf55eb 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -603,12 +603,13 @@ static void tuner_status(struct dvb_frontend *fe) if (tuner_status & TUNER_STATUS_STEREO) tuner_info("Stereo: yes\n"); } - if ((ops) && (ops->has_signal)) { - tuner_info("Signal strength: %d\n", ops->has_signal(fe)); - } - if ((ops) && (ops->is_stereo)) { - tuner_info("Stereo: %s\n", ops->is_stereo(fe) ? - "yes" : "no"); + if (ops) { + if (ops->has_signal) + tuner_info("Signal strength: %d\n", + ops->has_signal(fe)); + if (ops->is_stereo) + tuner_info("Stereo: %s\n", + ops->is_stereo(fe) ? "yes" : "no"); } } -- cgit v1.2.3 From 4728a760179d2992de4fa160f0b1d474cb0c03d2 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 22 Oct 2007 00:10:39 -0400 Subject: move std if setting from tda8290 to tda827x From: Michael Krufky Signed-off-by: Michael Krufky Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/tda827x.c | 61 +++++++++++++++++++++++++--- linux/drivers/media/dvb/frontends/tda827x.h | 3 - linux/drivers/media/video/tda8290.c | 20 --------- 3 files changed, 57 insertions(+), 27 deletions(-) --- linux/drivers/media/dvb/frontends/tda827x.c | 61 ++++++++++++++++++++++++++--- linux/drivers/media/dvb/frontends/tda827x.h | 3 -- linux/drivers/media/video/tda8290.c | 20 +--------- 3 files changed, 57 insertions(+), 27 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/tda827x.c b/linux/drivers/media/dvb/frontends/tda827x.c index 6de1aea02..8329d33b5 100644 --- a/linux/drivers/media/dvb/frontends/tda827x.c +++ b/linux/drivers/media/dvb/frontends/tda827x.c @@ -38,10 +38,57 @@ struct tda827x_priv { int i2c_addr; struct i2c_adapter *i2c_adap; struct tda827x_config *cfg; + + unsigned int sgIF; + unsigned char lpsel; + u32 frequency; u32 bandwidth; }; +static void tda827x_set_std(struct dvb_frontend *fe, + struct analog_parameters *params) +{ + struct tda827x_priv *priv = fe->tuner_priv; + char *mode; + + priv->lpsel = 0; + if (params->std & V4L2_STD_MN) { + priv->sgIF = 92; + priv->lpsel = 1; + mode = "MN"; + } else if (params->std & V4L2_STD_B) { + priv->sgIF = 108; + mode = "B"; + } else if (params->std & V4L2_STD_GH) { + priv->sgIF = 124; + mode = "GH"; + } else if (params->std & V4L2_STD_PAL_I) { + priv->sgIF = 124; + mode = "I"; + } else if (params->std & V4L2_STD_DK) { + priv->sgIF = 124; + mode = "DK"; + } else if (params->std & V4L2_STD_SECAM_L) { + priv->sgIF = 124; + mode = "L"; + } else if (params->std & V4L2_STD_SECAM_LC) { + priv->sgIF = 20; + mode = "LC"; + } else { + priv->sgIF = 124; + mode = "xx"; + } + + if (params->mode == V4L2_TUNER_RADIO) + priv->sgIF = 88; /* if frequency is 5.5 MHz */ + + dprintk("setting tda827x to system %s\n", mode); +} + + +/* ------------------------------------------------------------------ */ + struct tda827x_data { u32 lomax; u8 spd; @@ -189,10 +236,12 @@ static int tda827xo_set_analog_params(struct dvb_frontend *fe, struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0 }; unsigned int freq = params->frequency; + tda827x_set_std(fe, params); + if (params->mode == V4L2_TUNER_RADIO) freq = freq / 1000; - N = freq + priv->cfg->sgIF; + N = freq + priv->sgIF; i = 0; while (tda827x_table[i].lomax < N * 62500) { @@ -207,7 +256,7 @@ static int tda827xo_set_analog_params(struct dvb_frontend *fe, tuner_reg[1] = (unsigned char)(N>>8); tuner_reg[2] = (unsigned char) N; tuner_reg[3] = 0x40; - tuner_reg[4] = 0x52 + (priv->cfg->tda827x_lpsel << 5); + tuner_reg[4] = 0x52 + (priv->lpsel << 5); tuner_reg[5] = (tda827x_table[i].spd << 6) + (tda827x_table[i].div1p5 << 5) + (tda827x_table[i].bs << 3) + tda827x_table[i].bp; @@ -550,13 +599,15 @@ static int tda827xa_set_analog_params(struct dvb_frontend *fe, .buf = tuner_reg, .len = sizeof(tuner_reg) }; unsigned int freq = params->frequency; + tda827x_set_std(fe, params); + tda827xa_lna_gain(fe, 1, params); msleep(10); if (params->mode == V4L2_TUNER_RADIO) freq = freq / 1000; - N = freq + priv->cfg->sgIF; + N = freq + priv->sgIF; i = 0; while (tda827xa_analog[i].lomax < N * 62500) { @@ -587,7 +638,7 @@ static int tda827xa_set_analog_params(struct dvb_frontend *fe, tuner_reg[1] = 0xff; tuner_reg[2] = 0xe0; tuner_reg[3] = 0; - tuner_reg[4] = 0x99 + (priv->cfg->tda827x_lpsel << 1); + tuner_reg[4] = 0x99 + (priv->lpsel << 1); msg.len = 5; i2c_transfer(priv->i2c_adap, &msg, 1); @@ -627,7 +678,7 @@ static int tda827xa_set_analog_params(struct dvb_frontend *fe, i2c_transfer(priv->i2c_adap, &msg, 1); tuner_reg[0] = 0xc0; - tuner_reg[1] = 0x19 + (priv->cfg->tda827x_lpsel << 1); + tuner_reg[1] = 0x19 + (priv->lpsel << 1); i2c_transfer(priv->i2c_adap, &msg, 1); priv->frequency = freq * 62500; diff --git a/linux/drivers/media/dvb/frontends/tda827x.h b/linux/drivers/media/dvb/frontends/tda827x.h index 06626f7af..92eb65b40 100644 --- a/linux/drivers/media/dvb/frontends/tda827x.h +++ b/linux/drivers/media/dvb/frontends/tda827x.h @@ -35,9 +35,6 @@ struct tda827x_config int (*sleep) (struct dvb_frontend *fe); /* interface to tda829x driver */ - unsigned char tda827x_lpsel; - unsigned int sgIF; - unsigned int *config; int (*tuner_callback) (void *dev, int command, int arg); diff --git a/linux/drivers/media/video/tda8290.c b/linux/drivers/media/video/tda8290.c index aed23ce1f..6cfc8fd92 100644 --- a/linux/drivers/media/video/tda8290.c +++ b/linux/drivers/media/video/tda8290.c @@ -133,45 +133,32 @@ static void set_audio(struct dvb_frontend *fe) struct tuner *t = priv->t; char* mode; - priv->cfg.tda827x_lpsel = 0; if (t->std & V4L2_STD_MN) { - priv->cfg.sgIF = 92; priv->tda8290_easy_mode = 0x01; - priv->cfg.tda827x_lpsel = 1; mode = "MN"; } else if (t->std & V4L2_STD_B) { - priv->cfg.sgIF = 108; priv->tda8290_easy_mode = 0x02; mode = "B"; } else if (t->std & V4L2_STD_GH) { - priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x04; mode = "GH"; } else if (t->std & V4L2_STD_PAL_I) { - priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x08; mode = "I"; } else if (t->std & V4L2_STD_DK) { - priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x10; mode = "DK"; } else if (t->std & V4L2_STD_SECAM_L) { - priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x20; mode = "L"; } else if (t->std & V4L2_STD_SECAM_LC) { - priv->cfg.sgIF = 20; priv->tda8290_easy_mode = 0x40; mode = "LC"; } else { - priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x10; mode = "xx"; } - if (t->mode == V4L2_TUNER_RADIO) - priv->cfg.sgIF = 88; /* if frequency is 5.5 MHz */ - tuner_dbg("setting tda8290 to system %s\n", mode); } @@ -397,7 +384,6 @@ static void tda8295_set_freq(struct dvb_frontend *fe, unsigned int freq) { struct tda8290_priv *priv = fe->analog_demod_priv; struct tuner *t = priv->t; - u16 ifc; unsigned char blanking_mode[] = { 0x1d, 0x00 }; @@ -410,9 +396,7 @@ static void tda8295_set_freq(struct dvb_frontend *fe, unsigned int freq) set_audio(fe); - ifc = priv->cfg.sgIF; /* FIXME */ - - tuner_dbg("%s: ifc = %u, freq = %d\n", __FUNCTION__, ifc, freq); + tuner_dbg("%s: freq = %d\n", __FUNCTION__, freq); tda8295_power(fe, 1); tda8295_agc1_out(fe, 1); @@ -654,7 +638,6 @@ int tda8290_attach(struct tuner *t) tuner_info("type set to %s\n", t->i2c.name); - priv->cfg.tda827x_lpsel = 0; t->mode = V4L2_TUNER_ANALOG_TV; tda8290_init_tuner(&t->fe); @@ -744,7 +727,6 @@ int tda8295_attach(struct tuner *t) t->fe.ops.analog_demod_ops = &tda8295_tuner_ops; - priv->cfg.tda827x_lpsel = 0; t->mode = V4L2_TUNER_ANALOG_TV; tda8295_init_if(&t->fe); -- cgit v1.2.3 From f206890c29c965f6ef422b318895e11c4039800a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 21 Oct 2007 19:48:48 -0400 Subject: make tda9887 build selectable via Kconfig From: Michael Krufky Signed-off-by: Michael Krufky Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/Kconfig | 10 +++++++++ linux/drivers/media/video/Makefile | 3 +- linux/drivers/media/video/tda9887.c | 23 ++++++++++++++------- linux/drivers/media/video/tda9887.h | 33 +++++++++++++++++++++++++++++++ linux/drivers/media/video/tuner-core.c | 3 +- linux/drivers/media/video/tuner-driver.h | 4 --- 6 files changed, 62 insertions(+), 14 deletions(-) --- linux/drivers/media/Kconfig | 10 ++++++++++ linux/drivers/media/video/Makefile | 3 ++- linux/drivers/media/video/tda9887.c | 23 ++++++++++++++-------- linux/drivers/media/video/tda9887.h | 33 ++++++++++++++++++++++++++++++++ linux/drivers/media/video/tuner-core.c | 3 ++- linux/drivers/media/video/tuner-driver.h | 4 ---- 6 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 linux/drivers/media/video/tda9887.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/Kconfig b/linux/drivers/media/Kconfig index 416d85c65..951ce4896 100644 --- a/linux/drivers/media/Kconfig +++ b/linux/drivers/media/Kconfig @@ -75,6 +75,7 @@ config VIDEO_TUNER select TUNER_TEA5761 if !VIDEO_TUNER_CUSTOMIZE select TUNER_TEA5767 if !VIDEO_TUNER_CUSTOMIZE select TUNER_SIMPLE if !VIDEO_TUNER_CUSTOMIZE + select TUNER_TDA9887 if !VIDEO_TUNER_CUSTOMIZE menuconfig VIDEO_TUNER_CUSTOMIZE bool "Customize analog tuner modules to build" @@ -130,10 +131,19 @@ config TUNER_TEA5767 config TUNER_SIMPLE tristate "Simple tuner support" depends on I2C + select TUNER_TDA9887 default m if VIDEO_TUNER_CUSTOMIZE help Say Y here to include support for various simple tuners. +config TUNER_TDA9887 + tristate "TDA 9885/6/7 analog IF demodulator" + depends on I2C + default m if VIDEO_TUNER_CUSTOMIZE + help + Say Y here to include support for Philips TDA9885/6/7 + analog IF demodulator. + endif # VIDEO_TUNER_CUSTOMIZE config VIDEOBUF_GEN diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 08ac197cc..8a2781821 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -4,7 +4,7 @@ zr36067-objs := zoran_procfs.o zoran_device.o \ zoran_driver.o zoran_card.o -tuner-objs := tuner-core.o tuner-types.o tda9887.o +tuner-objs := tuner-core.o tuner-types.o msp3400-objs := msp3400-driver.o msp3400-kthreads.o @@ -87,6 +87,7 @@ obj-$(CONFIG_TUNER_MT20XX) += mt20xx.o obj-$(CONFIG_TUNER_TDA8290) += tda8290.o obj-$(CONFIG_TUNER_TEA5767) += tea5767.o obj-$(CONFIG_TUNER_TEA5761) += tea5761.o +obj-$(CONFIG_TUNER_TDA9887) += tda9887.o obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o diff --git a/linux/drivers/media/video/tda9887.c b/linux/drivers/media/video/tda9887.c index 1edb1299f..48a7de63e 100644 --- a/linux/drivers/media/video/tda9887.c +++ b/linux/drivers/media/video/tda9887.c @@ -13,7 +13,7 @@ #endif #include #include -#include "tuner-driver.h" +#include "tda9887.h" /* Chips: @@ -24,13 +24,18 @@ Used as part of several tuners */ +static int tda9887_debug; +module_param_named(debug, tda9887_debug, int, 0644); + #define tda9887_info(fmt, arg...) do {\ printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c.name, \ - i2c_adapter_id(priv->t->i2c.adapter), priv->t->i2c.addr , ##arg); } while (0) + i2c_adapter_id(priv->t->i2c.adapter), \ + priv->t->i2c.addr, ##arg); } while (0) #define tda9887_dbg(fmt, arg...) do {\ - if (tuner_debug) \ + if (tda9887_debug) \ printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c.name, \ - i2c_adapter_id(priv->t->i2c.adapter), priv->t->i2c.addr , ##arg); } while (0) + i2c_adapter_id(priv->t->i2c.adapter), \ + priv->t->i2c.addr, ##arg); } while (0) struct tda9887_priv { struct tuner_i2c_props i2c_props; @@ -584,13 +589,13 @@ static void tda9887_configure(struct dvb_frontend *fe) tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", priv->data[1],priv->data[2],priv->data[3]); - if (tuner_debug > 1) + if (tda9887_debug > 1) dump_write_message(fe, priv->data); if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,priv->data,4))) tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); - if (tuner_debug > 2) { + if (tda9887_debug > 2) { msleep_interruptible(1000); tda9887_status(fe); } @@ -601,7 +606,8 @@ static void tda9887_configure(struct dvb_frontend *fe) static void tda9887_tuner_status(struct dvb_frontend *fe) { struct tda9887_priv *priv = fe->analog_demod_priv; - tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", priv->data[1], priv->data[2], priv->data[3]); + tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", + priv->data[1], priv->data[2], priv->data[3]); } static int tda9887_get_afc(struct dvb_frontend *fe) @@ -647,7 +653,7 @@ static struct analog_tuner_ops tda9887_tuner_ops = { .release = tda9887_release, }; -int tda9887_tuner_init(struct tuner *t) +int tda9887_attach(struct tuner *t) { struct tda9887_priv *priv = NULL; @@ -669,6 +675,7 @@ int tda9887_tuner_init(struct tuner *t) return 0; } +EXPORT_SYMBOL_GPL(tda9887_attach); /* * Overrides for Emacs so that we follow Linus's tabbing style. diff --git a/linux/drivers/media/video/tda9887.h b/linux/drivers/media/video/tda9887.h new file mode 100644 index 000000000..b879f0ec2 --- /dev/null +++ b/linux/drivers/media/video/tda9887.h @@ -0,0 +1,33 @@ +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __TDA9887_H__ +#define __TDA9887_H__ + +#include "tuner-driver.h" + +/* ------------------------------------------------------------------------ */ +#if defined(CONFIG_TUNER_TDA9887) || (defined(CONFIG_TUNER_TDA9887_MODULE) && defined(MODULE)) +extern int tda9887_attach(struct tuner *t); +#else +static inline int tda9887_attach(struct tuner *t) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return -EINVAL; +} +#endif + +#endif /* __TDA9887_H__ */ diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index ccddf55eb..e78a5c43e 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -30,6 +30,7 @@ #include "tea5767.h" #include "tuner-xc2028.h" #include "tuner-simple.h" +#include "tda9887.h" #define UNSET (-1U) @@ -371,7 +372,7 @@ static void set_type(struct i2c_client *c, unsigned int type, break; } case TUNER_TDA9887: - tda9887_tuner_init(t); + tda9887_attach(t); break; default: attach_simple_tuner(t); diff --git a/linux/drivers/media/video/tuner-driver.h b/linux/drivers/media/video/tuner-driver.h index e9d7dc061..2794e718b 100644 --- a/linux/drivers/media/video/tuner-driver.h +++ b/linux/drivers/media/video/tuner-driver.h @@ -69,10 +69,6 @@ struct tuner { /* ------------------------------------------------------------------------ */ -extern int tda9887_tuner_init(struct tuner *t); - -/* ------------------------------------------------------------------------ */ - #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) #define tuner_warn(fmt, arg...) do {\ printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->name, \ -- cgit v1.2.3 From 1c249f720732658d2c39deefcbc5eadd4d81e8bb Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 22 Oct 2007 17:03:29 -0400 Subject: tuner-core: remove excessive parenthesis From: Michael Krufky Convert all instances of "if ((ops) && (ops->foo))" to "if (ops && ops->foo)" Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-core.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) --- linux/drivers/media/video/tuner-core.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index e78a5c43e..f04c53631 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -306,7 +306,7 @@ static void set_type(struct i2c_client *c, unsigned int type, #endif /* discard private data, in case set_type() was previously called */ - if ((ops) && (ops->release)) + if (ops && ops->release) ops->release(&t->fe); switch (t->type) { @@ -779,7 +779,7 @@ static int tuner_detach(struct i2c_client *client) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) MOD_DEC_USE_COUNT; #endif - if ((ops) && (ops->release)) + if (ops && ops->release) ops->release(&t->fe); kfree(t); @@ -804,7 +804,7 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, if (check_mode(t, cmd) == EINVAL) { t->mode = T_STANDBY; - if ((ops) && (ops->standby)) + if (ops && ops->standby) ops->standby(&t->fe); return EINVAL; } @@ -861,7 +861,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL) return 0; t->mode = T_STANDBY; - if ((ops) && (ops->standby)) + if (ops && ops->standby) ops->standby(&t->fe); break; #ifdef CONFIG_VIDEO_V4L1 @@ -930,7 +930,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) else vt->flags &= ~VIDEO_TUNER_STEREO_ON; } else { - if ((ops) && (ops->is_stereo)) { + if (ops && ops->is_stereo) { if (ops->is_stereo(&t->fe)) vt->flags |= VIDEO_TUNER_STEREO_ON; @@ -939,7 +939,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) ~VIDEO_TUNER_STEREO_ON; } } - if ((ops) && (ops->has_signal)) + if (ops && ops->has_signal) vt->signal = ops->has_signal(&t->fe); vt->flags |= VIDEO_TUNER_LOW; /* Allow freqs at 62.5 Hz */ @@ -970,7 +970,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) fe_tuner_ops->get_status(&t->fe, &tuner_status); va->mode = (tuner_status & TUNER_STATUS_STEREO) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; - } else if ((ops) && (ops->is_stereo)) + } else if (ops && ops->is_stereo) va->mode = ops->is_stereo(&t->fe) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; } @@ -1061,7 +1061,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) switch_v4l2(); tuner->type = t->mode; - if ((ops) && (ops->get_afc)) + if (ops && ops->get_afc) tuner->afc = ops->get_afc(&t->fe); if (t->mode == V4L2_TUNER_ANALOG_TV) tuner->capability |= V4L2_TUNER_CAP_NORM; @@ -1083,14 +1083,14 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; } else { - if ((ops) && (ops->is_stereo)) { + if (ops && ops->is_stereo) { tuner->rxsubchans = ops->is_stereo(&t->fe) ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; } } - if ((ops) && (ops->has_signal)) + if (ops && ops->has_signal) tuner->signal = ops->has_signal(&t->fe); tuner->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; @@ -1116,7 +1116,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } case VIDIOC_LOG_STATUS: - if ((ops) && (ops->tuner_status)) + if (ops && ops->tuner_status) ops->tuner_status(&t->fe); break; } -- cgit v1.2.3 From 13158eca8802518b8b4426eb20f86aae1b512461 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 22 Oct 2007 17:15:39 -0400 Subject: tuner-core: improve comments inside function fe_release() From: Michael Krufky Explain who is responsible for freeing analog_demod_priv Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-core.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) --- linux/drivers/media/video/tuner-core.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index f04c53631..9e7cf77e0 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -128,7 +128,15 @@ static void fe_release(struct dvb_frontend *fe) fe->ops.tuner_ops.release(fe); fe->ops.analog_demod_ops = NULL; - /* DO NOT kfree(t->fe.analog_demod_priv) */ + + /* DO NOT kfree(fe->analog_demod_priv) + * + * If we are in this function, analog_demod_priv contains a pointer + * to struct tuner *t. This will be kfree'd in tuner_detach(). + * + * Otherwise, fe->ops.analog_demod_ops->release will + * handle the cleanup for analog demodulator modules. + */ fe->analog_demod_priv = NULL; } -- cgit v1.2.3 From 3c5bcbaf545783293afcf23dce8c88ead829f6c0 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 24 Oct 2007 00:00:24 -0400 Subject: tda18271: clean up debug macros From: Michael Krufky Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/tda18271.c | 76 ++++++++++++--------------- 1 file changed, 35 insertions(+), 41 deletions(-) --- linux/drivers/media/dvb/frontends/tda18271.c | 76 +++++++++++++--------------- 1 file changed, 35 insertions(+), 41 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/tda18271.c b/linux/drivers/media/dvb/frontends/tda18271.c index 83e89a54f..8916db29f 100644 --- a/linux/drivers/media/dvb/frontends/tda18271.c +++ b/linux/drivers/media/dvb/frontends/tda18271.c @@ -28,13 +28,9 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -#define tuner_dbg(fmt, arg...) do {\ - if (debug > 0) \ - printk(KERN_DEBUG fmt, ##arg); } while (0) - -#define tuner_extra_dbg(fmt, arg...) do {\ - if (debug > 1) \ - printk(KERN_DEBUG fmt, ##arg); } while (0) +#define dprintk(level, fmt, arg...) do {\ + if (debug >= level) \ + printk(KERN_DEBUG "%s: " fmt, __FUNCTION__, ##arg); } while (0) #define R_ID 0x00 /* ID byte */ #define R_TM 0x01 /* Thermo byte */ @@ -335,23 +331,23 @@ static void tda18271_dump_regs(struct dvb_frontend *fe) struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; - tuner_dbg("=== TDA18271 REG DUMP ===\n"); - tuner_dbg("ID_BYTE = 0x%x\n", 0xff & regs[R_ID]); - tuner_dbg("THERMO_BYTE = 0x%x\n", 0xff & regs[R_TM]); - tuner_dbg("POWER_LEVEL_BYTE = 0x%x\n", 0xff & regs[R_PL]); - tuner_dbg("EASY_PROG_BYTE_1 = 0x%x\n", 0xff & regs[R_EP1]); - tuner_dbg("EASY_PROG_BYTE_2 = 0x%x\n", 0xff & regs[R_EP2]); - tuner_dbg("EASY_PROG_BYTE_3 = 0x%x\n", 0xff & regs[R_EP3]); - tuner_dbg("EASY_PROG_BYTE_4 = 0x%x\n", 0xff & regs[R_EP4]); - tuner_dbg("EASY_PROG_BYTE_5 = 0x%x\n", 0xff & regs[R_EP5]); - tuner_dbg("CAL_POST_DIV_BYTE = 0x%x\n", 0xff & regs[R_CPD]); - tuner_dbg("CAL_DIV_BYTE_1 = 0x%x\n", 0xff & regs[R_CD1]); - tuner_dbg("CAL_DIV_BYTE_2 = 0x%x\n", 0xff & regs[R_CD2]); - tuner_dbg("CAL_DIV_BYTE_3 = 0x%x\n", 0xff & regs[R_CD3]); - tuner_dbg("MAIN_POST_DIV_BYTE = 0x%x\n", 0xff & regs[R_MPD]); - tuner_dbg("MAIN_DIV_BYTE_1 = 0x%x\n", 0xff & regs[R_MD1]); - tuner_dbg("MAIN_DIV_BYTE_2 = 0x%x\n", 0xff & regs[R_MD2]); - tuner_dbg("MAIN_DIV_BYTE_3 = 0x%x\n", 0xff & regs[R_MD3]); + dprintk(1, "=== TDA18271 REG DUMP ===\n"); + dprintk(1, "ID_BYTE = 0x%x\n", 0xff & regs[R_ID]); + dprintk(1, "THERMO_BYTE = 0x%x\n", 0xff & regs[R_TM]); + dprintk(1, "POWER_LEVEL_BYTE = 0x%x\n", 0xff & regs[R_PL]); + dprintk(1, "EASY_PROG_BYTE_1 = 0x%x\n", 0xff & regs[R_EP1]); + dprintk(1, "EASY_PROG_BYTE_2 = 0x%x\n", 0xff & regs[R_EP2]); + dprintk(1, "EASY_PROG_BYTE_3 = 0x%x\n", 0xff & regs[R_EP3]); + dprintk(1, "EASY_PROG_BYTE_4 = 0x%x\n", 0xff & regs[R_EP4]); + dprintk(1, "EASY_PROG_BYTE_5 = 0x%x\n", 0xff & regs[R_EP5]); + dprintk(1, "CAL_POST_DIV_BYTE = 0x%x\n", 0xff & regs[R_CPD]); + dprintk(1, "CAL_DIV_BYTE_1 = 0x%x\n", 0xff & regs[R_CD1]); + dprintk(1, "CAL_DIV_BYTE_2 = 0x%x\n", 0xff & regs[R_CD2]); + dprintk(1, "CAL_DIV_BYTE_3 = 0x%x\n", 0xff & regs[R_CD3]); + dprintk(1, "MAIN_POST_DIV_BYTE = 0x%x\n", 0xff & regs[R_MPD]); + dprintk(1, "MAIN_DIV_BYTE_1 = 0x%x\n", 0xff & regs[R_MD1]); + dprintk(1, "MAIN_DIV_BYTE_2 = 0x%x\n", 0xff & regs[R_MD2]); + dprintk(1, "MAIN_DIV_BYTE_3 = 0x%x\n", 0xff & regs[R_MD3]); } static void tda18271_read_regs(struct dvb_frontend *fe) @@ -619,7 +615,7 @@ static int tda18271_tune(struct dvb_frontend *fe, freq = freq / 1000; #endif - tuner_dbg("%s: freq = %d, ifc = %d\n", __FUNCTION__, freq, ifc); + dprintk(1, "freq = %d, ifc = %d\n", freq, ifc); tda18271_init_regs(fe); /* RF tracking filter calibration */ @@ -631,8 +627,7 @@ static int tda18271_tune(struct dvb_frontend *fe, break; i++; } - tuner_extra_dbg("bp filter = 0x%x, i = %d\n", - tda18271_bp_filter[i].val, i); + dprintk(2, "bp filter = 0x%x, i = %d\n", tda18271_bp_filter[i].val, i); regs[R_EP1] &= ~0x07; /* clear bp filter bits */ regs[R_EP1] |= tda18271_bp_filter[i].val; @@ -671,8 +666,8 @@ static int tda18271_tune(struct dvb_frontend *fe, break; i++; } - tuner_extra_dbg("cal pll, pd = 0x%x, d = 0x%x, i = %d\n", - tda18271_cal_pll[i].pd, tda18271_cal_pll[i].d, i); + dprintk(2, "cal pll, pd = 0x%x, d = 0x%x, i = %d\n", + tda18271_cal_pll[i].pd, tda18271_cal_pll[i].d, i); regs[R_CPD] = tda18271_cal_pll[i].pd; @@ -698,8 +693,8 @@ static int tda18271_tune(struct dvb_frontend *fe, break; i++; } - tuner_extra_dbg("main pll, pd = 0x%x, d = 0x%x, i = %d\n", - tda18271_main_pll[i].pd, tda18271_main_pll[i].d, i); + dprintk(2, "main pll, pd = 0x%x, d = 0x%x, i = %d\n", + tda18271_main_pll[i].pd, tda18271_main_pll[i].d, i); regs[R_MPD] = (0x7f & tda18271_main_pll[i].pd); @@ -727,7 +722,7 @@ static int tda18271_tune(struct dvb_frontend *fe, break; i++; } - tuner_extra_dbg("km = 0x%x, i = %d\n", tda18271_km[i].val, i); + dprintk(2, "km = 0x%x, i = %d\n", tda18271_km[i].val, i); regs[R_EB13] &= 0x83; regs[R_EB13] |= tda18271_km[i].val; @@ -740,8 +735,7 @@ static int tda18271_tune(struct dvb_frontend *fe, break; i++; } - tuner_extra_dbg("rf band = 0x%x, i = %d\n", - tda18271_rf_band[i].val, i); + dprintk(2, "rf band = 0x%x, i = %d\n", tda18271_rf_band[i].val, i); regs[R_EP2] &= ~0xe0; /* clear rf band bits */ regs[R_EP2] |= (tda18271_rf_band[i].val << 5); @@ -753,8 +747,8 @@ static int tda18271_tune(struct dvb_frontend *fe, break; i++; } - tuner_extra_dbg("gain taper = 0x%x, i = %d\n", - tda18271_gain_taper[i].val, i); + dprintk(2, "gain taper = 0x%x, i = %d\n", + tda18271_gain_taper[i].val, i); regs[R_EP2] &= ~0x1f; /* clear gain taper bits */ regs[R_EP2] |= tda18271_gain_taper[i].val; @@ -788,7 +782,7 @@ static int tda18271_tune(struct dvb_frontend *fe, break; i++; } - tuner_extra_dbg("rf cal = 0x%x, i = %d\n", tda18271_rf_cal[i].val, i); + dprintk(2, "rf cal = 0x%x, i = %d\n", tda18271_rf_cal[i].val, i); /* VHF_Low band only */ if (tda18271_rf_cal[i].rfmax != 0) { @@ -852,8 +846,8 @@ static int tda18271_tune(struct dvb_frontend *fe, break; i++; } - tuner_extra_dbg("main pll, pd = 0x%x, d = 0x%x, i = %d\n", - tda18271_main_pll[i].pd, tda18271_main_pll[i].d, i); + dprintk(2, "main pll, pd = 0x%x, d = 0x%x, i = %d\n", + tda18271_main_pll[i].pd, tda18271_main_pll[i].d, i); regs[R_MPD] = (0x7f & tda18271_main_pll[i].pd); switch (priv->mode) { @@ -987,7 +981,7 @@ static int tda18271_set_analog_params(struct dvb_frontend *fe, if (params->mode == V4L2_TUNER_RADIO) sgIF = 88; /* if frequency is 5.5 MHz */ - tuner_dbg("setting tda18271 to system %s\n", mode); + dprintk(1, "setting tda18271 to system %s\n", mode); return tda18271_tune(fe, sgIF * 62500, params->frequency * 62500, 0, std); @@ -1033,7 +1027,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, { struct tda18271_priv *priv = NULL; - tuner_dbg("%s:\n", __FUNCTION__); + dprintk(1, "@ 0x%x\n", addr); priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL); if (priv == NULL) return NULL; -- cgit v1.2.3 From 0c2c3851d68bcc621a0e4c3d3b9469da047ed7b7 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 24 Oct 2007 08:23:17 -0400 Subject: tuner: add i2c_gate_ctrl function to struct analog_tuner_ops From: Michael Krufky In some designs, the tuner silicon may be on an i2c bus behind an i2c gate, controlled by the analog demodulator. We already have a method to control such i2c gates when they are controlled by the digital demodulator, but in some hybrid designs, there may be an i2c gate controlled by each demodulator. For example, when in analog tuning mode, one would access the tuner by opening the i2c gate controlled by the analog demodulator, while when in digital tuning mode, one would access the tuner by opening the i2c gate controlled by the digital demodulator. We must add this callback function to analog_tuner_ops in order to handle such configurations. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-driver.h | 1 + 1 file changed, 1 insertion(+) --- linux/drivers/media/video/tuner-driver.h | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-driver.h b/linux/drivers/media/video/tuner-driver.h index 2794e718b..ad2d57dfb 100644 --- a/linux/drivers/media/video/tuner-driver.h +++ b/linux/drivers/media/video/tuner-driver.h @@ -40,6 +40,7 @@ struct analog_tuner_ops { void (*tuner_status)(struct dvb_frontend *fe); void (*standby)(struct dvb_frontend *fe); void (*release)(struct dvb_frontend *fe); + int (*i2c_gate_ctrl)(struct dvb_frontend *fe, int enable); }; struct tuner { -- cgit v1.2.3 From 45e16ceff61bbe8a9d94d5967d909b901bed82bb Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 24 Oct 2007 08:30:17 -0400 Subject: tda8290: fill i2c_gate_ctrl callback From: Michael Krufky Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tda8290.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) --- linux/drivers/media/video/tda8290.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tda8290.c b/linux/drivers/media/video/tda8290.c index 6cfc8fd92..e4946f9dc 100644 --- a/linux/drivers/media/video/tda8290.c +++ b/linux/drivers/media/video/tda8290.c @@ -59,14 +59,15 @@ struct tda8290_priv { /*---------------------------------------------------------------------*/ -static void tda8290_i2c_bridge(struct dvb_frontend *fe, int close) +static int tda8290_i2c_bridge(struct dvb_frontend *fe, int close) { struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char enable[2] = { 0x21, 0xC0 }; unsigned char disable[2] = { 0x21, 0x00 }; unsigned char *msg; - if(close) { + + if (close) { msg = enable; tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); /* let the bridge stabilize */ @@ -75,10 +76,12 @@ static void tda8290_i2c_bridge(struct dvb_frontend *fe, int close) msg = disable; tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); } + + return 0; } #if 1 -static void tda8295_i2c_bridge(struct dvb_frontend *fe, int close) +static int tda8295_i2c_bridge(struct dvb_frontend *fe, int close) { struct tda8290_priv *priv = fe->analog_demod_priv; @@ -86,6 +89,7 @@ static void tda8295_i2c_bridge(struct dvb_frontend *fe, int close) unsigned char disable[2] = { 0x46, 0x00 }; unsigned char buf[3] = { 0x45, 0x01, 0x00 }; unsigned char *msg; + if (close) { msg = enable; tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); @@ -104,9 +108,11 @@ static void tda8295_i2c_bridge(struct dvb_frontend *fe, int close) msg[1] |= 0x04; tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); } + + return 0; } #else -static void tda8295_i2c_bridge(struct dvb_frontend *fe, int close) +static int tda8295_i2c_bridge(struct dvb_frontend *fe, int close) { struct tda8290_priv *priv = fe->analog_demod_priv; @@ -122,6 +128,8 @@ static void tda8295_i2c_bridge(struct dvb_frontend *fe, int close) buf[1] |= 0x80; tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); + + return 0; } #endif @@ -546,6 +554,7 @@ static struct analog_tuner_ops tda8290_tuner_ops = { .has_signal = tda8290_has_signal, .standby = tda8290_standby, .release = tda829x_release, + .i2c_gate_ctrl = tda8290_i2c_bridge, }; static struct analog_tuner_ops tda8295_tuner_ops = { @@ -554,6 +563,7 @@ static struct analog_tuner_ops tda8295_tuner_ops = { .has_signal = tda8295_has_signal, .standby = tda8295_standby, .release = tda829x_release, + .i2c_gate_ctrl = tda8295_i2c_bridge, }; int tda8290_attach(struct tuner *t) -- cgit v1.2.3 From d34b4355e00c810272a89a506d26385553ae23e2 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 24 Oct 2007 08:55:54 -0400 Subject: tda18271: clean up i2c_gate handling From: Michael Krufky Call analog_demod_ops->i2c_gate_ctrl when in analog tuning mode, and frontend_ops.i2c_gate_ctrl when in digital tuning mode. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/Makefile | 1 linux/drivers/media/dvb/frontends/tda18271.c | 33 ++++++++++++++++++++------- 2 files changed, 26 insertions(+), 8 deletions(-) --- linux/drivers/media/dvb/frontends/Makefile | 1 + linux/drivers/media/dvb/frontends/tda18271.c | 33 +++++++++++++++++++++------- 2 files changed, 26 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile index 457effcda..57e5fa805 100644 --- a/linux/drivers/media/dvb/frontends/Makefile +++ b/linux/drivers/media/dvb/frontends/Makefile @@ -3,6 +3,7 @@ # EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ +EXTRA_CFLAGS += -Idrivers/media/video/ obj-$(CONFIG_DVB_PLL) += dvb-pll.o obj-$(CONFIG_DVB_STV0299) += stv0299.o diff --git a/linux/drivers/media/dvb/frontends/tda18271.c b/linux/drivers/media/dvb/frontends/tda18271.c index 8916db29f..bc84465c7 100644 --- a/linux/drivers/media/dvb/frontends/tda18271.c +++ b/linux/drivers/media/dvb/frontends/tda18271.c @@ -21,6 +21,7 @@ #include #include #include +#include "tuner-driver.h" #include "tda18271.h" @@ -324,6 +325,26 @@ struct tda18271_priv { u32 bandwidth; }; +static int tda18271_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + struct tda18271_priv *priv = fe->tuner_priv; + struct analog_tuner_ops *ops = fe->ops.analog_demod_ops; + int ret = 0; + + switch (priv->mode) { + case TDA18271_ANALOG: + if (ops && ops->i2c_gate_ctrl) + ret = ops->i2c_gate_ctrl(fe, enable); + break; + case TDA18271_DIGITAL: + if (fe->ops.i2c_gate_ctrl) + ret = fe->ops.i2c_gate_ctrl(fe, enable); + break; + } + + return ret; +}; + /*---------------------------------------------------------------------*/ static void tda18271_dump_regs(struct dvb_frontend *fe) @@ -363,14 +384,12 @@ static void tda18271_read_regs(struct dvb_frontend *fe) .buf = regs, .len = 16 } }; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); + tda18271_i2c_gate_ctrl(fe, 1); /* read all registers */ ret = i2c_transfer(priv->i2c_adap, msg, 2); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); + tda18271_i2c_gate_ctrl(fe, 0); if (ret != 2) printk("ERROR: %s: i2c_transfer returned: %d\n", @@ -396,14 +415,12 @@ static void tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) buf[i] = regs[idx-1+i]; } - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); + tda18271_i2c_gate_ctrl(fe, 1); /* write registers */ ret = i2c_transfer(priv->i2c_adap, &msg, 1); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); + tda18271_i2c_gate_ctrl(fe, 0); if (ret != 1) printk(KERN_WARNING "ERROR: %s: i2c_transfer returned: %d\n", -- cgit v1.2.3 From 55c585d89d06e29009f8bdc652c54e3de0993c4a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 27 Oct 2007 01:17:19 -0400 Subject: tda9887: add missing module license From: Michael Krufky This module was always GPL, and will remain GPL Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tda9887.c | 2 ++ 1 file changed, 2 insertions(+) --- linux/drivers/media/video/tda9887.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tda9887.c b/linux/drivers/media/video/tda9887.c index 48a7de63e..e21345147 100644 --- a/linux/drivers/media/video/tda9887.c +++ b/linux/drivers/media/video/tda9887.c @@ -677,6 +677,8 @@ int tda9887_attach(struct tuner *t) } EXPORT_SYMBOL_GPL(tda9887_attach); +MODULE_LICENSE("GPL"); + /* * Overrides for Emacs so that we follow Linus's tabbing style. * --------------------------------------------------------------------------- -- cgit v1.2.3 From 30e50fe332679825e6f54936c7c5e97bf109584d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 12 Sep 2007 13:32:50 +0200 Subject: v4l2: add support for bus-based I2C drivers From: Hans Verkuil Two new headers were added: one for I2C drivers that are only used by V4L2 drivers converted to the new bus-based I2C API, and one that can be used by both converted and unconverted drivers (at the expense of some additional overhead). To support the legacy I2C API a helper function was added to v4l2-common.c. These headers take care of all the 'boilerplate' code that all V4L2 I2C drivers have in common and will automatically support the bus-based I2C API introduced in kernel 2.6.22. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-common.c | 37 +++++ linux/include/media/v4l2-common.h | 11 + linux/include/media/v4l2-i2c-drv-legacy.h | 207 ++++++++++++++++++++++++++++++ linux/include/media/v4l2-i2c-drv.h | 199 ++++++++++++++++++++++++++++ 4 files changed, 454 insertions(+) --- linux/drivers/media/video/v4l2-common.c | 37 +++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 476b5ea5a..ef4514369 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -1625,6 +1625,41 @@ int v4l2_chip_match_host(u32 match_type, u32 match_chip) /* ----------------------------------------------------------------- */ +/* Helper function for I2C legacy drivers */ + +int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver *driver, + const char *name, int (*probe)(struct i2c_client *)) +{ + struct i2c_client *client; + int err; + + client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (client == 0) + return -ENOMEM; + + client->addr = address; + client->adapter = adapter; + client->driver = driver; +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) + client->flags = I2C_CLIENT_ALLOW_USE; +#endif + snprintf(client->name, sizeof(client->name) - 1, name); + + err = probe(client); + if (err == 0) { + i2c_attach_client(client); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + MOD_INC_USE_COUNT; +#endif + } + else { + kfree(client); + } + return err; +} + +/* ----------------------------------------------------------------- */ + EXPORT_SYMBOL(v4l2_norm_to_name); EXPORT_SYMBOL(v4l2_video_std_construct); @@ -1650,6 +1685,8 @@ EXPORT_SYMBOL(v4l2_chip_match_i2c_client); EXPORT_SYMBOL(v4l2_chip_ident_i2c_client); EXPORT_SYMBOL(v4l2_chip_match_host); +EXPORT_SYMBOL(v4l2_i2c_attach); + /* * Local variables: * c-basic-offset: 8 -- cgit v1.2.3 From 9ffc9b84fc6de477f366efda9e590838e05bcc98 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 13 Sep 2007 16:08:25 +0200 Subject: wm8775: convert to bus-based I2C API. From: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/wm8775.c | 102 +++++-------------------------------- 1 file changed, 14 insertions(+), 88 deletions(-) --- linux/drivers/media/video/wm8775.c | 102 +++++-------------------------------- 1 file changed, 14 insertions(+), 88 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/wm8775.c b/linux/drivers/media/video/wm8775.c index 7e3734f00..95167d4bf 100644 --- a/linux/drivers/media/video/wm8775.c +++ b/linux/drivers/media/video/wm8775.c @@ -34,6 +34,7 @@ #include #include #include +#include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "i2c-compat.h" #include @@ -52,6 +53,7 @@ static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; I2C_CLIENT_INSMOD; + /* ----------------------------------------------------------------------- */ enum { @@ -84,8 +86,7 @@ static int wm8775_write(struct i2c_client *client, int reg, u16 val) return -1; } -static int wm8775_command(struct i2c_client *client, unsigned int cmd, - void *arg) +static int wm8775_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct wm8775_state *state = i2c_get_clientdata(client); struct v4l2_routing *route = arg; @@ -167,39 +168,18 @@ static int wm8775_command(struct i2c_client *client, unsigned int cmd, * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' */ -static struct i2c_driver i2c_driver; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -static int wm8775_attach(struct i2c_adapter *adapter, int address, int kind) -#else -static int wm8775_attach(struct i2c_adapter *adapter, int address, - unsigned short flags, int kind) -#endif +static int wm8775_probe(struct i2c_client *client) { - struct i2c_client *client; struct wm8775_state *state; /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == 0) - return -ENOMEM; - - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - client->flags = I2C_CLIENT_ALLOW_USE; -#endif - snprintf(client->name, sizeof(client->name) - 1, "wm8775"); - - v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name); + v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); state = kmalloc(sizeof(struct wm8775_state), GFP_KERNEL); if (state == NULL) { - kfree(client); return -ENOMEM; } state->input = 2; @@ -224,77 +204,23 @@ static int wm8775_attach(struct i2c_adapter *adapter, int address, wm8775_write(client, R20, 0x07a); /* Transient window 4ms, lower PGA gain */ /* limit -1dB */ wm8775_write(client, R21, 0x102); /* LRBOTH = 1, use input 2. */ - i2c_attach_client(client); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_INC_USE_COUNT; -#endif return 0; } -static int wm8775_probe(struct i2c_adapter *adapter) +static int wm8775_remove(struct i2c_client *client) { -#ifdef I2C_CLASS_TV_ANALOG - if (adapter->class & I2C_CLASS_TV_ANALOG) -#else - if (adapter->id == I2C_HW_B_BT848) -#endif - return i2c_probe(adapter, &addr_data, wm8775_attach); + kfree(i2c_get_clientdata(client)); return 0; } -static int wm8775_detach(struct i2c_client *client) -{ - struct wm8775_state *state = i2c_get_clientdata(client); - int err; - - err = i2c_detach_client(client); - if (err) { - return err; - } - kfree(state); - kfree(client); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_DEC_USE_COUNT; -#endif - return 0; -} - -/* ----------------------------------------------------------------------- */ - -/* i2c implementation */ -static struct i2c_driver i2c_driver = { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))&&(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)) - .owner = THIS_MODULE, -#endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) +static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "wm8775", - .flags = I2C_DF_NOTIFY, -#else - .driver = { - .name = "wm8775", - }, -#endif - .id = I2C_DRIVERID_WM8775, - .attach_adapter = wm8775_probe, - .detach_client = wm8775_detach, - .command = wm8775_command, + .driverid = I2C_DRIVERID_WM8775, + .command = wm8775_command, + .probe = wm8775_probe, + .remove = wm8775_remove, }; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) EXPORT_NO_SYMBOLS; #endif - -static int __init wm8775_init_module(void) -{ - return i2c_add_driver(&i2c_driver); -} - -static void __exit wm8775_cleanup_module(void) -{ - i2c_del_driver(&i2c_driver); -} - -module_init(wm8775_init_module); -module_exit(wm8775_cleanup_module); -- cgit v1.2.3 From 9d69c811776a2ca50f901effcb999e8662d5c504 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 13 Sep 2007 16:10:07 +0200 Subject: wm8739: convert to bus-based I2C API. From: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/wm8739.c | 98 ++++--------------------------------- 1 file changed, 12 insertions(+), 86 deletions(-) --- linux/drivers/media/video/wm8739.c | 98 +++++--------------------------------- 1 file changed, 12 insertions(+), 86 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/wm8739.c b/linux/drivers/media/video/wm8739.c index 999c25a30..953c47ed4 100644 --- a/linux/drivers/media/video/wm8739.c +++ b/linux/drivers/media/video/wm8739.c @@ -30,6 +30,7 @@ #include #include #include +#include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "i2c-compat.h" #include @@ -271,35 +272,11 @@ static int wm8739_command(struct i2c_client *client, unsigned int cmd, void *arg /* i2c implementation */ -static struct i2c_driver i2c_driver; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -static int wm8739_attach(struct i2c_adapter *adapter, int address, int kind) -#else -static int wm8739_attach(struct i2c_adapter *adapter, int address, - unsigned short flags, int kind) -#endif +static int wm8739_probe(struct i2c_client *client) { - struct i2c_client *client; struct wm8739_state *state; - /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; - - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == NULL) - return -ENOMEM; - - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - client->flags = I2C_CLIENT_ALLOW_USE; -#endif - snprintf(client->name, sizeof(client->name) - 1, "wm8739"); - - v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name); + v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); state = kmalloc(sizeof(struct wm8739_state), GFP_KERNEL); if (state == NULL) { @@ -326,77 +303,26 @@ static int wm8739_attach(struct i2c_adapter *adapter, int address, /* normal, 256fs, 48KHz sampling rate */ wm8739_write(client, R9, 0x001); /* activate */ wm8739_set_audio(client); /* set volume/mute */ - - i2c_attach_client(client); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_INC_USE_COUNT; -#endif - return 0; -} - -static int wm8739_probe(struct i2c_adapter *adapter) -{ -#ifdef I2C_CLASS_TV_ANALOG - if (adapter->class & I2C_CLASS_TV_ANALOG) -#else - if (adapter->id == I2C_HW_B_CX2341X) -#endif - return i2c_probe(adapter, &addr_data, wm8739_attach); return 0; } -static int wm8739_detach(struct i2c_client *client) +static int wm8739_remove(struct i2c_client *client) { - struct wm8739_state *state = i2c_get_clientdata(client); - int err; - - err = i2c_detach_client(client); - if (err) - return err; - - kfree(state); - kfree(client); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_DEC_USE_COUNT; -#endif + kfree(i2c_get_clientdata(client)); return 0; } -/* ----------------------------------------------------------------------- */ - -/* i2c implementation */ -static struct i2c_driver i2c_driver = { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - .owner = THIS_MODULE, -#endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) +static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "wm8739", - .flags = I2C_DF_NOTIFY, -#else - .driver = { - .name = "wm8739", - }, -#endif - .id = I2C_DRIVERID_WM8739, - .attach_adapter = wm8739_probe, - .detach_client = wm8739_detach, + .driverid = I2C_DRIVERID_WM8739, .command = wm8739_command, + .probe = wm8739_probe, + .remove = wm8739_remove, +#ifndef I2C_CLASS_TV_ANALOG + .legacy_id = I2C_HW_B_CX2341X, +#endif }; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) EXPORT_NO_SYMBOLS; #endif - -static int __init wm8739_init_module(void) -{ - return i2c_add_driver(&i2c_driver); -} - -static void __exit wm8739_cleanup_module(void) -{ - i2c_del_driver(&i2c_driver); -} - -module_init(wm8739_init_module); -module_exit(wm8739_cleanup_module); -- cgit v1.2.3 From 1c075a9a2e3818c754a21540d36985de92fe4434 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 13 Sep 2007 16:11:44 +0200 Subject: vp27smpx: convert to bus-based I2C API. From: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/vp27smpx.c | 96 +++++------------------------------ 1 file changed, 14 insertions(+), 82 deletions(-) --- linux/drivers/media/video/vp27smpx.c | 96 ++++++------------------------------ 1 file changed, 14 insertions(+), 82 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/vp27smpx.c b/linux/drivers/media/video/vp27smpx.c index 3793930fe..fae69bee7 100644 --- a/linux/drivers/media/video/vp27smpx.c +++ b/linux/drivers/media/video/vp27smpx.c @@ -30,6 +30,7 @@ #include #include #include +#include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "i2c-compat.h" #include @@ -81,8 +82,7 @@ static void vp27smpx_set_audmode(struct i2c_client *client, u32 audmode) } } -static int vp27smpx_command(struct i2c_client *client, unsigned int cmd, - void *arg) +static int vp27smpx_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct vp27smpx_state *state = i2c_get_clientdata(client); struct v4l2_tuner *vt = arg; @@ -133,39 +133,20 @@ static int vp27smpx_command(struct i2c_client *client, unsigned int cmd, * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' */ -static struct i2c_driver i2c_driver; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -static int vp27smpx_attach(struct i2c_adapter *adapter, int address, int kind) -#else -static int vp27smpx_attach(struct i2c_adapter *adapter, int address, - unsigned short flags, int kind) -#endif +static int vp27smpx_probe(struct i2c_client *client) { - struct i2c_client *client; struct vp27smpx_state *state; /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return 0; - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == 0) - return -ENOMEM; - - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - client->flags = I2C_CLIENT_ALLOW_USE; -#endif snprintf(client->name, sizeof(client->name) - 1, "vp27smpx"); - v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name); + v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); state = kzalloc(sizeof(struct vp27smpx_state), GFP_KERNEL); if (state == NULL) { - kfree(client); return -ENOMEM; } state->audmode = V4L2_TUNER_MODE_STEREO; @@ -173,77 +154,28 @@ static int vp27smpx_attach(struct i2c_adapter *adapter, int address, /* initialize vp27smpx */ vp27smpx_set_audmode(client, state->audmode); - i2c_attach_client(client); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_INC_USE_COUNT; -#endif return 0; } -static int vp27smpx_probe(struct i2c_adapter *adapter) +static int vp27smpx_remove(struct i2c_client *client) { -#ifdef I2C_CLASS_TV_ANALOG - if (adapter->class & I2C_CLASS_TV_ANALOG) -#else - if (adapter->id == I2C_HW_B_CX2341X) -#endif - return i2c_probe(adapter, &addr_data, vp27smpx_attach); - return 0; -} - -static int vp27smpx_detach(struct i2c_client *client) -{ - struct vp27smpx_state *state = i2c_get_clientdata(client); - int err; - - err = i2c_detach_client(client); - if (err) { - return err; - } - kfree(state); - kfree(client); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_DEC_USE_COUNT; -#endif + kfree(i2c_get_clientdata(client)); return 0; } /* ----------------------------------------------------------------------- */ -/* i2c implementation */ -static struct i2c_driver i2c_driver = { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))&&(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)) - .owner = THIS_MODULE, -#endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) +static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "vp27smpx", - .flags = I2C_DF_NOTIFY, -#else - .driver = { - .name = "vp27smpx", - }, + .driverid = I2C_DRIVERID_VP27SMPX, + .command = vp27smpx_command, + .probe = vp27smpx_probe, + .remove = vp27smpx_remove, +#ifndef I2C_CLASS_TV_ANALOG + .legacy_id = I2C_HW_B_CX2341X, #endif - .id = I2C_DRIVERID_VP27SMPX, - .attach_adapter = vp27smpx_probe, - .detach_client = vp27smpx_detach, - .command = vp27smpx_command, }; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) EXPORT_NO_SYMBOLS; #endif - -static int __init vp27smpx_init_module(void) -{ - return i2c_add_driver(&i2c_driver); -} - -static void __exit vp27smpx_cleanup_module(void) -{ - i2c_del_driver(&i2c_driver); -} - -module_init(vp27smpx_init_module); -module_exit(vp27smpx_cleanup_module); -- cgit v1.2.3 From 4d368aaf926955adb0448c712f07327e0b16a662 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 13 Sep 2007 16:19:39 +0200 Subject: saa7115: convert to bus-based I2C API From: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7115.c | 102 ++++++------------------------------ 1 file changed, 17 insertions(+), 85 deletions(-) --- linux/drivers/media/video/saa7115.c | 102 ++++++------------------------------ 1 file changed, 17 insertions(+), 85 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c index 74c89b458..3d4020921 100644 --- a/linux/drivers/media/video/saa7115.c +++ b/linux/drivers/media/video/saa7115.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "i2c-compat.h" @@ -1241,7 +1242,7 @@ static void saa711x_decode_vbi_line(struct i2c_client *client, /* ============ SAA7115 AUDIO settings (end) ============= */ -static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *arg) +static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct saa711x_state *state = i2c_get_clientdata(client); @@ -1460,34 +1461,17 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar /* ----------------------------------------------------------------------- */ -static struct i2c_driver i2c_driver_saa711x; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -static int saa711x_attach(struct i2c_adapter *adapter, int address, - unsigned short flags, int kind) -#else -static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind) -#endif +static int saa7115_probe(struct i2c_client *client) { - struct i2c_client *client; struct saa711x_state *state; int i; char name[17]; u8 chip_id; /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return 0; - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == 0) - return -ENOMEM; - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver_saa711x; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - client->flags = I2C_CLIENT_ALLOW_USE; -#endif snprintf(client->name, sizeof(client->name) - 1, "saa7115"); for (i = 0; i < 0x0f; i++) { @@ -1504,18 +1488,16 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind) /* Check whether this chip is part of the saa711x series */ if (memcmp(name, "1f711", 5)) { v4l_dbg(1, debug, client, "chip found @ 0x%x (ID %s) does not match a known saa711x chip.\n", - address << 1, name); - kfree(client); + client->addr << 1, name); return 0; } snprintf(client->name, sizeof(client->name) - 1, "saa711%d",chip_id); - v4l_info(client, "saa711%d found (%s) @ 0x%x (%s)\n", chip_id, name, address << 1, adapter->name); + v4l_info(client, "saa711%d found (%s) @ 0x%x (%s)\n", chip_id, name, client->addr << 1, client->adapter->name); state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL); i2c_set_clientdata(client, state); if (state == NULL) { - kfree(client); return -ENOMEM; } state->input = -1; @@ -1568,80 +1550,30 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind) saa711x_writeregs(client, saa7115_init_misc); saa711x_set_v4lstd(client, V4L2_STD_NTSC); - i2c_attach_client(client); - v4l_dbg(1, debug, client, "status: (1E) 0x%02x, (1F) 0x%02x\n", saa711x_read(client, R_1E_STATUS_BYTE_1_VD_DEC), saa711x_read(client, R_1F_STATUS_BYTE_2_VD_DEC)); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_INC_USE_COUNT; -#endif return 0; } -static int saa711x_probe(struct i2c_adapter *adapter) -{ -#ifdef I2C_CLASS_TV_ANALOG - if (adapter->class & I2C_CLASS_TV_ANALOG || adapter->class & I2C_CLASS_TV_DIGITAL) -#else - if (adapter->id == I2C_HW_B_BT848) -#endif - return i2c_probe(adapter, &addr_data, &saa711x_attach); - return 0; -} +/* ----------------------------------------------------------------------- */ -static int saa711x_detach(struct i2c_client *client) +static int saa7115_remove(struct i2c_client *client) { - struct saa711x_state *state = i2c_get_clientdata(client); - int err; - - err = i2c_detach_client(client); - if (err) { - return err; - } - - kfree(state); - kfree(client); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_DEC_USE_COUNT; -#endif + kfree(i2c_get_clientdata(client)); return 0; } -/* ----------------------------------------------------------------------- */ - -/* i2c implementation */ -static struct i2c_driver i2c_driver_saa711x = { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) &&(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)) - .owner = THIS_MODULE, -#endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) +static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa7115", - .flags = I2C_DF_NOTIFY, -#else - .driver = { - .name = "saa7115", - }, + .driverid = I2C_DRIVERID_SAA711X, + .command = saa7115_command, + .probe = saa7115_probe, + .remove = saa7115_remove, +#ifdef I2C_CLASS_TV_ANALOG + .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, #endif - .id = I2C_DRIVERID_SAA711X, - .attach_adapter = saa711x_probe, - .detach_client = saa711x_detach, - .command = saa711x_command, }; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) EXPORT_NO_SYMBOLS; #endif - -static int __init saa711x_init_module(void) -{ - return i2c_add_driver(&i2c_driver_saa711x); -} - -static void __exit saa711x_cleanup_module(void) -{ - i2c_del_driver(&i2c_driver_saa711x); -} - -module_init(saa711x_init_module); -module_exit(saa711x_cleanup_module); -- cgit v1.2.3 From acd79c943b2564edc9ae1752174da3897f84eac0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 13 Sep 2007 16:21:51 +0200 Subject: saa7127: convert to bus-based I2C API. From: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7127.c | 109 ++++-------------------------------- 1 file changed, 13 insertions(+), 96 deletions(-) --- linux/drivers/media/video/saa7127.c | 109 +++++------------------------------- 1 file changed, 13 insertions(+), 96 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7127.c b/linux/drivers/media/video/saa7127.c index 17c3078c3..95e0f998a 100644 --- a/linux/drivers/media/video/saa7127.c +++ b/linux/drivers/media/video/saa7127.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "i2c-compat.h" @@ -674,39 +675,19 @@ static int saa7127_command(struct i2c_client *client, /* ----------------------------------------------------------------------- */ -static struct i2c_driver i2c_driver_saa7127; - -/* ----------------------------------------------------------------------- */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -static int saa7127_attach(struct i2c_adapter *adapter, int address, - unsigned short flags, int kind) -#else -static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind) -#endif +static int saa7127_probe(struct i2c_client *client) { - struct i2c_client *client; struct saa7127_state *state; struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 }; /* set to disabled */ int read_result = 0; /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return 0; - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == 0) - return -ENOMEM; - - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver_saa7127; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - client->flags = I2C_CLIENT_ALLOW_USE; -#endif snprintf(client->name, sizeof(client->name) - 1, "saa7127"); - v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n", address << 1); + v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n", client->addr << 1); /* First test register 0: Bits 5-7 are a version ID (should be 0), and bit 2 should also be 0. @@ -716,13 +697,11 @@ static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind) if ((saa7127_read(client, 0) & 0xe4) != 0 || (saa7127_read(client, 0x29) & 0x3f) != 0x1d) { v4l_dbg(1, debug, client, "saa7127 not found\n"); - kfree(client); return 0; } state = kzalloc(sizeof(struct saa7127_state), GFP_KERNEL); if (state == NULL) { - kfree(client); return (-ENOMEM); } @@ -751,99 +730,37 @@ static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind) read_result = saa7127_read(client, SAA7129_REG_FADE_KEY_COL2); saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, 0xaa); if (saa7127_read(client, SAA7129_REG_FADE_KEY_COL2) == 0xaa) { - v4l_info(client, "saa7129 found @ 0x%x (%s)\n", address << 1, adapter->name); + v4l_info(client, "saa7129 found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, read_result); saa7127_write_inittab(client, saa7129_init_config_extra); state->ident = V4L2_IDENT_SAA7129; } else { - v4l_info(client, "saa7127 found @ 0x%x (%s)\n", address << 1, adapter->name); + v4l_info(client, "saa7127 found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); state->ident = V4L2_IDENT_SAA7127; } - - i2c_attach_client(client); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_INC_USE_COUNT; -#endif return 0; } /* ----------------------------------------------------------------------- */ -static int saa7127_probe(struct i2c_adapter *adapter) +static int saa7127_remove(struct i2c_client *client) { -#ifdef I2C_CLASS_TV_ANALOG - if (adapter->class & I2C_CLASS_TV_ANALOG) -#else - if (adapter->id == I2C_HW_B_BT848) -#endif - return i2c_probe(adapter, &addr_data, saa7127_attach); - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static int saa7127_detach(struct i2c_client *client) -{ - struct saa7127_state *state = i2c_get_clientdata(client); - int err; - /* Turn off TV output */ saa7127_set_video_enable(client, 0); - - err = i2c_detach_client(client); - - if (err) { - return err; - } - - kfree(state); - kfree(client); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_DEC_USE_COUNT; -#endif + kfree(i2c_get_clientdata(client)); return 0; } /* ----------------------------------------------------------------------- */ -static struct i2c_driver i2c_driver_saa7127 = { -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) && (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)) - .owner = THIS_MODULE, -#endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) +static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa7127", - .flags = I2C_DF_NOTIFY, -#else - .driver = { - .name = "saa7127", - }, -#endif - .id = I2C_DRIVERID_SAA7127, - .attach_adapter = saa7127_probe, - .detach_client = saa7127_detach, + .driverid = I2C_DRIVERID_SAA7127, .command = saa7127_command, + .probe = saa7127_probe, + .remove = saa7127_remove, }; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) EXPORT_NO_SYMBOLS; #endif - -/* ----------------------------------------------------------------------- */ - -static int __init saa7127_init_module(void) -{ - return i2c_add_driver(&i2c_driver_saa7127); -} - -/* ----------------------------------------------------------------------- */ - -static void __exit saa7127_cleanup_module(void) -{ - i2c_del_driver(&i2c_driver_saa7127); -} - -/* ----------------------------------------------------------------------- */ - -module_init(saa7127_init_module); -module_exit(saa7127_cleanup_module); -- cgit v1.2.3 From d1b2468f9cc02f6f7e7628f2f32db1b4e21cd424 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 13 Sep 2007 16:28:59 +0200 Subject: msp3400: convert to bus-based I2C API. From: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/msp3400-driver.c | 135 +++-------------------------- 1 file changed, 14 insertions(+), 121 deletions(-) --- linux/drivers/media/video/msp3400-driver.c | 135 +++-------------------------- 1 file changed, 14 insertions(+), 121 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/msp3400-driver.c b/linux/drivers/media/video/msp3400-driver.c index cd9180668..690a81478 100644 --- a/linux/drivers/media/video/msp3400-driver.c +++ b/linux/drivers/media/video/msp3400-driver.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) @@ -825,62 +826,24 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,14) -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,20) static int msp_suspend(struct i2c_client *client, pm_message_t state) -#else -static int msp_suspend(struct device * dev, pm_message_t state) -#endif -#else -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) -static int msp_suspend(struct device * dev, pm_message_t state, u32 level) -#else -static int msp_suspend(struct device * dev, u32 state, u32 level) -#endif -#endif { -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,20) - struct i2c_client *client = container_of(dev, struct i2c_client, dev); -#endif - v4l_dbg(1, msp_debug, client, "suspend\n"); msp_reset(client); return 0; } -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,14) -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,20) static int msp_resume(struct i2c_client *client) -#else -static int msp_resume(struct device * dev) -#endif -#else -static int msp_resume(struct device * dev, u32 level) -#endif { -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,20) - struct i2c_client *client = container_of(dev, struct i2c_client, dev); -#endif - v4l_dbg(1, msp_debug, client, "resume\n"); msp_wake_thread(client); return 0; } -#endif /* LINUX_VERSION_CODE */ /* ----------------------------------------------------------------------- */ -static struct i2c_driver i2c_driver; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -static int msp_attach(struct i2c_adapter *adapter, int address, - unsigned short flags, int kind) -#else -static int msp_attach(struct i2c_adapter *adapter, int address, int kind) -#endif +static int msp_probe(struct i2c_client *client) { - struct i2c_client *client; struct msp_state *state; int (*thread_func)(void *data) = NULL; int msp_hard; @@ -889,27 +852,15 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) int msp_product, msp_prod_hi, msp_prod_lo; int msp_rom; - client = kzalloc(sizeof(*client), GFP_KERNEL); - if (!client) - return -ENOMEM; - - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - client->flags = I2C_CLIENT_ALLOW_USE; -#endif snprintf(client->name, sizeof(client->name) - 1, "msp3400"); if (msp_reset(client) == -1) { v4l_dbg(1, msp_debug, client, "msp3400 not found\n"); - kfree(client); return 0; } state = kzalloc(sizeof(*state), GFP_KERNEL); if (!state) { - kfree(client); return -ENOMEM; } @@ -937,7 +888,6 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) if (state->rev1 == -1 || (state->rev1 == 0 && state->rev2 == 0)) { v4l_dbg(1, msp_debug, client, "not an msp3400 (cannot read chip version)\n"); kfree(state); - kfree(client); return 0; } @@ -1003,7 +953,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) } /* hello world :-) */ - v4l_info(client, "%s found @ 0x%x (%s)\n", client->name, address << 1, adapter->name); + v4l_info(client, "%s found @ 0x%x (%s)\n", client->name, client->addr << 1, client->adapter->name); v4l_info(client, "%s ", client->name); if (state->has_nicam && state->has_radio) printk("supports nicam and radio, "); @@ -1048,31 +998,12 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) #endif msp_wake_thread(client); } - - /* done */ - i2c_attach_client(client); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_INC_USE_COUNT; -#endif return 0; } -static int msp_probe(struct i2c_adapter *adapter) -{ -#ifdef I2C_CLASS_TV_ANALOG - if (adapter->class & I2C_CLASS_TV_ANALOG) -#else - if (adapter->id == I2C_HW_B_BT848) -#endif - return i2c_probe(adapter, &addr_data, msp_attach); - return 0; -} - -static int msp_detach(struct i2c_client *client) +static int msp_remove(struct i2c_client *client) { struct msp_state *state = i2c_get_clientdata(client); - int err; /* shutdown control thread */ if (state->kthread) { @@ -1093,63 +1024,25 @@ static int msp_detach(struct i2c_client *client) } msp_reset(client); - err = i2c_detach_client(client); - if (err) { - return err; - } - kfree(state); - kfree(client); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_DEC_USE_COUNT; -#endif return 0; } /* ----------------------------------------------------------------------- */ -/* i2c implementation */ -static struct i2c_driver i2c_driver = { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))&&(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)) - .owner = THIS_MODULE, -#endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - .name = "msp3400", - .flags = I2C_DF_NOTIFY, -#endif - .id = I2C_DRIVERID_MSP3400, - .attach_adapter = msp_probe, - .detach_client = msp_detach, -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,20) +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "msp3400", + .driverid = I2C_DRIVERID_MSP3400, + .command = msp_command, + .probe = msp_probe, + .remove = msp_remove, .suspend = msp_suspend, - .resume = msp_resume, -#endif - .command = msp_command, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - .driver = { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) - .name = "msp3400", -#endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,20) - .suspend = msp_suspend, - .resume = msp_resume, -#endif - }, -#endif + .resume = msp_resume, }; -static int __init msp3400_init_module(void) -{ - return i2c_add_driver(&i2c_driver); -} - -static void __exit msp3400_cleanup_module(void) -{ - i2c_del_driver(&i2c_driver); -} - -module_init(msp3400_init_module); -module_exit(msp3400_cleanup_module); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +EXPORT_NO_SYMBOLS; +#endif /* * Overrides for Emacs so that we follow Linus's tabbing style. -- cgit v1.2.3 From 76d0b639663792f43c641da173249c3bfd79d5d6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 13 Sep 2007 16:30:38 +0200 Subject: cs53l23a: convert to bus-based I2C API. From: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cs53l32a.c | 94 ++--------------------------------- 1 file changed, 8 insertions(+), 86 deletions(-) --- linux/drivers/media/video/cs53l32a.c | 94 +++--------------------------------- 1 file changed, 8 insertions(+), 86 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cs53l32a.c b/linux/drivers/media/video/cs53l32a.c index f0240e079..0c7789b1c 100644 --- a/linux/drivers/media/video/cs53l32a.c +++ b/linux/drivers/media/video/cs53l32a.c @@ -29,6 +29,7 @@ #include #include #include +#include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "i2c-compat.h" #include @@ -69,8 +70,7 @@ static int cs53l32a_read(struct i2c_client *client, u8 reg) return i2c_smbus_read_byte_data(client, reg); } -static int cs53l32a_command(struct i2c_client *client, unsigned int cmd, - void *arg) +static int cs53l32a_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct v4l2_routing *route = arg; struct v4l2_control *ctrl = arg; @@ -146,35 +146,17 @@ static int cs53l32a_command(struct i2c_client *client, unsigned int cmd, * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' */ -static struct i2c_driver i2c_driver; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -static int cs53l32a_attach(struct i2c_adapter *adapter, int address, int kind) -#else -static int cs53l32a_attach(struct i2c_adapter *adapter, int address, - unsigned short flags, int kind) -#endif +static int cs53l32a_probe(struct i2c_client *client) { - struct i2c_client *client; int i; /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return 0; - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == 0) - return -ENOMEM; - - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - client->flags = I2C_CLIENT_ALLOW_USE; -#endif snprintf(client->name, sizeof(client->name) - 1, "cs53l32a"); - v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name); + v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); for (i = 1; i <= 7; i++) { u8 v = cs53l32a_read(client, i); @@ -199,76 +181,16 @@ static int cs53l32a_attach(struct i2c_adapter *adapter, int address, v4l_dbg(1, debug, client, "Read Reg %d %02x\n", i, v); } - - i2c_attach_client(client); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_INC_USE_COUNT; -#endif - return 0; -} - -static int cs53l32a_probe(struct i2c_adapter *adapter) -{ -#ifdef I2C_CLASS_TV_ANALOG - if (adapter->class & I2C_CLASS_TV_ANALOG) -#else - if (adapter->id == I2C_HW_B_BT848) -#endif - return i2c_probe(adapter, &addr_data, cs53l32a_attach); - return 0; -} - -static int cs53l32a_detach(struct i2c_client *client) -{ - int err; - - err = i2c_detach_client(client); - if (err) { - return err; - } - kfree(client); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_DEC_USE_COUNT; -#endif return 0; } -/* ----------------------------------------------------------------------- */ - -/* i2c implementation */ -static struct i2c_driver i2c_driver = { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)) - .owner = THIS_MODULE, -#endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) +static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "cs53l32a", - .flags = I2C_DF_NOTIFY, -#else - .driver = { - .name = "cs53l32a", - }, -#endif - .id = I2C_DRIVERID_CS53L32A, - .attach_adapter = cs53l32a_probe, - .detach_client = cs53l32a_detach, + .driverid = I2C_DRIVERID_CS53L32A, .command = cs53l32a_command, + .probe = cs53l32a_probe, }; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) EXPORT_NO_SYMBOLS; #endif - -static int __init cs53l32a_init_module(void) -{ - return i2c_add_driver(&i2c_driver); -} - -static void __exit cs53l32a_cleanup_module(void) -{ - i2c_del_driver(&i2c_driver); -} - -module_init(cs53l32a_init_module); -module_exit(cs53l32a_cleanup_module); -- cgit v1.2.3 From d24bf7117c64db6acdfb27f2e1eb6afdab9851f8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 13 Sep 2007 16:44:47 +0200 Subject: cx25840: convert to bus-based I2C API. From: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx25840/cx25840-core.c | 495 +++++++++-------------- 1 file changed, 202 insertions(+), 293 deletions(-) --- linux/drivers/media/video/cx25840/cx25840-core.c | 495 +++++++++-------------- 1 file changed, 202 insertions(+), 293 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index be246b0c8..89fec724c 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include "compat.h" #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) @@ -133,8 +134,6 @@ int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned and_mask, static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input, enum cx25840_audio_input aud_input); -static void log_audio_status(struct i2c_client *client); -static void log_video_status(struct i2c_client *client); /* ----------------------------------------------------------------------- */ @@ -662,6 +661,200 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) /* ----------------------------------------------------------------------- */ +static void log_video_status(struct i2c_client *client) +{ + static const char *const fmt_strs[] = { + "0x0", + "NTSC-M", "NTSC-J", "NTSC-4.43", + "PAL-BDGHI", "PAL-M", "PAL-N", "PAL-Nc", "PAL-60", + "0x9", "0xA", "0xB", + "SECAM", + "0xD", "0xE", "0xF" + }; + + struct cx25840_state *state = i2c_get_clientdata(client); + u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf; + u8 gen_stat1 = cx25840_read(client, 0x40d); + u8 gen_stat2 = cx25840_read(client, 0x40e); + int vid_input = state->vid_input; + + v4l_info(client, "Video signal: %spresent\n", + (gen_stat2 & 0x20) ? "" : "not "); + v4l_info(client, "Detected format: %s\n", + fmt_strs[gen_stat1 & 0xf]); + + v4l_info(client, "Specified standard: %s\n", + vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection"); + + if (vid_input >= CX25840_COMPOSITE1 && + vid_input <= CX25840_COMPOSITE8) { + v4l_info(client, "Specified video input: Composite %d\n", + vid_input - CX25840_COMPOSITE1 + 1); + } else { + v4l_info(client, "Specified video input: S-Video (Luma In%d, Chroma In%d)\n", + (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8); + } + + v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq); +} + +/* ----------------------------------------------------------------------- */ + +static void log_audio_status(struct i2c_client *client) +{ + struct cx25840_state *state = i2c_get_clientdata(client); + u8 download_ctl = cx25840_read(client, 0x803); + u8 mod_det_stat0 = cx25840_read(client, 0x804); + u8 mod_det_stat1 = cx25840_read(client, 0x805); + u8 audio_config = cx25840_read(client, 0x808); + u8 pref_mode = cx25840_read(client, 0x809); + u8 afc0 = cx25840_read(client, 0x80b); + u8 mute_ctl = cx25840_read(client, 0x8d3); + int aud_input = state->aud_input; + char *p; + + switch (mod_det_stat0) { + case 0x00: p = "mono"; break; + case 0x01: p = "stereo"; break; + case 0x02: p = "dual"; break; + case 0x04: p = "tri"; break; + case 0x10: p = "mono with SAP"; break; + case 0x11: p = "stereo with SAP"; break; + case 0x12: p = "dual with SAP"; break; + case 0x14: p = "tri with SAP"; break; + case 0xfe: p = "forced mode"; break; + default: p = "not defined"; + } + v4l_info(client, "Detected audio mode: %s\n", p); + + switch (mod_det_stat1) { + case 0x00: p = "not defined"; break; + case 0x01: p = "EIAJ"; break; + case 0x02: p = "A2-M"; break; + case 0x03: p = "A2-BG"; break; + case 0x04: p = "A2-DK1"; break; + case 0x05: p = "A2-DK2"; break; + case 0x06: p = "A2-DK3"; break; + case 0x07: p = "A1 (6.0 MHz FM Mono)"; break; + case 0x08: p = "AM-L"; break; + case 0x09: p = "NICAM-BG"; break; + case 0x0a: p = "NICAM-DK"; break; + case 0x0b: p = "NICAM-I"; break; + case 0x0c: p = "NICAM-L"; break; + case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break; + case 0x0e: p = "IF FM Radio"; break; + case 0x0f: p = "BTSC"; break; + case 0x10: p = "high-deviation FM"; break; + case 0x11: p = "very high-deviation FM"; break; + case 0xfd: p = "unknown audio standard"; break; + case 0xfe: p = "forced audio standard"; break; + case 0xff: p = "no detected audio standard"; break; + default: p = "not defined"; + } + v4l_info(client, "Detected audio standard: %s\n", p); + v4l_info(client, "Audio muted: %s\n", + (state->unmute_volume >= 0) ? "yes" : "no"); + v4l_info(client, "Audio microcontroller: %s\n", + (download_ctl & 0x10) ? + ((mute_ctl & 0x2) ? "detecting" : "running") : "stopped"); + + switch (audio_config >> 4) { + case 0x00: p = "undefined"; break; + case 0x01: p = "BTSC"; break; + case 0x02: p = "EIAJ"; break; + case 0x03: p = "A2-M"; break; + case 0x04: p = "A2-BG"; break; + case 0x05: p = "A2-DK1"; break; + case 0x06: p = "A2-DK2"; break; + case 0x07: p = "A2-DK3"; break; + case 0x08: p = "A1 (6.0 MHz FM Mono)"; break; + case 0x09: p = "AM-L"; break; + case 0x0a: p = "NICAM-BG"; break; + case 0x0b: p = "NICAM-DK"; break; + case 0x0c: p = "NICAM-I"; break; + case 0x0d: p = "NICAM-L"; break; + case 0x0e: p = "FM radio"; break; + case 0x0f: p = "automatic detection"; break; + default: p = "undefined"; + } + v4l_info(client, "Configured audio standard: %s\n", p); + + if ((audio_config >> 4) < 0xF) { + switch (audio_config & 0xF) { + case 0x00: p = "MONO1 (LANGUAGE A/Mono L+R channel for BTSC, EIAJ, A2)"; break; + case 0x01: p = "MONO2 (LANGUAGE B)"; break; + case 0x02: p = "MONO3 (STEREO forced MONO)"; break; + case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break; + case 0x04: p = "STEREO"; break; + case 0x05: p = "DUAL1 (AB)"; break; + case 0x06: p = "DUAL2 (AC) (FM)"; break; + case 0x07: p = "DUAL3 (BC) (FM)"; break; + case 0x08: p = "DUAL4 (AC) (AM)"; break; + case 0x09: p = "DUAL5 (BC) (AM)"; break; + case 0x0a: p = "SAP"; break; + default: p = "undefined"; + } + v4l_info(client, "Configured audio mode: %s\n", p); + } else { + switch (audio_config & 0xF) { + case 0x00: p = "BG"; break; + case 0x01: p = "DK1"; break; + case 0x02: p = "DK2"; break; + case 0x03: p = "DK3"; break; + case 0x04: p = "I"; break; + case 0x05: p = "L"; break; + case 0x06: p = "BTSC"; break; + case 0x07: p = "EIAJ"; break; + case 0x08: p = "A2-M"; break; + case 0x09: p = "FM Radio"; break; + case 0x0f: p = "automatic standard and mode detection"; break; + default: p = "undefined"; + } + v4l_info(client, "Configured audio system: %s\n", p); + } + + if (aud_input) { + v4l_info(client, "Specified audio input: Tuner (In%d)\n", aud_input); + } else { + v4l_info(client, "Specified audio input: External\n"); + } + + switch (pref_mode & 0xf) { + case 0: p = "mono/language A"; break; + case 1: p = "language B"; break; + case 2: p = "language C"; break; + case 3: p = "analog fallback"; break; + case 4: p = "stereo"; break; + case 5: p = "language AC"; break; + case 6: p = "language BC"; break; + case 7: p = "language AB"; break; + default: p = "undefined"; + } + v4l_info(client, "Preferred audio mode: %s\n", p); + + if ((audio_config & 0xf) == 0xf) { + switch ((afc0 >> 3) & 0x3) { + case 0: p = "system DK"; break; + case 1: p = "system L"; break; + case 2: p = "autodetect"; break; + default: p = "undefined"; + } + v4l_info(client, "Selected 65 MHz format: %s\n", p); + + switch (afc0 & 0x7) { + case 0: p = "chroma"; break; + case 1: p = "BTSC"; break; + case 2: p = "EIAJ"; break; + case 3: p = "A2-M"; break; + case 4: p = "autodetect"; break; + default: p = "undefined"; + } + v4l_info(client, "Selected 45 MHz format: %s\n", p); + } +} + +/* ----------------------------------------------------------------------- */ + static int cx25840_command(struct i2c_client *client, unsigned int cmd, void *arg) { @@ -900,41 +1093,12 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, /* ----------------------------------------------------------------------- */ -static struct i2c_driver i2c_driver_cx25840; - -static int cx25840_detect_client(struct i2c_adapter *adapter, int address, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - unsigned short flags, -#endif - int kind) +static int cx25840_probe(struct i2c_client *client) { - struct i2c_client *client; struct cx25840_state *state; u32 id; u16 device_id; - /* Check if the adapter supports the needed features - * Not until kernel version 2.6.11 did the bit-algo - * correctly report that it would do an I2C-level xfer */ -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,11) - if (!adapter->algo->master_xfer) -#else - if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) -#endif - return 0; - - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == 0) - return -ENOMEM; - - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver_cx25840; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - client->flags = I2C_CLIENT_ALLOW_USE; -#endif - snprintf(client->name, sizeof(client->name) - 1, "cx25840"); - v4l_dbg(1, cx25840_debug, client, "detecting cx25840 client on address 0x%x\n", client->addr << 1); device_id = cx25840_read(client, 0x101) << 8; @@ -950,13 +1114,11 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, } else { v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n"); - kfree(client); return 0; } state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL); if (state == NULL) { - kfree(client); return -ENOMEM; } @@ -979,272 +1141,19 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, state->vbi_line_offset = 8; state->id = id; state->rev = device_id; - - i2c_attach_client(client); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_INC_USE_COUNT; -#endif return 0; } -static int cx25840_attach_adapter(struct i2c_adapter *adapter) +static int cx25840_remove(struct i2c_client *client) { -#ifdef I2C_CLASS_TV_ANALOG - if (adapter->class & I2C_CLASS_TV_ANALOG) -#else - if (adapter->id == I2C_HW_B_BT848) -#endif - return i2c_probe(adapter, &addr_data, &cx25840_detect_client); + kfree(i2c_get_clientdata(client)); return 0; } -static int cx25840_detach_client(struct i2c_client *client) -{ - struct cx25840_state *state = i2c_get_clientdata(client); - int err; - - err = i2c_detach_client(client); - if (err) { - return err; - } - - kfree(state); - kfree(client); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_DEC_USE_COUNT; -#endif - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static struct i2c_driver i2c_driver_cx25840 = { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)) - .owner = THIS_MODULE, -#endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) +static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "cx25840", - .flags = I2C_DF_NOTIFY, -#else - .driver = { - .name = "cx25840", - }, -#endif - .id = I2C_DRIVERID_CX25840, - .attach_adapter = cx25840_attach_adapter, - .detach_client = cx25840_detach_client, + .driverid = I2C_DRIVERID_CX25840, .command = cx25840_command, + .probe = cx25840_probe, + .remove = cx25840_remove, }; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -EXPORT_NO_SYMBOLS; -#endif - -static int __init m__init(void) -{ - return i2c_add_driver(&i2c_driver_cx25840); -} - -static void __exit m__exit(void) -{ - i2c_del_driver(&i2c_driver_cx25840); -} - -module_init(m__init); -module_exit(m__exit); - -/* ----------------------------------------------------------------------- */ - -static void log_video_status(struct i2c_client *client) -{ - static const char *const fmt_strs[] = { - "0x0", - "NTSC-M", "NTSC-J", "NTSC-4.43", - "PAL-BDGHI", "PAL-M", "PAL-N", "PAL-Nc", "PAL-60", - "0x9", "0xA", "0xB", - "SECAM", - "0xD", "0xE", "0xF" - }; - - struct cx25840_state *state = i2c_get_clientdata(client); - u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf; - u8 gen_stat1 = cx25840_read(client, 0x40d); - u8 gen_stat2 = cx25840_read(client, 0x40e); - int vid_input = state->vid_input; - - v4l_info(client, "Video signal: %spresent\n", - (gen_stat2 & 0x20) ? "" : "not "); - v4l_info(client, "Detected format: %s\n", - fmt_strs[gen_stat1 & 0xf]); - - v4l_info(client, "Specified standard: %s\n", - vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection"); - - if (vid_input >= CX25840_COMPOSITE1 && - vid_input <= CX25840_COMPOSITE8) { - v4l_info(client, "Specified video input: Composite %d\n", - vid_input - CX25840_COMPOSITE1 + 1); - } else { - v4l_info(client, "Specified video input: S-Video (Luma In%d, Chroma In%d)\n", - (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8); - } - - v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq); -} - -/* ----------------------------------------------------------------------- */ - -static void log_audio_status(struct i2c_client *client) -{ - struct cx25840_state *state = i2c_get_clientdata(client); - u8 download_ctl = cx25840_read(client, 0x803); - u8 mod_det_stat0 = cx25840_read(client, 0x804); - u8 mod_det_stat1 = cx25840_read(client, 0x805); - u8 audio_config = cx25840_read(client, 0x808); - u8 pref_mode = cx25840_read(client, 0x809); - u8 afc0 = cx25840_read(client, 0x80b); - u8 mute_ctl = cx25840_read(client, 0x8d3); - int aud_input = state->aud_input; - char *p; - - switch (mod_det_stat0) { - case 0x00: p = "mono"; break; - case 0x01: p = "stereo"; break; - case 0x02: p = "dual"; break; - case 0x04: p = "tri"; break; - case 0x10: p = "mono with SAP"; break; - case 0x11: p = "stereo with SAP"; break; - case 0x12: p = "dual with SAP"; break; - case 0x14: p = "tri with SAP"; break; - case 0xfe: p = "forced mode"; break; - default: p = "not defined"; - } - v4l_info(client, "Detected audio mode: %s\n", p); - - switch (mod_det_stat1) { - case 0x00: p = "not defined"; break; - case 0x01: p = "EIAJ"; break; - case 0x02: p = "A2-M"; break; - case 0x03: p = "A2-BG"; break; - case 0x04: p = "A2-DK1"; break; - case 0x05: p = "A2-DK2"; break; - case 0x06: p = "A2-DK3"; break; - case 0x07: p = "A1 (6.0 MHz FM Mono)"; break; - case 0x08: p = "AM-L"; break; - case 0x09: p = "NICAM-BG"; break; - case 0x0a: p = "NICAM-DK"; break; - case 0x0b: p = "NICAM-I"; break; - case 0x0c: p = "NICAM-L"; break; - case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break; - case 0x0e: p = "IF FM Radio"; break; - case 0x0f: p = "BTSC"; break; - case 0x10: p = "high-deviation FM"; break; - case 0x11: p = "very high-deviation FM"; break; - case 0xfd: p = "unknown audio standard"; break; - case 0xfe: p = "forced audio standard"; break; - case 0xff: p = "no detected audio standard"; break; - default: p = "not defined"; - } - v4l_info(client, "Detected audio standard: %s\n", p); - v4l_info(client, "Audio muted: %s\n", - (state->unmute_volume >= 0) ? "yes" : "no"); - v4l_info(client, "Audio microcontroller: %s\n", - (download_ctl & 0x10) ? - ((mute_ctl & 0x2) ? "detecting" : "running") : "stopped"); - - switch (audio_config >> 4) { - case 0x00: p = "undefined"; break; - case 0x01: p = "BTSC"; break; - case 0x02: p = "EIAJ"; break; - case 0x03: p = "A2-M"; break; - case 0x04: p = "A2-BG"; break; - case 0x05: p = "A2-DK1"; break; - case 0x06: p = "A2-DK2"; break; - case 0x07: p = "A2-DK3"; break; - case 0x08: p = "A1 (6.0 MHz FM Mono)"; break; - case 0x09: p = "AM-L"; break; - case 0x0a: p = "NICAM-BG"; break; - case 0x0b: p = "NICAM-DK"; break; - case 0x0c: p = "NICAM-I"; break; - case 0x0d: p = "NICAM-L"; break; - case 0x0e: p = "FM radio"; break; - case 0x0f: p = "automatic detection"; break; - default: p = "undefined"; - } - v4l_info(client, "Configured audio standard: %s\n", p); - - if ((audio_config >> 4) < 0xF) { - switch (audio_config & 0xF) { - case 0x00: p = "MONO1 (LANGUAGE A/Mono L+R channel for BTSC, EIAJ, A2)"; break; - case 0x01: p = "MONO2 (LANGUAGE B)"; break; - case 0x02: p = "MONO3 (STEREO forced MONO)"; break; - case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break; - case 0x04: p = "STEREO"; break; - case 0x05: p = "DUAL1 (AB)"; break; - case 0x06: p = "DUAL2 (AC) (FM)"; break; - case 0x07: p = "DUAL3 (BC) (FM)"; break; - case 0x08: p = "DUAL4 (AC) (AM)"; break; - case 0x09: p = "DUAL5 (BC) (AM)"; break; - case 0x0a: p = "SAP"; break; - default: p = "undefined"; - } - v4l_info(client, "Configured audio mode: %s\n", p); - } else { - switch (audio_config & 0xF) { - case 0x00: p = "BG"; break; - case 0x01: p = "DK1"; break; - case 0x02: p = "DK2"; break; - case 0x03: p = "DK3"; break; - case 0x04: p = "I"; break; - case 0x05: p = "L"; break; - case 0x06: p = "BTSC"; break; - case 0x07: p = "EIAJ"; break; - case 0x08: p = "A2-M"; break; - case 0x09: p = "FM Radio"; break; - case 0x0f: p = "automatic standard and mode detection"; break; - default: p = "undefined"; - } - v4l_info(client, "Configured audio system: %s\n", p); - } - - if (aud_input) { - v4l_info(client, "Specified audio input: Tuner (In%d)\n", aud_input); - } else { - v4l_info(client, "Specified audio input: External\n"); - } - - switch (pref_mode & 0xf) { - case 0: p = "mono/language A"; break; - case 1: p = "language B"; break; - case 2: p = "language C"; break; - case 3: p = "analog fallback"; break; - case 4: p = "stereo"; break; - case 5: p = "language AC"; break; - case 6: p = "language BC"; break; - case 7: p = "language AB"; break; - default: p = "undefined"; - } - v4l_info(client, "Preferred audio mode: %s\n", p); - - if ((audio_config & 0xf) == 0xf) { - switch ((afc0 >> 3) & 0x3) { - case 0: p = "system DK"; break; - case 1: p = "system L"; break; - case 2: p = "autodetect"; break; - default: p = "undefined"; - } - v4l_info(client, "Selected 65 MHz format: %s\n", p); - - switch (afc0 & 0x7) { - case 0: p = "chroma"; break; - case 1: p = "BTSC"; break; - case 2: p = "EIAJ"; break; - case 3: p = "A2-M"; break; - case 4: p = "autodetect"; break; - default: p = "undefined"; - } - v4l_info(client, "Selected 45 MHz format: %s\n", p); - } -} -- cgit v1.2.3 From b3aa8ed04b7cab08e4a997aec02c02ce0b3809bd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 14 Sep 2007 09:50:44 +0200 Subject: tvaudio: convert to bus-based I2C API. From: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tvaudio.c | 238 ++++++++++++++---------------------- 1 file changed, 93 insertions(+), 145 deletions(-) --- linux/drivers/media/video/tvaudio.c | 238 ++++++++++++++---------------------- 1 file changed, 93 insertions(+), 145 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tvaudio.c b/linux/drivers/media/video/tvaudio.c index 5c3bd5030..26591c780 100644 --- a/linux/drivers/media/video/tvaudio.c +++ b/linux/drivers/media/video/tvaudio.c @@ -38,6 +38,7 @@ #include #include #include +#include #include @@ -116,7 +117,7 @@ static struct CHIPDESC chiplist[]; /* current state of the chip */ struct CHIPSTATE { - struct i2c_client c; + struct i2c_client *c; /* index into CHIPDESC array */ int type; @@ -155,10 +156,6 @@ static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; #endif I2C_CLIENT_INSMOD; -static struct i2c_driver driver; -static struct i2c_client client_template; - - /* ---------------------------------------------------------------------- */ /* i2c I/O functions */ @@ -167,24 +164,24 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val) unsigned char buffer[2]; if (-1 == subaddr) { - v4l_dbg(1, debug, &chip->c, "%s: chip_write: 0x%x\n", - chip->c.name, val); + v4l_dbg(1, debug, chip->c, "%s: chip_write: 0x%x\n", + chip->c->name, val); chip->shadow.bytes[1] = val; buffer[0] = val; - if (1 != i2c_master_send(&chip->c,buffer,1)) { - v4l_warn(&chip->c, "%s: I/O error (write 0x%x)\n", - chip->c.name, val); + if (1 != i2c_master_send(chip->c,buffer,1)) { + v4l_warn(chip->c, "%s: I/O error (write 0x%x)\n", + chip->c->name, val); return -1; } } else { - v4l_dbg(1, debug, &chip->c, "%s: chip_write: reg%d=0x%x\n", - chip->c.name, subaddr, val); + v4l_dbg(1, debug, chip->c, "%s: chip_write: reg%d=0x%x\n", + chip->c->name, subaddr, val); chip->shadow.bytes[subaddr+1] = val; buffer[0] = subaddr; buffer[1] = val; - if (2 != i2c_master_send(&chip->c,buffer,2)) { - v4l_warn(&chip->c, "%s: I/O error (write reg%d=0x%x)\n", - chip->c.name, subaddr, val); + if (2 != i2c_master_send(chip->c,buffer,2)) { + v4l_warn(chip->c, "%s: I/O error (write reg%d=0x%x)\n", + chip->c->name, subaddr, val); return -1; } } @@ -207,12 +204,12 @@ static int chip_read(struct CHIPSTATE *chip) { unsigned char buffer; - if (1 != i2c_master_recv(&chip->c,&buffer,1)) { - v4l_warn(&chip->c, "%s: I/O error (read)\n", - chip->c.name); + if (1 != i2c_master_recv(chip->c,&buffer,1)) { + v4l_warn(chip->c, "%s: I/O error (read)\n", + chip->c->name); return -1; } - v4l_dbg(1, debug, &chip->c, "%s: chip_read: 0x%x\n",chip->c.name, buffer); + v4l_dbg(1, debug, chip->c, "%s: chip_read: 0x%x\n",chip->c->name, buffer); return buffer; } @@ -221,17 +218,17 @@ static int chip_read2(struct CHIPSTATE *chip, int subaddr) unsigned char write[1]; unsigned char read[1]; struct i2c_msg msgs[2] = { - { chip->c.addr, 0, 1, write }, - { chip->c.addr, I2C_M_RD, 1, read } + { chip->c->addr, 0, 1, write }, + { chip->c->addr, I2C_M_RD, 1, read } }; write[0] = subaddr; - if (2 != i2c_transfer(chip->c.adapter,msgs,2)) { - v4l_warn(&chip->c, "%s: I/O error (read2)\n", chip->c.name); + if (2 != i2c_transfer(chip->c->adapter,msgs,2)) { + v4l_warn(chip->c, "%s: I/O error (read2)\n", chip->c->name); return -1; } - v4l_dbg(1, debug, &chip->c, "%s: chip_read2: reg%d=0x%x\n", - chip->c.name, subaddr,read[0]); + v4l_dbg(1, debug, chip->c, "%s: chip_read2: reg%d=0x%x\n", + chip->c->name, subaddr,read[0]); return read[0]; } @@ -243,8 +240,8 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd) return 0; /* update our shadow register set; print bytes if (debug > 0) */ - v4l_dbg(1, debug, &chip->c, "%s: chip_cmd(%s): reg=%d, data:", - chip->c.name, name,cmd->bytes[0]); + v4l_dbg(1, debug, chip->c, "%s: chip_cmd(%s): reg=%d, data:", + chip->c->name, name,cmd->bytes[0]); for (i = 1; i < cmd->count; i++) { if (debug) printk(" 0x%x",cmd->bytes[i]); @@ -254,8 +251,8 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd) printk("\n"); /* send data to the chip */ - if (cmd->count != i2c_master_send(&chip->c,cmd->bytes,cmd->count)) { - v4l_warn(&chip->c, "%s: I/O error (%s)\n", chip->c.name, name); + if (cmd->count != i2c_master_send(chip->c,cmd->bytes,cmd->count)) { + v4l_warn(chip->c, "%s: I/O error (%s)\n", chip->c->name, name); return -1; } return 0; @@ -279,7 +276,7 @@ static int chip_thread(void *data) struct CHIPSTATE *chip = data; struct CHIPDESC *desc = chiplist + chip->type; - v4l_dbg(1, debug, &chip->c, "%s: thread started\n", chip->c.name); + v4l_dbg(1, debug, chip->c, "%s: thread started\n", chip->c->name); set_freezable(); for (;;) { set_current_state(TASK_INTERRUPTIBLE); @@ -291,7 +288,7 @@ static int chip_thread(void *data) #endif if (kthread_should_stop()) break; - v4l_dbg(1, debug, &chip->c, "%s: thread wakeup\n", chip->c.name); + v4l_dbg(1, debug, chip->c, "%s: thread wakeup\n", chip->c->name); /* don't do anything for radio or if mode != auto */ if (chip->radio || chip->mode != 0) @@ -304,7 +301,7 @@ static int chip_thread(void *data) mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); } - v4l_dbg(1, debug, &chip->c, "%s: thread exiting\n", chip->c.name); + v4l_dbg(1, debug, chip->c, "%s: thread exiting\n", chip->c->name); return 0; } @@ -316,7 +313,7 @@ static void generic_checkmode(struct CHIPSTATE *chip) if (mode == chip->prevmode) return; - v4l_dbg(1, debug, &chip->c, "%s: thread checkmode\n", chip->c.name); + v4l_dbg(1, debug, chip->c, "%s: thread checkmode\n", chip->c->name); chip->prevmode = mode; if (mode & V4L2_TUNER_MODE_STEREO) @@ -365,7 +362,7 @@ static int tda9840_getmode(struct CHIPSTATE *chip) if (val & TDA9840_ST_STEREO) mode |= V4L2_TUNER_MODE_STEREO; - v4l_dbg(1, debug, &chip->c, "tda9840_getmode(): raw chip read: %d, return: %d\n", + v4l_dbg(1, debug, chip->c, "tda9840_getmode(): raw chip read: %d, return: %d\n", val, mode); return mode; } @@ -669,7 +666,7 @@ static int tda9873_getmode(struct CHIPSTATE *chip) mode |= V4L2_TUNER_MODE_STEREO; if (val & TDA9873_DUAL) mode |= V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; - v4l_dbg(1, debug, &chip->c, "tda9873_getmode(): raw chip read: %d, return: %d\n", + v4l_dbg(1, debug, chip->c, "tda9873_getmode(): raw chip read: %d, return: %d\n", val, mode); return mode; } @@ -680,12 +677,12 @@ static void tda9873_setmode(struct CHIPSTATE *chip, int mode) /* int adj_data = chip->shadow.bytes[TDA9873_AD+1] ; */ if ((sw_data & TDA9873_INP_MASK) != TDA9873_INTERNAL) { - v4l_dbg(1, debug, &chip->c, "tda9873_setmode(): external input\n"); + v4l_dbg(1, debug, chip->c, "tda9873_setmode(): external input\n"); return; } - v4l_dbg(1, debug, &chip->c, "tda9873_setmode(): chip->shadow.bytes[%d] = %d\n", TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]); - v4l_dbg(1, debug, &chip->c, "tda9873_setmode(): sw_data = %d\n", sw_data); + v4l_dbg(1, debug, chip->c, "tda9873_setmode(): chip->shadow.bytes[%d] = %d\n", TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]); + v4l_dbg(1, debug, chip->c, "tda9873_setmode(): sw_data = %d\n", sw_data); switch (mode) { case V4L2_TUNER_MODE_MONO: @@ -706,7 +703,7 @@ static void tda9873_setmode(struct CHIPSTATE *chip, int mode) } chip_write(chip, TDA9873_SW, sw_data); - v4l_dbg(1, debug, &chip->c, "tda9873_setmode(): req. mode %d; chip_write: %d\n", + v4l_dbg(1, debug, chip->c, "tda9873_setmode(): req. mode %d; chip_write: %d\n", mode, sw_data); } @@ -845,7 +842,7 @@ static int tda9874a_setup(struct CHIPSTATE *chip) chip_write(chip, TDA9874A_SDACOSR, (tda9874a_mode) ? 0x81:0x80); chip_write(chip, TDA9874A_AOSR, 0x00); /* or 0x10 */ } - v4l_dbg(1, debug, &chip->c, "tda9874a_setup(): %s [0x%02X].\n", + v4l_dbg(1, debug, chip->c, "tda9874a_setup(): %s [0x%02X].\n", tda9874a_modelist[tda9874a_STD].name,tda9874a_STD); return 1; } @@ -893,7 +890,7 @@ static int tda9874a_getmode(struct CHIPSTATE *chip) mode |= V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; } - v4l_dbg(1, debug, &chip->c, "tda9874a_getmode(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n", + v4l_dbg(1, debug, chip->c, "tda9874a_getmode(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n", dsr, nsr, necr, mode); return mode; } @@ -939,7 +936,7 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode) chip_write(chip, TDA9874A_AOSR, aosr); chip_write(chip, TDA9874A_MDACOSR, mdacosr); - v4l_dbg(1, debug, &chip->c, "tda9874a_setmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n", + v4l_dbg(1, debug, chip->c, "tda9874a_setmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n", mode, aosr, mdacosr); } else { /* dic == 0x07 */ @@ -974,7 +971,7 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode) chip_write(chip, TDA9874A_FMMR, fmmr); chip_write(chip, TDA9874A_AOSR, aosr); - v4l_dbg(1, debug, &chip->c, "tda9874a_setmode(): req. mode %d; FMMR=0x%X, AOSR=0x%X.\n", + v4l_dbg(1, debug, chip->c, "tda9874a_setmode(): req. mode %d; FMMR=0x%X, AOSR=0x%X.\n", mode, fmmr, aosr); } } @@ -988,10 +985,10 @@ static int tda9874a_checkit(struct CHIPSTATE *chip) if(-1 == (sic = chip_read2(chip,TDA9874A_SIC))) return 0; - v4l_dbg(1, debug, &chip->c, "tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic); + v4l_dbg(1, debug, chip->c, "tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic); if((dic == 0x11)||(dic == 0x07)) { - v4l_info(&chip->c, "found tda9874%s.\n", (dic == 0x11) ? "a":"h"); + v4l_info(chip->c, "found tda9874%s.\n", (dic == 0x11) ? "a":"h"); tda9874a_dic = dic; /* remember device id. */ return 1; } @@ -1114,7 +1111,7 @@ static int tda8425_initialize(struct CHIPSTATE *chip) int inputmap[4] = { /* tuner */ TDA8425_S1_CH2, /* radio */ TDA8425_S1_CH1, /* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF}; - if (chip->c.adapter->id == I2C_HW_B_RIVA) { + if (chip->c->adapter->id == I2C_HW_B_RIVA) { memcpy (desc->inputmap, inputmap, sizeof (inputmap)); } return 0; @@ -1202,7 +1199,7 @@ static int ta8874z_getmode(struct CHIPSTATE *chip) }else if (!(val & TA8874Z_B0)){ mode |= V4L2_TUNER_MODE_STEREO; } - /* v4l_dbg(1, debug, &chip->c, "ta8874z_getmode(): raw chip read: 0x%02x, return: 0x%02x\n", val, mode); */ + /* v4l_dbg(1, debug, chip->c, "ta8874z_getmode(): raw chip read: 0x%02x, return: 0x%02x\n", val, mode); */ return mode; } @@ -1215,7 +1212,7 @@ static void ta8874z_setmode(struct CHIPSTATE *chip, int mode) { int update = 1; audiocmd *t = NULL; - v4l_dbg(1, debug, &chip->c, "ta8874z_setmode(): mode: 0x%02x\n", mode); + v4l_dbg(1, debug, chip->c, "ta8874z_setmode(): mode: 0x%02x\n", mode); switch(mode){ case V4L2_TUNER_MODE_MONO: @@ -1481,59 +1478,55 @@ static struct CHIPDESC chiplist[] = { /* ---------------------------------------------------------------------- */ /* i2c registration */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -static int chip_attach(struct i2c_adapter *adap, int addr, int kind) -#else -static int chip_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind) -#endif +static int chip_probe(struct i2c_client *client) { struct CHIPSTATE *chip; struct CHIPDESC *desc; + if (debug) { + printk(KERN_INFO "tvaudio: TV audio decoder + audio/video mux driver\n"); + printk(KERN_INFO "tvaudio: known chips: "); + for (desc = chiplist; desc->name != NULL; desc++) + printk("%s%s", (desc == chiplist) ? "" : ", ", desc->name); + printk("\n"); + } + chip = kzalloc(sizeof(*chip),GFP_KERNEL); if (!chip) return -ENOMEM; - memcpy(&chip->c,&client_template,sizeof(struct i2c_client)); - chip->c.adapter = adap; - chip->c.addr = addr; - i2c_set_clientdata(&chip->c, chip); + chip->c = client; + i2c_set_clientdata(client, chip); /* find description for the chip */ - v4l_dbg(1, debug, &chip->c, "chip found @ 0x%x\n", addr<<1); + v4l_dbg(1, debug, client, "chip found @ 0x%x\n", client->addr<<1); for (desc = chiplist; desc->name != NULL; desc++) { if (0 == *(desc->insmodopt)) continue; - if (addr < desc->addr_lo || - addr > desc->addr_hi) + if (client->addr < desc->addr_lo || + client->addr > desc->addr_hi) continue; if (desc->checkit && !desc->checkit(chip)) continue; break; } if (desc->name == NULL) { - v4l_dbg(1, debug, &chip->c, "no matching chip description found\n"); + v4l_dbg(1, debug, client, "no matching chip description found\n"); return -EIO; } - v4l_info(&chip->c, "%s found @ 0x%x (%s)\n", desc->name, addr<<1, adap->name); + v4l_info(client, "%s found @ 0x%x (%s)\n", desc->name, client->addr<<1, client->adapter->name); if (desc->flags) { - v4l_dbg(1, debug, &chip->c, "matches:%s%s%s.\n", + v4l_dbg(1, debug, client, "matches:%s%s%s.\n", (desc->flags & CHIP_HAS_VOLUME) ? " volume" : "", (desc->flags & CHIP_HAS_BASSTREBLE) ? " bass/treble" : "", (desc->flags & CHIP_HAS_INPUTSEL) ? " audiomux" : ""); } /* fill required data structures */ - strcpy(chip->c.name, desc->name); + strcpy(client->name, desc->name); chip->type = desc-chiplist; chip->shadow.count = desc->registers+1; chip->prevmode = -1; chip->audmode = V4L2_TUNER_MODE_LANG1; - /* register */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_INC_USE_COUNT; -#endif - i2c_attach_client(&chip->c); /* initialization */ if (desc->initialize != NULL) @@ -1560,39 +1553,17 @@ static int chip_attach(struct i2c_adapter *adap, int addr, init_timer(&chip->wt); chip->wt.function = chip_thread_wake; chip->wt.data = (unsigned long)chip; - chip->thread = kthread_run(chip_thread, chip, chip->c.name); + chip->thread = kthread_run(chip_thread, chip, chip->c->name); if (IS_ERR(chip->thread)) { - v4l_warn(&chip->c, "%s: failed to create kthread\n", - chip->c.name); + v4l_warn(chip->c, "%s: failed to create kthread\n", + chip->c->name); chip->thread = NULL; } } return 0; } -static int chip_probe(struct i2c_adapter *adap) -{ - /* don't attach on saa7146 based cards, - because dedicated drivers are used */ - if ((adap->id == I2C_HW_SAA7146)) - return 0; -#ifdef I2C_CLASS_TV_ANALOG - if (adap->class & I2C_CLASS_TV_ANALOG) - return i2c_probe(adap, &addr_data, chip_attach); -#else - switch (adap->id) { - case I2C_HW_B_BT848: - case I2C_HW_B_RIVA: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - case I2C_HW_SAA7134: -#endif - return i2c_probe(adap, &addr_data, chip_attach); - } -#endif - return 0; -} - -static int chip_detach(struct i2c_client *client) +static int chip_remove(struct i2c_client *client) { struct CHIPSTATE *chip = i2c_get_clientdata(client); @@ -1603,11 +1574,7 @@ static int chip_detach(struct i2c_client *client) chip->thread = NULL; } - i2c_detach_client(&chip->c); kfree(chip); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_DEC_USE_COUNT; -#endif return 0; } @@ -1732,7 +1699,7 @@ static int chip_command(struct i2c_client *client, struct CHIPSTATE *chip = i2c_get_clientdata(client); struct CHIPDESC *desc = chiplist + chip->type; - v4l_dbg(1, debug, &chip->c, "%s: chip_command 0x%x\n", chip->c.name, cmd); + v4l_dbg(1, debug, chip->c, "%s: chip_command 0x%x\n", chip->c->name, cmd); switch (cmd) { case AUDC_SET_RADIO: @@ -1869,55 +1836,36 @@ static int chip_command(struct i2c_client *client, return 0; } -static struct i2c_driver driver = { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))&&(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)) - .owner = THIS_MODULE, -#endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - .name = "tvaudio", - .flags = I2C_DF_NOTIFY, -#else - .driver = { - .name = "tvaudio", - }, -#endif - .id = I2C_DRIVERID_TVAUDIO, - .attach_adapter = chip_probe, - .detach_client = chip_detach, - .command = chip_command, -}; - -static struct i2c_client client_template = +static int chip_legacy_probe(struct i2c_adapter *adap) { - .name = "(unset)", -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - .flags = I2C_CLIENT_ALLOW_USE, + /* don't attach on saa7146 based cards, + because dedicated drivers are used */ + if ((adap->id == I2C_HW_SAA7146)) + return 0; +#ifdef I2C_CLASS_TV_ANALOG + if (adap->class & I2C_CLASS_TV_ANALOG) + return 1; +#else + switch (adap->id) { + case I2C_HW_B_BT848: + case I2C_HW_B_RIVA: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + case I2C_HW_SAA7134: #endif - .driver = &driver, -}; - -static int __init audiochip_init_module(void) -{ - struct CHIPDESC *desc; - - if (debug) { - printk(KERN_INFO "tvaudio: TV audio decoder + audio/video mux driver\n"); - printk(KERN_INFO "tvaudio: known chips: "); - for (desc = chiplist; desc->name != NULL; desc++) - printk("%s%s", (desc == chiplist) ? "" : ", ", desc->name); - printk("\n"); + return 1; } - - return i2c_add_driver(&driver); -} - -static void __exit audiochip_cleanup_module(void) -{ - i2c_del_driver(&driver); +#endif + return 0; } -module_init(audiochip_init_module); -module_exit(audiochip_cleanup_module); +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "tvaudio", + .driverid = I2C_DRIVERID_TVAUDIO, + .command = chip_command, + .probe = chip_probe, + .remove = chip_remove, + .legacy_probe = chip_legacy_probe, +}; /* * Local variables: -- cgit v1.2.3 From e5f182c1d62f1ea1f7dc45d7f1b9d241fb1e6c74 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 14 Sep 2007 09:58:06 +0200 Subject: upd64083: convert to bus-based I2C API. From: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/upd64083.c | 96 ++++------------------------------- 1 file changed, 13 insertions(+), 83 deletions(-) --- linux/drivers/media/video/upd64083.c | 96 +++++------------------------------- 1 file changed, 13 insertions(+), 83 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/upd64083.c b/linux/drivers/media/video/upd64083.c index ccf340a5b..280c593d0 100644 --- a/linux/drivers/media/video/upd64083.c +++ b/linux/drivers/media/video/upd64083.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "compat.h" @@ -179,40 +180,18 @@ static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *a /* i2c implementation */ -static struct i2c_driver i2c_driver; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -static int upd64083_attach(struct i2c_adapter *adapter, int address, int kind) -#else -static int upd64083_attach(struct i2c_adapter *adapter, int address, - unsigned short flags, int kind) -#endif +static int upd64083_probe(struct i2c_client *client) { - struct i2c_client *client; struct upd64083_state *state; int i; - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return 0; - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == NULL) { - return -ENOMEM; - } - - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - client->flags = I2C_CLIENT_ALLOW_USE; -#endif - snprintf(client->name, sizeof(client->name) - 1, "uPD64083"); - - v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name); + v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); state = kmalloc(sizeof(struct upd64083_state), GFP_KERNEL); if (state == NULL) { - kfree(client); return -ENOMEM; } i2c_set_clientdata(client, state); @@ -223,74 +202,25 @@ static int upd64083_attach(struct i2c_adapter *adapter, int address, for (i = 0; i < TOT_REGS; i++) { upd64083_write(client, i, state->regs[i]); } - i2c_attach_client(client); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_INC_USE_COUNT; -#endif return 0; } -static int upd64083_probe(struct i2c_adapter *adapter) +static int upd64083_remove(struct i2c_client *client) { -#ifdef I2C_CLASS_TV_ANALOG - if (adapter->class & I2C_CLASS_TV_ANALOG) -#else - if (adapter->id == I2C_HW_B_BT848) -#endif - return i2c_probe(adapter, &addr_data, upd64083_attach); - return 0; -} - -static int upd64083_detach(struct i2c_client *client) -{ - int err; - - err = i2c_detach_client(client); - if (err) - return err; - - kfree(client); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_DEC_USE_COUNT; -#endif + kfree(i2c_get_clientdata(client)); return 0; } /* ----------------------------------------------------------------------- */ -/* i2c implementation */ -static struct i2c_driver i2c_driver = { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - .owner = THIS_MODULE, -#endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - .name = "upd64083", - .flags = I2C_DF_NOTIFY, -#else - .driver = { - .name = "upd64083", - }, -#endif - .id = I2C_DRIVERID_UPD64083, - .attach_adapter = upd64083_probe, - .detach_client = upd64083_detach, - .command = upd64083_command, -}; - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) EXPORT_NO_SYMBOLS; #endif -static int __init upd64083_init_module(void) -{ - return i2c_add_driver(&i2c_driver); -} - -static void __exit upd64083_exit_module(void) -{ - i2c_del_driver(&i2c_driver); -} - -module_init(upd64083_init_module); -module_exit(upd64083_exit_module); +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "upd64083", + .driverid = I2C_DRIVERID_UPD64083, + .command = upd64083_command, + .probe = upd64083_probe, + .remove = upd64083_remove, +}; -- cgit v1.2.3 From 7074267148bb16db60cad242026aed9f91e1ef26 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 14 Sep 2007 09:58:31 +0200 Subject: upd64031a: convert to bus-based I2C API. From: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/upd64031a.c | 97 ++++------------------------------ 1 file changed, 13 insertions(+), 84 deletions(-) --- linux/drivers/media/video/upd64031a.c | 97 +++++------------------------------ 1 file changed, 13 insertions(+), 84 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/upd64031a.c b/linux/drivers/media/video/upd64031a.c index bd6a50ec7..9234cbb0d 100644 --- a/linux/drivers/media/video/upd64031a.c +++ b/linux/drivers/media/video/upd64031a.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "compat.h" @@ -201,40 +202,18 @@ static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void * /* i2c implementation */ -static struct i2c_driver i2c_driver; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -static int upd64031a_attach(struct i2c_adapter *adapter, int address, int kind) -#else -static int upd64031a_attach(struct i2c_adapter *adapter, int address, - unsigned short flags, int kind) -#endif +static int upd64031a_probe(struct i2c_client *client) { - struct i2c_client *client; struct upd64031a_state *state; int i; - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return 0; - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == NULL) { - return -ENOMEM; - } - - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - client->flags = I2C_CLIENT_ALLOW_USE; -#endif - snprintf(client->name, sizeof(client->name) - 1, "uPD64031A"); - - v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name); + v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); state = kmalloc(sizeof(struct upd64031a_state), GFP_KERNEL); if (state == NULL) { - kfree(client); return -ENOMEM; } i2c_set_clientdata(client, state); @@ -245,75 +224,25 @@ static int upd64031a_attach(struct i2c_adapter *adapter, int address, for (i = 0; i < TOT_REGS; i++) { upd64031a_write(client, i, state->regs[i]); } - - i2c_attach_client(client); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_INC_USE_COUNT; -#endif return 0; } -static int upd64031a_probe(struct i2c_adapter *adapter) +static int upd64031a_remove(struct i2c_client *client) { -#ifdef I2C_CLASS_TV_ANALOG - if (adapter->class & I2C_CLASS_TV_ANALOG) -#else - if (adapter->id == I2C_HW_B_BT848) -#endif - return i2c_probe(adapter, &addr_data, upd64031a_attach); - return 0; -} - -static int upd64031a_detach(struct i2c_client *client) -{ - int err; - - err = i2c_detach_client(client); - if (err) - return err; - - kfree(client); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_DEC_USE_COUNT; -#endif + kfree(i2c_get_clientdata(client)); return 0; } /* ----------------------------------------------------------------------- */ -/* i2c implementation */ -static struct i2c_driver i2c_driver = { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - .owner = THIS_MODULE, -#endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - .name = "upd64031a", - .flags = I2C_DF_NOTIFY, -#else - .driver = { - .name = "upd64031a", - }, -#endif - .id = I2C_DRIVERID_UPD64031A, - .attach_adapter = upd64031a_probe, - .detach_client = upd64031a_detach, - .command = upd64031a_command, -}; - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) EXPORT_NO_SYMBOLS; #endif -static int __init upd64031a_init_module(void) -{ - return i2c_add_driver(&i2c_driver); -} - -static void __exit upd64031a_exit_module(void) -{ - i2c_del_driver(&i2c_driver); -} - -module_init(upd64031a_init_module); -module_exit(upd64031a_exit_module); +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "upd64031a", + .driverid = I2C_DRIVERID_UPD64031A, + .command = upd64031a_command, + .probe = upd64031a_probe, + .remove = upd64031a_remove, +}; -- cgit v1.2.3 From 80d4ab9102f845bde660eab7e43d80af2c2fc328 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 14 Sep 2007 10:03:17 +0200 Subject: tlv320aic23b: convert to bus-based I2C API. From: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tlv320aic23b.c | 93 ++++--------------------------- 1 file changed, 13 insertions(+), 80 deletions(-) --- linux/drivers/media/video/tlv320aic23b.c | 93 +++++--------------------------- 1 file changed, 13 insertions(+), 80 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tlv320aic23b.c b/linux/drivers/media/video/tlv320aic23b.c index ee10fbeaa..2e5ed138e 100644 --- a/linux/drivers/media/video/tlv320aic23b.c +++ b/linux/drivers/media/video/tlv320aic23b.c @@ -31,6 +31,7 @@ #include #include #include +#include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "i2c-compat.h" #include @@ -134,39 +135,18 @@ static int tlv320aic23b_command(struct i2c_client *client, unsigned int cmd, * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' */ -static struct i2c_driver i2c_driver; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -static int tlv320aic23b_attach(struct i2c_adapter *adapter, int address, int kind) -#else -static int tlv320aic23b_attach(struct i2c_adapter *adapter, int address, - unsigned short flags, int kind) -#endif +static int tlv320aic23b_probe(struct i2c_client *client) { - struct i2c_client *client; struct tlv320aic23b_state *state; /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return 0; - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == 0) - return -ENOMEM; - - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - client->flags = I2C_CLIENT_ALLOW_USE; -#endif - snprintf(client->name, sizeof(client->name) - 1, "tlv320aic23b"); - - v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name); + v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); state = kmalloc(sizeof(struct tlv320aic23b_state), GFP_KERNEL); if (state == NULL) { - kfree(client); return -ENOMEM; } state->muted = 0; @@ -179,72 +159,25 @@ static int tlv320aic23b_attach(struct i2c_adapter *adapter, int address, tlv320aic23b_write(client, 0, 0x119); /* set gain on both channels to +3.0 dB */ tlv320aic23b_write(client, 8, 0x000); /* set sample rate to 48 kHz */ tlv320aic23b_write(client, 9, 0x001); /* activate digital interface */ - - i2c_attach_client(client); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_INC_USE_COUNT; -#endif return 0; } -static int tlv320aic23b_probe(struct i2c_adapter *adapter) +static int tlv320aic23b_remove(struct i2c_client *client) { - if (adapter->class & I2C_CLASS_TV_ANALOG) - return i2c_probe(adapter, &addr_data, tlv320aic23b_attach); - return 0; -} - -static int tlv320aic23b_detach(struct i2c_client *client) -{ - int err; - - err = i2c_detach_client(client); - if (err) { - return err; - } - kfree(client); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_DEC_USE_COUNT; -#endif + kfree(i2c_get_clientdata(client)); return 0; } /* ----------------------------------------------------------------------- */ -/* i2c implementation */ -static struct i2c_driver i2c_driver = { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))&&(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)) - .owner = THIS_MODULE, -#endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - .name = "tlv320aic23b", - .flags = I2C_DF_NOTIFY, -#else - .driver = { - .name = "tlv320aic23b", - }, -#endif - .id = I2C_DRIVERID_TLV320AIC23B, - .attach_adapter = tlv320aic23b_probe, - .detach_client = tlv320aic23b_detach, - .command = tlv320aic23b_command, -}; - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) EXPORT_NO_SYMBOLS; #endif -static int __init tlv320aic23b_init_module(void) -{ - return i2c_add_driver(&i2c_driver); -} - -static void __exit tlv320aic23b_cleanup_module(void) -{ - i2c_del_driver(&i2c_driver); -} - -module_init(tlv320aic23b_init_module); -module_exit(tlv320aic23b_cleanup_module); +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "tlv320aic23b", + .driverid = I2C_DRIVERID_TLV320AIC23B, + .command = tlv320aic23b_command, + .probe = tlv320aic23b_probe, + .remove = tlv320aic23b_remove, +}; -- cgit v1.2.3 From 3f466835bc047f9f83f11ce8dcecc3021de4dec2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 16 Sep 2007 15:47:15 +0200 Subject: Use correct error codes when chip is not recognized. From: Hans Verkuil If the chip isn't recognized, then the correct errors should be returned. The v4l2_i2c_attach() utility function will return 0 for all errors except -ENOMEM to provide proper compatibility support for the old I2C probing function. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cs53l32a.c | 2 +- linux/drivers/media/video/cx25840/cx25840-core.c | 6 +++++- linux/drivers/media/video/msp3400-driver.c | 4 ++-- linux/drivers/media/video/saa7115.c | 4 ++-- linux/drivers/media/video/saa7127.c | 6 +++--- linux/drivers/media/video/tlv320aic23b.c | 2 +- linux/drivers/media/video/upd64031a.c | 2 +- linux/drivers/media/video/upd64083.c | 2 +- linux/drivers/media/video/v4l2-common.c | 2 +- linux/drivers/media/video/vp27smpx.c | 2 +- linux/drivers/media/video/wm8739.c | 4 ++++ 11 files changed, 22 insertions(+), 14 deletions(-) --- linux/drivers/media/video/cs53l32a.c | 2 +- linux/drivers/media/video/cx25840/cx25840-core.c | 6 +++++- linux/drivers/media/video/msp3400-driver.c | 4 ++-- linux/drivers/media/video/saa7115.c | 4 ++-- linux/drivers/media/video/saa7127.c | 6 +++--- linux/drivers/media/video/tlv320aic23b.c | 2 +- linux/drivers/media/video/upd64031a.c | 2 +- linux/drivers/media/video/upd64083.c | 2 +- linux/drivers/media/video/v4l2-common.c | 2 +- linux/drivers/media/video/vp27smpx.c | 2 +- linux/drivers/media/video/wm8739.c | 4 ++++ 11 files changed, 22 insertions(+), 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cs53l32a.c b/linux/drivers/media/video/cs53l32a.c index 0c7789b1c..38b5516e3 100644 --- a/linux/drivers/media/video/cs53l32a.c +++ b/linux/drivers/media/video/cs53l32a.c @@ -152,7 +152,7 @@ static int cs53l32a_probe(struct i2c_client *client) /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; + return -EIO; snprintf(client->name, sizeof(client->name) - 1, "cs53l32a"); diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index 89fec724c..3f249b025 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -1099,6 +1099,10 @@ static int cx25840_probe(struct i2c_client *client) u32 id; u16 device_id; + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + v4l_dbg(1, cx25840_debug, client, "detecting cx25840 client on address 0x%x\n", client->addr << 1); device_id = cx25840_read(client, 0x101) << 8; @@ -1114,7 +1118,7 @@ static int cx25840_probe(struct i2c_client *client) } else { v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n"); - return 0; + return -ENODEV; } state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL); diff --git a/linux/drivers/media/video/msp3400-driver.c b/linux/drivers/media/video/msp3400-driver.c index 690a81478..bc74cdccb 100644 --- a/linux/drivers/media/video/msp3400-driver.c +++ b/linux/drivers/media/video/msp3400-driver.c @@ -856,7 +856,7 @@ static int msp_probe(struct i2c_client *client) if (msp_reset(client) == -1) { v4l_dbg(1, msp_debug, client, "msp3400 not found\n"); - return 0; + return -ENODEV; } state = kzalloc(sizeof(*state), GFP_KERNEL); @@ -888,7 +888,7 @@ static int msp_probe(struct i2c_client *client) if (state->rev1 == -1 || (state->rev1 == 0 && state->rev2 == 0)) { v4l_dbg(1, msp_debug, client, "not an msp3400 (cannot read chip version)\n"); kfree(state); - return 0; + return -ENODEV; } #if 0 diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c index 3d4020921..3b57cb352 100644 --- a/linux/drivers/media/video/saa7115.c +++ b/linux/drivers/media/video/saa7115.c @@ -1470,7 +1470,7 @@ static int saa7115_probe(struct i2c_client *client) /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; + return -EIO; snprintf(client->name, sizeof(client->name) - 1, "saa7115"); @@ -1489,7 +1489,7 @@ static int saa7115_probe(struct i2c_client *client) if (memcmp(name, "1f711", 5)) { v4l_dbg(1, debug, client, "chip found @ 0x%x (ID %s) does not match a known saa711x chip.\n", client->addr << 1, name); - return 0; + return -ENODEV; } snprintf(client->name, sizeof(client->name) - 1, "saa711%d",chip_id); diff --git a/linux/drivers/media/video/saa7127.c b/linux/drivers/media/video/saa7127.c index 95e0f998a..27d9cab97 100644 --- a/linux/drivers/media/video/saa7127.c +++ b/linux/drivers/media/video/saa7127.c @@ -683,7 +683,7 @@ static int saa7127_probe(struct i2c_client *client) /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; + return -EIO; snprintf(client->name, sizeof(client->name) - 1, "saa7127"); @@ -697,12 +697,12 @@ static int saa7127_probe(struct i2c_client *client) if ((saa7127_read(client, 0) & 0xe4) != 0 || (saa7127_read(client, 0x29) & 0x3f) != 0x1d) { v4l_dbg(1, debug, client, "saa7127 not found\n"); - return 0; + return -ENODEV; } state = kzalloc(sizeof(struct saa7127_state), GFP_KERNEL); if (state == NULL) { - return (-ENOMEM); + return -ENOMEM; } i2c_set_clientdata(client, state); diff --git a/linux/drivers/media/video/tlv320aic23b.c b/linux/drivers/media/video/tlv320aic23b.c index 2e5ed138e..32f4c8c53 100644 --- a/linux/drivers/media/video/tlv320aic23b.c +++ b/linux/drivers/media/video/tlv320aic23b.c @@ -141,7 +141,7 @@ static int tlv320aic23b_probe(struct i2c_client *client) /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; + return -EIO; v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); diff --git a/linux/drivers/media/video/upd64031a.c b/linux/drivers/media/video/upd64031a.c index 9234cbb0d..6cbd124c7 100644 --- a/linux/drivers/media/video/upd64031a.c +++ b/linux/drivers/media/video/upd64031a.c @@ -208,7 +208,7 @@ static int upd64031a_probe(struct i2c_client *client) int i; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; + return -EIO; v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); diff --git a/linux/drivers/media/video/upd64083.c b/linux/drivers/media/video/upd64083.c index 280c593d0..34e99cfbb 100644 --- a/linux/drivers/media/video/upd64083.c +++ b/linux/drivers/media/video/upd64083.c @@ -186,7 +186,7 @@ static int upd64083_probe(struct i2c_client *client) int i; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; + return -EIO; v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index ef4514369..f97d14486 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -1655,7 +1655,7 @@ int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver else { kfree(client); } - return err; + return err != -ENOMEM ? 0 : err; } /* ----------------------------------------------------------------- */ diff --git a/linux/drivers/media/video/vp27smpx.c b/linux/drivers/media/video/vp27smpx.c index fae69bee7..602d7da63 100644 --- a/linux/drivers/media/video/vp27smpx.c +++ b/linux/drivers/media/video/vp27smpx.c @@ -139,7 +139,7 @@ static int vp27smpx_probe(struct i2c_client *client) /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; + return -EIO; snprintf(client->name, sizeof(client->name) - 1, "vp27smpx"); diff --git a/linux/drivers/media/video/wm8739.c b/linux/drivers/media/video/wm8739.c index 953c47ed4..4b5956a8f 100644 --- a/linux/drivers/media/video/wm8739.c +++ b/linux/drivers/media/video/wm8739.c @@ -276,6 +276,10 @@ static int wm8739_probe(struct i2c_client *client) { struct wm8739_state *state; + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); state = kmalloc(sizeof(struct wm8739_state), GFP_KERNEL); -- cgit v1.2.3 From 67da967ca82fae5cdaba3d5b646bc505ba423813 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 18 Sep 2007 08:22:32 +0200 Subject: v4l2-common: minor cleanups. From: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-common.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) --- linux/drivers/media/video/v4l2-common.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index f97d14486..a1d751c8a 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -1640,10 +1640,10 @@ int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver client->addr = address; client->adapter = adapter; client->driver = driver; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) client->flags = I2C_CLIENT_ALLOW_USE; #endif - snprintf(client->name, sizeof(client->name) - 1, name); + strlcpy(client->name, name, sizeof(client->name)); err = probe(client); if (err == 0) { @@ -1651,8 +1651,7 @@ int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) MOD_INC_USE_COUNT; #endif - } - else { + } else { kfree(client); } return err != -ENOMEM ? 0 : err; -- cgit v1.2.3 From 50185c8f6e8634aebd934c66584a299945750772 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 27 Oct 2007 01:00:57 -0400 Subject: tda8290: auto-detect tda8290 or tda8295 From: Michael Krufky Consolidate tda8290_attach() and tda8295_attach() into a single function, tda829x_attach(), which will detect chip combinations tda8290 or tda8295 with tda8275, tda8275a or tda18271. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tda8290.c | 263 +++++++++++++++------------------ linux/drivers/media/video/tda8290.h | 12 - linux/drivers/media/video/tuner-core.c | 6 3 files changed, 130 insertions(+), 151 deletions(-) --- linux/drivers/media/video/tda8290.c | 257 ++++++++++++++++----------------- linux/drivers/media/video/tda8290.h | 12 +- linux/drivers/media/video/tuner-core.c | 6 +- 3 files changed, 127 insertions(+), 148 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tda8290.c b/linux/drivers/media/video/tda8290.c index e4946f9dc..4e0ed4f57 100644 --- a/linux/drivers/media/video/tda8290.c +++ b/linux/drivers/media/video/tda8290.c @@ -50,7 +50,13 @@ struct tda8290_priv { unsigned char tda8290_easy_mode; unsigned char tda827x_addr; - unsigned char tda827x_ver; + + unsigned char ver; +#define TDA8290 1 +#define TDA8295 2 +#define TDA8275 4 +#define TDA8275A 8 +#define TDA18271 16 struct tda827x_config cfg; @@ -167,7 +173,7 @@ static void set_audio(struct dvb_frontend *fe) mode = "xx"; } - tuner_dbg("setting tda8290 to system %s\n", mode); + tuner_dbg("setting tda829x to system %s\n", mode); } static void tda8290_set_freq(struct dvb_frontend *fe, unsigned int freq) @@ -460,7 +466,7 @@ static void tda8290_standby(struct dvb_frontend *fe) struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2}; tda8290_i2c_bridge(fe, 1); - if (priv->tda827x_ver != 0) + if (priv->ver & TDA8275A) cb1[1] = 0x90; i2c_transfer(priv->i2c_props.adap, &msg, 1); tda8290_i2c_bridge(fe, 0); @@ -529,7 +535,7 @@ static void tda8290_init_tuner(struct dvb_frontend *fe) 0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b }; struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=tda8275_init, .len = 14}; - if (priv->tda827x_ver != 0) + if (priv->ver & TDA8275A) msg.buf = tda8275a_init; tda8290_i2c_bridge(fe, 1); @@ -548,48 +554,25 @@ static void tda829x_release(struct dvb_frontend *fe) fe->analog_demod_priv = NULL; } -static struct analog_tuner_ops tda8290_tuner_ops = { - .set_tv_freq = tda8290_set_freq, - .set_radio_freq = tda8290_set_freq, - .has_signal = tda8290_has_signal, - .standby = tda8290_standby, - .release = tda829x_release, - .i2c_gate_ctrl = tda8290_i2c_bridge, -}; - -static struct analog_tuner_ops tda8295_tuner_ops = { - .set_tv_freq = tda8295_set_freq, - .set_radio_freq = tda8295_set_freq, - .has_signal = tda8295_has_signal, - .standby = tda8295_standby, - .release = tda829x_release, - .i2c_gate_ctrl = tda8295_i2c_bridge, -}; - -int tda8290_attach(struct tuner *t) +static int tda829x_find_tuner(struct dvb_frontend *fe) { - struct tda8290_priv *priv = NULL; - u8 data; + struct tda8290_priv *priv = fe->analog_demod_priv; + struct analog_tuner_ops *ops = fe->ops.analog_demod_ops; + struct tuner *t = priv->t; int i, ret, tuners_found; u32 tuner_addrs; - struct i2c_msg msg = {.flags=I2C_M_RD, .buf=&data, .len = 1}; + u8 data; + struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 }; - priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); - if (priv == NULL) - return -ENOMEM; - t->fe.analog_demod_priv = priv; + if (NULL == ops) + return -EINVAL; - priv->i2c_props.addr = t->i2c.addr; - priv->i2c_props.adap = t->i2c.adapter; - priv->cfg.config = &t->config; - priv->cfg.tuner_callback = t->tuner_callback; - priv->t = t; + ops->i2c_gate_ctrl(fe, 1); - tda8290_i2c_bridge(&t->fe, 1); /* probe for tuner chip */ tuners_found = 0; tuner_addrs = 0; - for (i=0x60; i<= 0x63; i++) { + for (i = 0x60; i <= 0x63; i++) { msg.addr = i; ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); if (ret == 1) { @@ -601,20 +584,23 @@ int tda8290_attach(struct tuner *t) behind the bridge and we choose the highest address that doesn't give a response now */ - tda8290_i2c_bridge(&t->fe, 0); - if(tuners_found > 1) + + ops->i2c_gate_ctrl(fe, 0); + + if (tuners_found > 1) for (i = 0; i < tuners_found; i++) { msg.addr = tuner_addrs & 0xff; ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); - if(ret == 1) + if (ret == 1) tuner_addrs = tuner_addrs >> 8; else break; } + if (tuner_addrs == 0) { - tuner_addrs = 0x61; - tuner_info("could not clearly identify tuner address, defaulting to %x\n", - tuner_addrs); + tuner_addrs = 0x60; + tuner_info("could not clearly identify tuner address, " + "defaulting to %x\n", tuner_addrs); } else { tuner_addrs = tuner_addrs & 0xff; tuner_info("setting tuner address to %x\n", tuner_addrs); @@ -622,127 +608,132 @@ int tda8290_attach(struct tuner *t) priv->tda827x_addr = tuner_addrs; msg.addr = tuner_addrs; - tda8290_i2c_bridge(&t->fe, 1); - + ops->i2c_gate_ctrl(fe, 1); ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); - if( ret != 1) - tuner_warn("TDA827x access failed!\n"); - if ((data & 0x3c) == 0) { - strlcpy(t->i2c.name, "tda8290+75", sizeof(t->i2c.name)); - priv->tda827x_ver = 0; - } else { - strlcpy(t->i2c.name, "tda8290+75a", sizeof(t->i2c.name)); - priv->tda827x_ver = 2; + if (ret != 1) { + tuner_warn("tuner access failed!\n"); + return -EREMOTEIO; } - tda827x_attach(&t->fe, priv->tda827x_addr, - priv->i2c_props.adap, &priv->cfg); - /* FIXME: tda827x module doesn't probe the tuner until - * tda827x_initial_sleep is called - */ - if (t->fe.ops.tuner_ops.sleep) - t->fe.ops.tuner_ops.sleep(&t->fe); + if (data == 0x83) { + priv->ver |= TDA18271; + tda18271_attach(&t->fe, priv->tda827x_addr, + priv->i2c_props.adap); + } else { + if ((data & 0x3c) == 0) + priv->ver |= TDA8275; + else + priv->ver |= TDA8275A; - t->fe.ops.analog_demod_ops = &tda8290_tuner_ops; + tda827x_attach(&t->fe, priv->tda827x_addr, + priv->i2c_props.adap, &priv->cfg); - tuner_info("type set to %s\n", t->i2c.name); + /* FIXME: tda827x module doesn't probe the tuner until + * tda827x_initial_sleep is called + */ + if (t->fe.ops.tuner_ops.sleep) + t->fe.ops.tuner_ops.sleep(&t->fe); + } + ops->i2c_gate_ctrl(fe, 0); - t->mode = V4L2_TUNER_ANALOG_TV; + switch (priv->ver) { + case TDA8290 | TDA8275: + strlcpy(t->i2c.name, "tda8290+75", sizeof(t->i2c.name)); + break; + case TDA8295 | TDA8275: + strlcpy(t->i2c.name, "tda8295+75", sizeof(t->i2c.name)); + break; + case TDA8290 | TDA8275A: + strlcpy(t->i2c.name, "tda8290+75a", sizeof(t->i2c.name)); + break; + case TDA8295 | TDA8275A: + strlcpy(t->i2c.name, "tda8295+75a", sizeof(t->i2c.name)); + break; + case TDA8290 | TDA18271: + strlcpy(t->i2c.name, "tda8290+18271", sizeof(t->i2c.name)); + break; + case TDA8295 | TDA18271: + strlcpy(t->i2c.name, "tda8295+18271", sizeof(t->i2c.name)); + break; + default: + return -EINVAL; + } - tda8290_init_tuner(&t->fe); - tda8290_init_if(&t->fe); return 0; } -EXPORT_SYMBOL_GPL(tda8290_attach); -int tda8295_attach(struct tuner *t) +static struct analog_tuner_ops tda8290_tuner_ops = { + .set_tv_freq = tda8290_set_freq, + .set_radio_freq = tda8290_set_freq, + .has_signal = tda8290_has_signal, + .standby = tda8290_standby, + .release = tda829x_release, + .i2c_gate_ctrl = tda8290_i2c_bridge, +}; + +static struct analog_tuner_ops tda8295_tuner_ops = { + .set_tv_freq = tda8295_set_freq, + .set_radio_freq = tda8295_set_freq, + .has_signal = tda8295_has_signal, + .standby = tda8295_standby, + .release = tda829x_release, + .i2c_gate_ctrl = tda8295_i2c_bridge, +}; + +int tda829x_attach(struct tuner *t) { + struct dvb_frontend *fe = &t->fe; struct tda8290_priv *priv = NULL; - u8 data; - int i, ret, tuners_found; - u32 tuner_addrs; - struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 }; + + unsigned char tda8290_id[] = { 0x1f, 0x00 }; +#define TDA8290_ID 0x89 + unsigned char tda8295_id[] = { 0x2f, 0x00 }; +#define TDA8295_ID 0x8a priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); if (priv == NULL) return -ENOMEM; - t->fe.analog_demod_priv = priv; + fe->analog_demod_priv = priv; priv->i2c_props.addr = t->i2c.addr; priv->i2c_props.adap = t->i2c.adapter; + priv->cfg.config = &t->config; + priv->cfg.tuner_callback = t->tuner_callback; priv->t = t; - tda8295_i2c_bridge(&t->fe, 1); - /* probe for tuner chip */ - tuners_found = 0; - tuner_addrs = 0; - for (i = 0x60; i <= 0x63; i++) { - msg.addr = i; - ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); - if (ret == 1) { - tuners_found++; - tuner_addrs = (tuner_addrs << 8) + i; - } + /* detect tda8290 */ + tuner_i2c_xfer_send(&priv->i2c_props, &tda8290_id[0], 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &tda8290_id[1], 1); + if (tda8290_id[1] == TDA8290_ID) { + priv->ver = TDA8290; + fe->ops.analog_demod_ops = &tda8290_tuner_ops; } - /* if there is more than one tuner, we expect the right one is - behind the bridge and we choose the highest address that doesn't - give a response now - */ - tda8295_i2c_bridge(&t->fe, 0); - if (tuners_found > 1) - for (i = 0; i < tuners_found; i++) { - msg.addr = tuner_addrs & 0xff; - ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); - if (ret == 1) - tuner_addrs = tuner_addrs >> 8; - else - break; - } - if (tuner_addrs == 0) { - tuner_addrs = 0x60; - tuner_info("could not clearly identify tuner address, " - "defaulting to %x\n", tuner_addrs); - } else { - tuner_addrs = tuner_addrs & 0xff; - tuner_info("setting tuner address to %x\n", tuner_addrs); + + /* detect tda8295 */ + tuner_i2c_xfer_send(&priv->i2c_props, &tda8295_id[0], 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &tda8295_id[1], 1); + if (tda8295_id[1] == TDA8295_ID) { + priv->ver = TDA8295; + fe->ops.analog_demod_ops = &tda8295_tuner_ops; } - priv->tda827x_addr = tuner_addrs; - msg.addr = tuner_addrs; - tda8295_i2c_bridge(&t->fe, 1); - ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); - tda8295_i2c_bridge(&t->fe, 0); - if (ret != 1) - tuner_warn("TDA827x access failed!\n"); - if ((data & 0x3c) == 0) { - strlcpy(t->i2c.name, "tda8295+18271", sizeof(t->i2c.name)); - tda18271_attach(&t->fe, priv->tda827x_addr, - priv->i2c_props.adap); - priv->tda827x_ver = 4; - } else { - strlcpy(t->i2c.name, "tda8295+75a", sizeof(t->i2c.name)); - tda827x_attach(&t->fe, priv->tda827x_addr, - priv->i2c_props.adap, &priv->cfg); + if (tda829x_find_tuner(fe) < 0) + return -EINVAL; - /* FIXME: tda827x module doesn't probe the tuner until - * tda827x_initial_sleep is called - */ - if (t->fe.ops.tuner_ops.sleep) - t->fe.ops.tuner_ops.sleep(&t->fe); - priv->tda827x_ver = 2; - } - priv->tda827x_ver |= 1; /* signifies 8295 vs 8290 */ - tuner_info("type set to %s\n", t->i2c.name); + if (priv->ver & TDA8290) { + tda8290_init_tuner(fe); + tda8290_init_if(fe); + } else if (priv->ver & TDA8295) + tda8295_init_if(fe); - t->fe.ops.analog_demod_ops = &tda8295_tuner_ops; + tuner_info("type set to %s\n", t->i2c.name); t->mode = V4L2_TUNER_ANALOG_TV; - tda8295_init_if(&t->fe); return 0; } -EXPORT_SYMBOL_GPL(tda8295_attach); +EXPORT_SYMBOL_GPL(tda829x_attach); int tda8290_probe(struct tuner *t) { @@ -776,7 +767,7 @@ int tda8290_probe(struct tuner *t) } EXPORT_SYMBOL_GPL(tda8290_probe); -MODULE_DESCRIPTION("Philips TDA8290 + TDA8275 / TDA8275a tuner driver"); +MODULE_DESCRIPTION("Philips/NXP TDA8290/TDA8295 analog IF demodulator driver"); MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky"); MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/video/tda8290.h b/linux/drivers/media/video/tda8290.h index dbbcb0f00..81517370b 100644 --- a/linux/drivers/media/video/tda8290.h +++ b/linux/drivers/media/video/tda8290.h @@ -23,8 +23,7 @@ #if defined(CONFIG_TUNER_TDA8290) || (defined(CONFIG_TUNER_TDA8290_MODULE) && defined(MODULE)) extern int tda8290_probe(struct tuner *t); -extern int tda8290_attach(struct tuner *t); -extern int tda8295_attach(struct tuner *t); +extern int tda829x_attach(struct tuner *t); #else static inline int tda8290_probe(struct tuner *t) { @@ -32,14 +31,7 @@ static inline int tda8290_probe(struct tuner *t) return -EINVAL; } -static inline int tda8290_attach(struct tuner *t) -{ - printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", - __FUNCTION__); - return -EINVAL; -} - -static inline int tda8295_attach(struct tuner *t) +static inline int tda829x_attach(struct tuner *t) { printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", __FUNCTION__); diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 9e7cf77e0..630b19ef0 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -322,13 +322,9 @@ static void set_type(struct i2c_client *c, unsigned int type, microtune_attach(&t->fe, t->i2c.adapter, t->i2c.addr); break; case TUNER_PHILIPS_TDA8290: - { - tda8290_attach(t); - break; - } case TUNER_PHILIPS_TDA8295: { - tda8295_attach(t); + tda829x_attach(t); break; } case TUNER_TEA5767: -- cgit v1.2.3 From 9fe310f613a6c6124a696705caef1d454a0fd7bf Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 27 Oct 2007 12:09:16 -0400 Subject: tuner: remove TUNER_PHILIPS_TDA8295 From: Michael Krufky TUNER_PHILIPS_TDA8290 will autodetect a TDA8290 or a TDA8295, so we don't need this separate entry anymore. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/CARDLIST.tuner | 3 +-- linux/drivers/media/video/tuner-core.c | 1 - linux/drivers/media/video/tuner-types.c | 5 +---- linux/drivers/media/video/tveeprom.c | 2 +- linux/include/media/tuner.h | 2 -- 5 files changed, 3 insertions(+), 10 deletions(-) --- linux/drivers/media/video/tuner-core.c | 1 - linux/drivers/media/video/tuner-types.c | 5 +---- linux/drivers/media/video/tveeprom.c | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 630b19ef0..ef75a7bc3 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -322,7 +322,6 @@ static void set_type(struct i2c_client *c, unsigned int type, microtune_attach(&t->fe, t->i2c.adapter, t->i2c.addr); break; case TUNER_PHILIPS_TDA8290: - case TUNER_PHILIPS_TDA8295: { tda829x_attach(t); break; diff --git a/linux/drivers/media/video/tuner-types.c b/linux/drivers/media/video/tuner-types.c index c1746464e..9076b538d 100644 --- a/linux/drivers/media/video/tuner-types.c +++ b/linux/drivers/media/video/tuner-types.c @@ -1414,7 +1414,7 @@ struct tunertype tuners[] = { .count = ARRAY_SIZE(tuner_philips_fq1286_params), }, [TUNER_PHILIPS_TDA8290] = { /* Philips PAL|NTSC */ - .name = "tda8290+75", + .name = "Philips/NXP TDA 8290/8295 + 8275/8275A/18271", /* see tda8290.c for details */ }, [TUNER_TCL_2002MB] = { /* TCL PAL */ .name = "TCL 2002MB", @@ -1523,9 +1523,6 @@ struct tunertype tuners[] = { .name = "Philips TEA5761 FM Radio", /* see tea5767.c for details */ }, - [TUNER_PHILIPS_TDA8295] = { /* Philips PAL|NTSC */ - .name = "tda8295+18271", - /* see tda8290.c for details */ }, }; unsigned const int tuner_count = ARRAY_SIZE(tuners); diff --git a/linux/drivers/media/video/tveeprom.c b/linux/drivers/media/video/tveeprom.c index c3a67eba2..d0bbf7969 100644 --- a/linux/drivers/media/video/tveeprom.c +++ b/linux/drivers/media/video/tveeprom.c @@ -261,7 +261,7 @@ hauppauge_tuner[] = { TUNER_ABSENT, "LG TAPQ_H702F"}, { TUNER_ABSENT, "TCL M09WPP_4N_E"}, { TUNER_ABSENT, "MaxLinear MXL5005_v2"}, - { TUNER_PHILIPS_TDA8295, "Philips 18271_8295"}, + { TUNER_PHILIPS_TDA8290, "Philips 18271_8295"}, }; static struct HAUPPAUGE_AUDIOIC -- cgit v1.2.3 From 45d49155305901c4e98c65f2fb47541d59b5bcc5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Oct 2007 11:33:18 -0300 Subject: Avoid breaking compilation From: Mauro Carvalho Chehab The next patchset series will change i2c structs inside tuner. This patch avoids breaking bissect, by commenting the still unused tuner xc2028. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-core.c | 2 ++ 1 file changed, 2 insertions(+) --- linux/drivers/media/video/tuner-core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index ef75a7bc3..969530094 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -362,6 +362,7 @@ static void set_type(struct i2c_client *c, unsigned int type, i2c_master_send(c,buffer,4); attach_simple_tuner(t); break; +#if 0 case TUNER_XC2028: { int rc=xc2028_attach(&t->fe, t->i2c.adapter, t->i2c.addr, @@ -374,6 +375,7 @@ static void set_type(struct i2c_client *c, unsigned int type, } break; } +#endif case TUNER_TDA9887: tda9887_attach(t); break; -- cgit v1.2.3 From ee8841ac8cd3158d3cc78ed87925dbf4768dd2f8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 14 Sep 2007 10:13:54 +0200 Subject: tuner: i2c_client cannot be part of the tuner struct From: Hans Verkuil The bus-based I2C subsystem allocates the i2c_client struct. So if in order to be able to convert the tuner to the bus-based I2C API the embedded i2c_client struct must be removed from the tuner struct and replaced with a pointer. Signed-off-by: Hans Verkuil Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tda8290.c | 22 ++++++------- linux/drivers/media/video/tda9887.c | 22 ++++++------- linux/drivers/media/video/tuner-core.c | 51 ++++++++++++++++++------------- linux/drivers/media/video/tuner-driver.h | 26 +++++++-------- 4 files changed, 65 insertions(+), 56 deletions(-) --- linux/drivers/media/video/tda8290.c | 22 +++++++------- linux/drivers/media/video/tda9887.c | 22 +++++++------- linux/drivers/media/video/tuner-core.c | 51 +++++++++++++++++++------------- linux/drivers/media/video/tuner-driver.h | 26 ++++++++-------- 4 files changed, 65 insertions(+), 56 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tda8290.c b/linux/drivers/media/video/tda8290.c index 4e0ed4f57..8026e65a8 100644 --- a/linux/drivers/media/video/tda8290.c +++ b/linux/drivers/media/video/tda8290.c @@ -639,22 +639,22 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) switch (priv->ver) { case TDA8290 | TDA8275: - strlcpy(t->i2c.name, "tda8290+75", sizeof(t->i2c.name)); + strlcpy(t->i2c->name, "tda8290+75", sizeof(t->i2c->name)); break; case TDA8295 | TDA8275: - strlcpy(t->i2c.name, "tda8295+75", sizeof(t->i2c.name)); + strlcpy(t->i2c->name, "tda8295+75", sizeof(t->i2c->name)); break; case TDA8290 | TDA8275A: - strlcpy(t->i2c.name, "tda8290+75a", sizeof(t->i2c.name)); + strlcpy(t->i2c->name, "tda8290+75a", sizeof(t->i2c->name)); break; case TDA8295 | TDA8275A: - strlcpy(t->i2c.name, "tda8295+75a", sizeof(t->i2c.name)); + strlcpy(t->i2c->name, "tda8295+75a", sizeof(t->i2c->name)); break; case TDA8290 | TDA18271: - strlcpy(t->i2c.name, "tda8290+18271", sizeof(t->i2c.name)); + strlcpy(t->i2c->name, "tda8290+18271", sizeof(t->i2c->name)); break; case TDA8295 | TDA18271: - strlcpy(t->i2c.name, "tda8295+18271", sizeof(t->i2c.name)); + strlcpy(t->i2c->name, "tda8295+18271", sizeof(t->i2c->name)); break; default: return -EINVAL; @@ -696,8 +696,8 @@ int tda829x_attach(struct tuner *t) return -ENOMEM; fe->analog_demod_priv = priv; - priv->i2c_props.addr = t->i2c.addr; - priv->i2c_props.adap = t->i2c.adapter; + priv->i2c_props.addr = t->i2c->addr; + priv->i2c_props.adap = t->i2c->adapter; priv->cfg.config = &t->config; priv->cfg.tuner_callback = t->tuner_callback; priv->t = t; @@ -727,7 +727,7 @@ int tda829x_attach(struct tuner *t) } else if (priv->ver & TDA8295) tda8295_init_if(fe); - tuner_info("type set to %s\n", t->i2c.name); + tuner_info("type set to %s\n", t->i2c->name); t->mode = V4L2_TUNER_ANALOG_TV; @@ -738,8 +738,8 @@ EXPORT_SYMBOL_GPL(tda829x_attach); int tda8290_probe(struct tuner *t) { struct tuner_i2c_props i2c_props = { - .adap = t->i2c.adapter, - .addr = t->i2c.addr + .adap = t->i2c->adapter, + .addr = t->i2c->addr }; unsigned char soft_reset[] = { 0x00, 0x00 }; diff --git a/linux/drivers/media/video/tda9887.c b/linux/drivers/media/video/tda9887.c index e21345147..cefba2a14 100644 --- a/linux/drivers/media/video/tda9887.c +++ b/linux/drivers/media/video/tda9887.c @@ -28,14 +28,14 @@ static int tda9887_debug; module_param_named(debug, tda9887_debug, int, 0644); #define tda9887_info(fmt, arg...) do {\ - printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c.name, \ - i2c_adapter_id(priv->t->i2c.adapter), \ - priv->t->i2c.addr, ##arg); } while (0) + printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c->name, \ + i2c_adapter_id(priv->t->i2c->adapter), \ + priv->t->i2c->addr, ##arg); } while (0) #define tda9887_dbg(fmt, arg...) do {\ if (tda9887_debug) \ - printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c.name, \ - i2c_adapter_id(priv->t->i2c.adapter), \ - priv->t->i2c.addr, ##arg); } while (0) + printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c->name, \ + i2c_adapter_id(priv->t->i2c->adapter), \ + priv->t->i2c->addr, ##arg); } while (0) struct tda9887_priv { struct tuner_i2c_props i2c_props; @@ -662,14 +662,14 @@ int tda9887_attach(struct tuner *t) return -ENOMEM; t->fe.analog_demod_priv = priv; - priv->i2c_props.addr = t->i2c.addr; - priv->i2c_props.adap = t->i2c.adapter; + priv->i2c_props.addr = t->i2c->addr; + priv->i2c_props.adap = t->i2c->adapter; priv->t = t; - strlcpy(t->i2c.name, "tda9887", sizeof(t->i2c.name)); + strlcpy(t->i2c->name, "tda9887", sizeof(t->i2c->name)); - tda9887_info("tda988[5/6/7] found @ 0x%x (%s)\n", t->i2c.addr, - t->i2c.driver->driver.name); + tda9887_info("tda988[5/6/7] found @ 0x%x (%s)\n", t->i2c->addr, + t->i2c->driver->driver.name); t->fe.ops.analog_demod_ops = &tda9887_tuner_ops; diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 969530094..ba05f9630 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -251,20 +251,20 @@ static void set_freq(struct i2c_client *c, unsigned long freq) static void tuner_i2c_address_check(struct tuner *t) { if ((t->type == UNSET || t->type == TUNER_ABSENT) || - ((t->i2c.addr < 0x64) || (t->i2c.addr > 0x6f))) + ((t->i2c->addr < 0x64) || (t->i2c->addr > 0x6f))) return; tuner_warn("====================== WARNING! ======================\n"); tuner_warn("Support for tuners in i2c address range 0x64 thru 0x6f\n"); tuner_warn("will soon be dropped. This message indicates that your\n"); tuner_warn("hardware has a %s tuner at i2c address 0x%02x.\n", - t->i2c.name, t->i2c.addr); + t->i2c->name, t->i2c->addr); tuner_warn("To ensure continued support for your device, please\n"); tuner_warn("send a copy of this message, along with full dmesg\n"); tuner_warn("output to v4l-dvb-maintainer@linuxtv.org\n"); tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n"); tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n", - t->i2c.adapter->name, t->i2c.addr, t->type, + t->i2c->adapter->name, t->i2c->addr, t->type, tuners[t->type].name); tuner_warn("====================== WARNING! ======================\n"); } @@ -275,7 +275,7 @@ static void attach_simple_tuner(struct tuner *t) .type = t->type, .tun = &tuners[t->type] }; - simple_tuner_attach(&t->fe, t->i2c.adapter, t->i2c.addr, &cfg); + simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg); } static void set_type(struct i2c_client *c, unsigned int type, @@ -319,7 +319,7 @@ static void set_type(struct i2c_client *c, unsigned int type, switch (t->type) { case TUNER_MT2032: - microtune_attach(&t->fe, t->i2c.adapter, t->i2c.addr); + microtune_attach(&t->fe, t->i2c->adapter, t->i2c->addr); break; case TUNER_PHILIPS_TDA8290: { @@ -327,7 +327,7 @@ static void set_type(struct i2c_client *c, unsigned int type, break; } case TUNER_TEA5767: - if (tea5767_attach(&t->fe, t->i2c.adapter, t->i2c.addr) == NULL) { + if (tea5767_attach(&t->fe, t->i2c->adapter, t->i2c->addr) == NULL) { t->type = TUNER_ABSENT; t->mode_mask = T_UNINITIALIZED; return; @@ -335,7 +335,7 @@ static void set_type(struct i2c_client *c, unsigned int type, t->mode_mask = T_RADIO; break; case TUNER_TEA5761: - if (tea5761_attach(&t->fe, t->i2c.adapter, t->i2c.addr) == NULL) { + if (tea5761_attach(&t->fe, t->i2c->adapter, t->i2c->addr) == NULL) { t->type = TUNER_ABSENT; t->mode_mask = T_UNINITIALIZED; return; @@ -389,13 +389,14 @@ static void set_type(struct i2c_client *c, unsigned int type, if (((NULL == ops) || ((NULL == ops->set_tv_freq) && (NULL == ops->set_radio_freq))) && (fe_tuner_ops->set_analog_params)) { - strlcpy(t->i2c.name, fe_tuner_ops->info.name, sizeof(t->i2c.name)); + strlcpy(t->i2c->name, fe_tuner_ops->info.name, + sizeof(t->i2c->name)); t->fe.ops.analog_demod_ops = &tuner_core_ops; t->fe.analog_demod_priv = t; } - tuner_info("type set to %s\n", t->i2c.name); + tuner_info("type set to %s\n", t->i2c->name); if (t->mode_mask == T_UNINITIALIZED) t->mode_mask = new_mode_mask; @@ -634,16 +635,23 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, unsigned short flags, int kind) #endif { + struct i2c_client *client; struct tuner *t; - client_template.adapter = adap; - client_template.addr = addr; + client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (NULL == client) + return -ENOMEM; t = kzalloc(sizeof(struct tuner), GFP_KERNEL); - if (NULL == t) + if (NULL == t) { + kfree(client); return -ENOMEM; - memcpy(&t->i2c, &client_template, sizeof(struct i2c_client)); - i2c_set_clientdata(&t->i2c, t); + } + t->i2c = client; + client_template.adapter = adap; + client_template.addr = addr; + memcpy(client, &client_template, sizeof(struct i2c_client)); + i2c_set_clientdata(client, t); t->type = UNSET; t->audmode = V4L2_TUNER_MODE_STEREO; t->mode_mask = T_UNINITIALIZED; @@ -653,7 +661,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int i,rc; memset(buffer, 0, sizeof(buffer)); - rc = i2c_master_recv(&t->i2c, buffer, sizeof(buffer)); + rc = i2c_master_recv(client, buffer, sizeof(buffer)); tuner_info("I2C RECV = "); for (i=0;ii2c.adapter, t->i2c.addr) != EINVAL) { + if (tea5761_autodetection(t->i2c->adapter, t->i2c->addr) != EINVAL) { t->type = TUNER_TEA5761; t->mode_mask = T_RADIO; t->mode = T_STANDBY; @@ -694,7 +702,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, } break; case 0x60: - if (tea5767_autodetection(t->i2c.adapter, t->i2c.addr) != EINVAL) { + if (tea5767_autodetection(t->i2c->adapter, t->i2c->addr) != EINVAL) { t->type = TUNER_TEA5767; t->mode_mask = T_RADIO; t->mode = T_STANDBY; @@ -719,8 +727,8 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, /* Should be just before return */ register_client: tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name); - i2c_attach_client (&t->i2c); - set_type (&t->i2c,t->type, t->mode_mask, t->config, t->tuner_callback); + i2c_attach_client (client); + set_type (client,t->type, t->mode_mask, t->config, t->tuner_callback); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) MOD_INC_USE_COUNT; #endif @@ -774,7 +782,7 @@ static int tuner_detach(struct i2c_client *client) struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; 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"); @@ -788,6 +796,7 @@ MOD_DEC_USE_COUNT; ops->release(&t->fe); kfree(t); + kfree(client); return 0; } @@ -842,7 +851,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; if (tuner_debug>1) - v4l_i2c_print_ioctl(&(t->i2c),cmd); + v4l_i2c_print_ioctl(client,cmd); switch (cmd) { /* --- configuration --- */ diff --git a/linux/drivers/media/video/tuner-driver.h b/linux/drivers/media/video/tuner-driver.h index ad2d57dfb..d5acacebd 100644 --- a/linux/drivers/media/video/tuner-driver.h +++ b/linux/drivers/media/video/tuner-driver.h @@ -45,7 +45,7 @@ struct analog_tuner_ops { struct tuner { /* device */ - struct i2c_client i2c; + struct i2c_client *i2c; unsigned int type; /* chip type */ @@ -72,28 +72,28 @@ struct tuner { #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) #define tuner_warn(fmt, arg...) do {\ - printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->name, \ - i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) + printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c->driver->name, \ + i2c_adapter_id(t->i2c->adapter), t->i2c->addr , ##arg); } while (0) #define tuner_info(fmt, arg...) do {\ - printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.driver->name, \ - i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) + printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c->driver->name, \ + i2c_adapter_id(t->i2c->adapter), t->i2c->addr , ##arg); } while (0) #define tuner_dbg(fmt, arg...) do {\ extern int tuner_debug; \ if (tuner_debug) \ - printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->name, \ - i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) + printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c->driver->name, \ + i2c_adapter_id(t->i2c->adapter), t->i2c->addr , ##arg); } while (0) #else #define tuner_warn(fmt, arg...) do {\ - printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \ - i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) + printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c->driver->driver.name, \ + i2c_adapter_id(t->i2c->adapter), t->i2c->addr , ##arg); } while (0) #define tuner_info(fmt, arg...) do {\ - printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \ - i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) + printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c->driver->driver.name, \ + i2c_adapter_id(t->i2c->adapter), t->i2c->addr , ##arg); } while (0) #define tuner_dbg(fmt, arg...) do {\ extern int tuner_debug; \ if (tuner_debug) \ - printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \ - i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) + printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c->driver->driver.name, \ + i2c_adapter_id(t->i2c->adapter), t->i2c->addr , ##arg); } while (0) #endif #endif /* __TUNER_DRIVER_H__ */ -- cgit v1.2.3 From 20340f725c5078f9bdc715efb2e926d6ce408816 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Oct 2007 11:33:18 -0300 Subject: Re-inserts xc2028 attach code, fixing its parameters From: Mauro Carvalho Chehab I2C bus redesign changed i2c parameters. This patch re-adds tuner xc2028 attach function, replacing the parameters to the newer syntax. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) --- linux/drivers/media/video/tuner-core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index ba05f9630..71ef32124 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -362,10 +362,9 @@ static void set_type(struct i2c_client *c, unsigned int type, i2c_master_send(c,buffer,4); attach_simple_tuner(t); break; -#if 0 case TUNER_XC2028: { - int rc=xc2028_attach(&t->fe, t->i2c.adapter, t->i2c.addr, + int rc=xc2028_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &c->dev, c->adapter->algo_data, t->tuner_callback); if (rc<0) { @@ -375,7 +374,6 @@ static void set_type(struct i2c_client *c, unsigned int type, } break; } -#endif case TUNER_TDA9887: tda9887_attach(t); break; -- cgit v1.2.3 From d10b8499d66b31d7e906fe3303b9d86ad7a6858f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Oct 2007 11:33:18 -0300 Subject: Prevents double tuner registering From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-core.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) --- linux/drivers/media/video/tuner-core.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 71ef32124..c53b64fb8 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -304,14 +304,11 @@ static void set_type(struct i2c_client *c, unsigned int type, t->tuner_callback = tuner_callback; } -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - /* This code detects calls by card attach_inform */ - if (NULL == t->i2c.dev.driver) { + if (t->mode == T_UNINITIALIZED) { tuner_dbg ("tuner 0x%02x: called during i2c_client register by adapter's attach_inform\n", c->addr); return; } -#endif /* discard private data, in case set_type() was previously called */ if (ops && ops->release) @@ -725,6 +722,16 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, /* Should be just before return */ register_client: tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name); + + /* Sets a default mode */ + if (t->mode_mask & T_ANALOG_TV) { + t->mode = T_ANALOG_TV; + } else if (t->mode_mask & T_RADIO) { + t->mode = T_RADIO; + } else { + t->mode = T_DIGITAL_TV; + } + i2c_attach_client (client); set_type (client,t->type, t->mode_mask, t->config, t->tuner_callback); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -- cgit v1.2.3 From 066e2491364ea04d408a789efcaa152066e82cfe Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Oct 2007 11:33:18 -0300 Subject: Add support for tuner-xc2028 From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) --- linux/drivers/media/video/em28xx/em28xx-cards.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 441b03d30..29d7031d1 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -36,6 +36,7 @@ #include #include "em28xx.h" +#include "tuner-xc2028.h" struct em28xx_board em28xx_boards[] = { [EM2800_BOARD_UNKNOWN] = { @@ -363,6 +364,21 @@ void em28xx_pre_card_setup(struct em28xx *dev) } } +static void em28xx_config_tuner (struct em28xx *dev) +{ + struct v4l2_priv_tun_config xc2028_cfg; + struct xc2028_ctrl ctl; + + memset (&ctl,0,sizeof(ctl)); + + ctl.fname = XC2028_DEFAULT_FIRMWARE; + + xc2028_cfg.tuner = TUNER_XC2028; + xc2028_cfg.priv = &ctl; + + em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg); +} + void em28xx_card_setup(struct em28xx *dev) { /* request some modules */ @@ -395,6 +411,7 @@ void em28xx_card_setup(struct em28xx *dev) } } + em28xx_config_tuner (dev); } MODULE_DEVICE_TABLE (usb, em28xx_id_table); -- cgit v1.2.3 From 0f9b6245afd4197cd3e92b390985f6e9e4c2b09c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Oct 2007 18:38:59 -0200 Subject: Fix some troubles at list handling From: Mauro Carvalho Chehab - priv->count were wrong. Should be incremented since the first usage; - forgot to use list_del() to remove the driver; - Release memory if an error occurs during _attach Thanks to Aidan Thornton for pointing this. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-xc2028.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c index 9b6e7c006..4b429759b 100644 --- a/linux/drivers/media/video/tuner-xc2028.c +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -653,6 +653,8 @@ static int xc2028_dvb_release(struct dvb_frontend *fe) priv->count--; if (!priv->count) { + list_del(&priv->xc2028_list); + if (priv->ctrl.fname) kfree(priv->ctrl.fname); @@ -742,7 +744,6 @@ int xc2028_attach(struct dvb_frontend *fe, struct i2c_adapter* i2c_adap, list_for_each_entry(priv, &xc2028_list, xc2028_list) { if (priv->dev == dev) { dev = NULL; - priv->count++; } } @@ -769,8 +770,10 @@ int xc2028_attach(struct dvb_frontend *fe, struct i2c_adapter* i2c_adap, priv->ctrl.fname = kmalloc(sizeof(DEFAULT_FIRMWARE)+1, GFP_KERNEL); - if (!priv->ctrl.fname) + if (!priv->ctrl.fname) { + kfree (priv); return -ENOMEM; + } strcpy (priv->ctrl.fname, DEFAULT_FIRMWARE); #endif @@ -779,6 +782,7 @@ int xc2028_attach(struct dvb_frontend *fe, struct i2c_adapter* i2c_adap, list_add_tail(&priv->xc2028_list,&xc2028_list); } + priv->count++; memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops, sizeof(xc2028_dvb_tuner_ops)); -- cgit v1.2.3 From cc32a31b441fde4d431e0688f8ed4d24227d560f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Oct 2007 00:36:12 -0200 Subject: Add support for analog tv on HVR-950 From: Mauro Carvalho Chehab This patch adds USB ID for HVR-950. It also adds the callback for handling firmware loading. Thanks to Markus Reichberger for the reset commands. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 1 + linux/drivers/media/video/em28xx/em28xx-i2c.c | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 29d7031d1..b9a11dee2 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -345,6 +345,7 @@ struct usb_device_id em28xx_id_table [] = { { USB_DEVICE(0x2040, 0x4200), .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, { USB_DEVICE(0x2304, 0x0207), .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, { USB_DEVICE(0x2040, 0x6500), .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, + { USB_DEVICE(0x2040, 0x6513), .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, { USB_DEVICE(0x0ccd, 0x0042), .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS }, { USB_DEVICE(0x0ccd, 0x0047), .driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS }, { }, diff --git a/linux/drivers/media/video/em28xx/em28xx-i2c.c b/linux/drivers/media/video/em28xx/em28xx-i2c.c index 5d102ec8c..209370e2b 100644 --- a/linux/drivers/media/video/em28xx/em28xx-i2c.c +++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c @@ -28,6 +28,7 @@ #include #include "em28xx.h" +#include "tuner-xc2028.h" #include #include @@ -402,6 +403,26 @@ static void dec_use(struct i2c_adapter *adap) } #endif +static int em28xx_tuner_callback(void *ptr, int command, int arg) +{ + int rc = 0; + struct em28xx *dev = ptr; + + if (dev->tuner_type != TUNER_XC2028) + return 0; + + switch (command) { + case XC2028_TUNER_RESET: + /* FIXME: This is device-dependent */ + dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); + dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1); + + msleep(140); + break; + } + return rc; +} + static int em28xx_set_tuner(int check_eeprom, struct i2c_client *client) { struct em28xx *dev = client->adapter->algo_data; @@ -411,6 +432,8 @@ static int em28xx_set_tuner(int check_eeprom, struct i2c_client *client) tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; tun_setup.type = dev->tuner_type; tun_setup.addr = dev->tuner_addr; + tun_setup.tuner_callback = em28xx_tuner_callback; + em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); } -- cgit v1.2.3 From 37d64f65c705d977dd13a6f07100564529611f80 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Oct 2007 00:44:18 -0200 Subject: Properly fill MODULE_AUTHOR From: Mauro Carvalho Chehab Most of the driver were written by Mauro Carvalho Chehab. DTV parts were added by Michel Ludwig. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-xc2028.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c index 4b429759b..fdea79c28 100644 --- a/linux/drivers/media/video/tuner-xc2028.c +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -1,8 +1,10 @@ /* tuner-xc2028 * * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org) + * * Copyright (c) 2007 Michel Ludwig (michel.ludwig@gmail.com) * - frontend interface + * * This code is placed under the terms of the GNU General Public License v2 */ @@ -795,5 +797,6 @@ int xc2028_attach(struct dvb_frontend *fe, struct i2c_adapter* i2c_adap, EXPORT_SYMBOL(xc2028_attach); MODULE_DESCRIPTION("Xceive xc2028/xc3028 tuner driver"); +MODULE_AUTHOR("Michel Ludwig "); MODULE_AUTHOR("Mauro Carvalho Chehab "); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 22699c0378fb8951eba42a940df115803c37da7e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Oct 2007 11:19:50 -0700 Subject: ir-functions use input functions, should depend on INPUT From: Randy Dunlap Media ir-functions uses input_(*) functions so it should depend on the INPUT config symbol. drivers/built-in.o: In function `ir_input_key_event': ir-functions.c:(.text+0x10849a): undefined reference to `input_event' ir-functions.c:(.text+0x1084ac): undefined reference to `input_event' Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/Kconfig b/linux/drivers/media/Kconfig index 951ce4896..8f4a45346 100644 --- a/linux/drivers/media/Kconfig +++ b/linux/drivers/media/Kconfig @@ -171,6 +171,7 @@ config VIDEO_IR_I2C config VIDEO_IR tristate + depends on INPUT select VIDEO_IR_I2C if I2C config VIDEO_TVEEPROM -- cgit v1.2.3 From 49ee8f98168f5871acfe0c379f8c8881b76197d9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Oct 2007 11:19:55 -0700 Subject: use input functions, should depend on INPUT From: Randy Dunlap All of these drivers select VIDEO_IR, which uses the input subsystem, so they should also depend on INPUT. Problem examples: drivers/built-in.o: In function `ir_input_key_event': ir-functions.c:(.text+0x10849a): undefined reference to `input_event' ir-functions.c:(.text+0x1084ac): undefined reference to `input_event' drivers/built-in.o: In function `saa7134_set_i2c_ir': (.text+0x11cc0a): undefined reference to `get_key_pinnacle_color' drivers/built-in.o: In function `saa7134_set_i2c_ir': (.text+0x11cc4f): undefined reference to `get_key_pinnacle_grey' drivers/built-in.o: In function `saa7134_input_fini': (.text+0x11cd8b): undefined reference to `input_unregister_device' drivers/built-in.o: In function `saa7134_input_init1': (.text+0x11d1fa): undefined reference to `input_allocate_device' drivers/built-in.o: In function `saa7134_input_init1': (.text+0x11d317): undefined reference to `input_register_device' drivers/built-in.o: In function `saa7134_input_init1': (.text+0x11d6ca): undefined reference to `input_free_device' drivers/built-in.o: In function `saa7134_set_i2c_ir': (.text+0x11c3f3): undefined reference to `ir_codes_hauppauge_new' drivers/built-in.o: In function `saa7134_set_i2c_ir': (.text+0x11c450): undefined reference to `ir_codes_pinnacle_color' drivers/built-in.o: In function `saa7134_set_i2c_ir': (.text+0x11c480): undefined reference to `ir_codes_purpletv' drivers/built-in.o: In function `saa7134_set_i2c_ir': (.text+0x11c495): undefined reference to `ir_codes_pinnacle_grey' drivers/built-in.o: In function `saa7134_ir_start': (.text+0x11c622): undefined reference to `ir_rc5_timer_end' drivers/built-in.o: In function `saa7134_ir_start': (.text+0x11c637): undefined reference to `ir_rc5_timer_keyup' drivers/built-in.o: In function `build_key': saa7134-input.c:(.text+0x11c769): undefined reference to `ir_extract_bits' saa7134-input.c:(.text+0x11c7ad): undefined reference to `ir_input_keydown' saa7134-input.c:(.text+0x11c7f0): undefined reference to `ir_input_keydown' saa7134-input.c:(.text+0x11c7f9): undefined reference to `ir_input_nokey' saa7134-input.c:(.text+0x11c806): undefined reference to `ir_input_nokey' drivers/built-in.o: In function `saa7134_input_init1': (.text+0x11ca07): undefined reference to `ir_codes_encore_enltv' drivers/built-in.o: In function `saa7134_input_init1': (.text+0x11caf6): undefined reference to `ir_input_init' drivers/built-in.o: In function `saa7134_input_init1': (.text+0x11cbf2): undefined reference to `ir_codes_avermedia' drivers/built-in.o: In function `saa7134_input_init1': (.text+0x11cc24): undefined reference to `ir_codes_pctv_sedna' drivers/built-in.o: In function `saa7134_input_init1': (.text+0x11cc53): undefined reference to `ir_codes_flydvb' drivers/built-in.o: In function `saa7134_input_init1': (.text+0x11cc85): undefined reference to `ir_codes_videomate_tv_pvr' drivers/built-in.o: In function `saa7134_input_init1': (.text+0x11ccb7): undefined reference to `ir_codes_pixelview' drivers/built-in.o: In function `saa7134_input_init1': (.text+0x11cce9): undefined reference to `ir_codes_eztv' drivers/built-in.o: In function `saa7134_input_init1': (.text+0x11cd1b): undefined reference to `ir_codes_manli' drivers/built-in.o: In function `saa7134_input_init1': (.text+0x11cda8): undefined reference to `ir_codes_cinergy' drivers/built-in.o: In function `saa7134_input_init1': (.text+0x11cdd7): undefined reference to `ir_codes_flyvideo' drivers/built-in.o: In function `saa7134_input_init1': (.text+0x11ce06): undefined reference to `ir_codes_asus_pc39' drivers/built-in.o: In function `saa7134_input_init1': (.text+0x11ce7d): undefined reference to `ir_codes_gotview7135' drivers/built-in.o: In function `saa7134_input_init1': (.text+0x11cee1): undefined reference to `ir_codes_proteus_2309' Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/ttpci/Kconfig | 2 +- linux/drivers/media/video/cx23885/Kconfig | 2 +- linux/drivers/media/video/cx88/Kconfig | 2 +- linux/drivers/media/video/em28xx/Kconfig | 2 +- linux/drivers/media/video/saa7134/Kconfig | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/ttpci/Kconfig b/linux/drivers/media/dvb/ttpci/Kconfig index 6d53289b3..54b91f26c 100644 --- a/linux/drivers/media/dvb/ttpci/Kconfig +++ b/linux/drivers/media/dvb/ttpci/Kconfig @@ -84,7 +84,7 @@ config DVB_BUDGET config DVB_BUDGET_CI tristate "Budget cards with onboard CI connector" - depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 + depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 && INPUT select VIDEO_SAA7146 select DVB_STV0297 if !DVB_FE_CUSTOMISE select DVB_STV0299 if !DVB_FE_CUSTOMISE diff --git a/linux/drivers/media/video/cx23885/Kconfig b/linux/drivers/media/video/cx23885/Kconfig index 72004a07b..d8b1ccb44 100644 --- a/linux/drivers/media/video/cx23885/Kconfig +++ b/linux/drivers/media/video/cx23885/Kconfig @@ -1,6 +1,6 @@ config VIDEO_CX23885 tristate "Conexant cx23885 (2388x successor) support" - depends on DVB_CORE && VIDEO_DEV && PCI && I2C + depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT select I2C_ALGOBIT select FW_LOADER select VIDEO_BTCX diff --git a/linux/drivers/media/video/cx88/Kconfig b/linux/drivers/media/video/cx88/Kconfig index eeb5224ca..ceb31d4a2 100644 --- a/linux/drivers/media/video/cx88/Kconfig +++ b/linux/drivers/media/video/cx88/Kconfig @@ -1,6 +1,6 @@ config VIDEO_CX88 tristate "Conexant 2388x (bt878 successor) support" - depends on VIDEO_DEV && PCI && I2C + depends on VIDEO_DEV && PCI && I2C && INPUT select I2C_ALGOBIT select FW_LOADER select VIDEO_BTCX diff --git a/linux/drivers/media/video/em28xx/Kconfig b/linux/drivers/media/video/em28xx/Kconfig index 5b6a40371..c1127802a 100644 --- a/linux/drivers/media/video/em28xx/Kconfig +++ b/linux/drivers/media/video/em28xx/Kconfig @@ -1,6 +1,6 @@ config VIDEO_EM28XX tristate "Empia EM2800/2820/2840 USB video capture support" - depends on VIDEO_V4L1 && I2C + depends on VIDEO_V4L1 && I2C && INPUT select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_IR diff --git a/linux/drivers/media/video/saa7134/Kconfig b/linux/drivers/media/video/saa7134/Kconfig index d6d8d6601..3aa8cb2b8 100644 --- a/linux/drivers/media/video/saa7134/Kconfig +++ b/linux/drivers/media/video/saa7134/Kconfig @@ -1,6 +1,6 @@ config VIDEO_SAA7134 tristate "Philips SAA7134 support" - depends on VIDEO_DEV && PCI && I2C + depends on VIDEO_DEV && PCI && I2C && INPUT select VIDEOBUF_DMA_SG select VIDEO_IR select VIDEO_TUNER -- cgit v1.2.3 From db7fcfc5c5821ff5568dd32c567e0c42488c503f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Oct 2007 11:19:45 -0700 Subject: bttv: uses input functions, should depend on INPUT From: Randy Dunlap Several media drivers use input_(*) functions so they need to depend on the INPUT config symbol. drivers/built-in.o: In function `bttv_input_fini': linux-2.6.24-rc1-git4/drivers/media/video/bt8xx/bttv-input.c:346: undefined reference to `input_unregister_device' drivers/built-in.o: In function `bttv_input_init': linux-2.6.24-rc1-git4/drivers/media/video/bt8xx/bttv-input.c:204: undefined reference to `input_allocate_device' linux-2.6.24-rc1-git4/drivers/media/video/bt8xx/bttv-input.c:335: undefined reference to `input_free_device' linux-2.6.24-rc1-git4/drivers/media/video/bt8xx/bttv-input.c:321: undefined reference to `input_register_device' linux-2.6.24-rc1-git4/drivers/media/video/bt8xx/bttv-input.c:335: undefined reference to `input_free_device' Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/Kconfig b/linux/drivers/media/video/bt8xx/Kconfig index ce93312cf..cfc822bb5 100644 --- a/linux/drivers/media/video/bt8xx/Kconfig +++ b/linux/drivers/media/video/bt8xx/Kconfig @@ -1,6 +1,6 @@ config VIDEO_BT848 tristate "BT848 Video For Linux" - depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 + depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 && INPUT select I2C_ALGOBIT select FW_LOADER select VIDEO_BTCX -- cgit v1.2.3