diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-14 00:13:22 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-15 16:25:07 -0300 |
commit | 0c0d06cac63ee327ceaab4b5ffe2206574ab86bd (patch) | |
tree | e759f0dc3185d97f2a0c6b5cd5e32ea6faa74d40 /drivers/media/video/em28xx | |
parent | 84cfe9e79bd5ac11c963f4841158454fefa872f6 (diff) | |
download | op-kernel-dev-0c0d06cac63ee327ceaab4b5ffe2206574ab86bd.zip op-kernel-dev-0c0d06cac63ee327ceaab4b5ffe2206574ab86bd.tar.gz |
[media] rename most media/video usb drivers to media/usb
Rename all USB drivers with their own directory under
drivers/media/video into drivers/media/usb and update the
building system.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/em28xx')
-rw-r--r-- | drivers/media/video/em28xx/Kconfig | 58 | ||||
-rw-r--r-- | drivers/media/video/em28xx/Makefile | 15 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-audio.c | 751 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-cards.c | 3417 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-core.c | 1260 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-dvb.c | 1197 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-i2c.c | 568 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-input.c | 645 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-reg.h | 226 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-vbi.c | 145 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 2624 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx.h | 809 |
12 files changed, 0 insertions, 11715 deletions
diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig deleted file mode 100644 index 928ef0d..0000000 --- a/drivers/media/video/em28xx/Kconfig +++ /dev/null @@ -1,58 +0,0 @@ -config VIDEO_EM28XX - tristate "Empia EM28xx USB video capture support" - depends on VIDEO_DEV && I2C - select VIDEO_TUNER - select VIDEO_TVEEPROM - select VIDEOBUF_VMALLOC - select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_MT9V011 if VIDEO_HELPER_CHIPS_AUTO - - ---help--- - This is a video4linux driver for Empia 28xx based TV cards. - - To compile this driver as a module, choose M here: the - module will be called em28xx - -config VIDEO_EM28XX_ALSA - depends on VIDEO_EM28XX && SND - select SND_PCM - tristate "Empia EM28xx ALSA audio module" - ---help--- - This is an ALSA driver for some Empia 28xx based TV cards. - - This is not required for em2800/em2820/em2821 boards. However, - newer em28xx devices uses Vendor Class for audio, instead of - implementing the USB Audio Class. For those chips, this module - will enable digital audio. - - To compile this driver as a module, choose M here: the - module will be called em28xx-alsa - -config VIDEO_EM28XX_DVB - tristate "DVB/ATSC Support for em28xx based TV cards" - depends on VIDEO_EM28XX && DVB_CORE - select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select DVB_TDA10023 if !DVB_FE_CUSTOMISE - select DVB_S921 if !DVB_FE_CUSTOMISE - select DVB_DRXD if !DVB_FE_CUSTOMISE - select DVB_CXD2820R if !DVB_FE_CUSTOMISE - select DVB_DRXK if !DVB_FE_CUSTOMISE - select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE - select DVB_TDA10071 if !DVB_FE_CUSTOMISE - select DVB_A8293 if !DVB_FE_CUSTOMISE - select VIDEOBUF_DVB - ---help--- - This adds support for DVB cards based on the - Empiatech em28xx chips. - -config VIDEO_EM28XX_RC - tristate "EM28XX Remote Controller support" - depends on RC_CORE - depends on VIDEO_EM28XX - depends on !(RC_CORE=m && VIDEO_EM28XX=y) - default VIDEO_EM28XX - ---help--- - Enables Remote Controller support on em28xx driver. diff --git a/drivers/media/video/em28xx/Makefile b/drivers/media/video/em28xx/Makefile deleted file mode 100644 index 65c7c29..0000000 --- a/drivers/media/video/em28xx/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -em28xx-y := em28xx-video.o em28xx-i2c.o em28xx-cards.o -em28xx-y += em28xx-core.o em28xx-vbi.o - -em28xx-alsa-objs := em28xx-audio.o -em28xx-rc-objs := em28xx-input.o - -obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o -obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o -obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o -obj-$(CONFIG_VIDEO_EM28XX_RC) += em28xx-rc.o - -ccflags-y += -Idrivers/media/video -ccflags-y += -Idrivers/media/tuners -ccflags-y += -Idrivers/media/dvb-core -ccflags-y += -Idrivers/media/dvb-frontends diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c deleted file mode 100644 index 2fdb66e..0000000 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ /dev/null @@ -1,751 +0,0 @@ -/* - * Empiatech em28x1 audio extension - * - * Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com> - * - * Copyright (C) 2007-2011 Mauro Carvalho Chehab <mchehab@redhat.com> - * - Port to work with the in-kernel driver - * - Cleanups, fixes, alsa-controls, etc. - * - * This driver is based on my previous au600 usb pstn audio driver - * and inherits all the copyrights - * - * 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 <linux/kernel.h> -#include <linux/usb.h> -#include <linux/init.h> -#include <linux/sound.h> -#include <linux/spinlock.h> -#include <linux/soundcard.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/proc_fs.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/info.h> -#include <sound/initval.h> -#include <sound/control.h> -#include <sound/tlv.h> -#include <sound/ac97_codec.h> -#include <media/v4l2-common.h> -#include "em28xx.h" - -static int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "activates debug info"); - -#define dprintk(fmt, arg...) do { \ - if (debug) \ - printk(KERN_INFO "em28xx-audio %s: " fmt, \ - __func__, ##arg); \ - } while (0) - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; - -static int em28xx_deinit_isoc_audio(struct em28xx *dev) -{ - int i; - - dprintk("Stopping isoc\n"); - for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { - if (!irqs_disabled()) - usb_kill_urb(dev->adev.urb[i]); - else - usb_unlink_urb(dev->adev.urb[i]); - - usb_free_urb(dev->adev.urb[i]); - dev->adev.urb[i] = NULL; - - kfree(dev->adev.transfer_buffer[i]); - dev->adev.transfer_buffer[i] = NULL; - } - - return 0; -} - -static void em28xx_audio_isocirq(struct urb *urb) -{ - struct em28xx *dev = urb->context; - int i; - unsigned int oldptr; - int period_elapsed = 0; - int status; - unsigned char *cp; - unsigned int stride; - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - - switch (urb->status) { - case 0: /* success */ - case -ETIMEDOUT: /* NAK */ - break; - case -ECONNRESET: /* kill */ - case -ENOENT: - case -ESHUTDOWN: - return; - default: /* error */ - dprintk("urb completition error %d.\n", urb->status); - break; - } - - if (atomic_read(&dev->stream_started) == 0) - return; - - if (dev->adev.capture_pcm_substream) { - substream = dev->adev.capture_pcm_substream; - runtime = substream->runtime; - stride = runtime->frame_bits >> 3; - - for (i = 0; i < urb->number_of_packets; i++) { - int length = - urb->iso_frame_desc[i].actual_length / stride; - cp = (unsigned char *)urb->transfer_buffer + - urb->iso_frame_desc[i].offset; - - if (!length) - continue; - - oldptr = dev->adev.hwptr_done_capture; - if (oldptr + length >= runtime->buffer_size) { - unsigned int cnt = - runtime->buffer_size - oldptr; - memcpy(runtime->dma_area + oldptr * stride, cp, - cnt * stride); - memcpy(runtime->dma_area, cp + cnt * stride, - length * stride - cnt * stride); - } else { - memcpy(runtime->dma_area + oldptr * stride, cp, - length * stride); - } - - snd_pcm_stream_lock(substream); - - dev->adev.hwptr_done_capture += length; - if (dev->adev.hwptr_done_capture >= - runtime->buffer_size) - dev->adev.hwptr_done_capture -= - runtime->buffer_size; - - dev->adev.capture_transfer_done += length; - if (dev->adev.capture_transfer_done >= - runtime->period_size) { - dev->adev.capture_transfer_done -= - runtime->period_size; - period_elapsed = 1; - } - - snd_pcm_stream_unlock(substream); - } - if (period_elapsed) - snd_pcm_period_elapsed(substream); - } - urb->status = 0; - - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status < 0) { - em28xx_errdev("resubmit of audio urb failed (error=%i)\n", - status); - } - return; -} - -static int em28xx_init_audio_isoc(struct em28xx *dev) -{ - int i, errCode; - const int sb_size = EM28XX_NUM_AUDIO_PACKETS * - EM28XX_AUDIO_MAX_PACKET_SIZE; - - dprintk("Starting isoc transfers\n"); - - for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { - struct urb *urb; - int j, k; - - dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC); - if (!dev->adev.transfer_buffer[i]) - return -ENOMEM; - - memset(dev->adev.transfer_buffer[i], 0x80, sb_size); - urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC); - if (!urb) { - em28xx_errdev("usb_alloc_urb failed!\n"); - for (j = 0; j < i; j++) { - usb_free_urb(dev->adev.urb[j]); - kfree(dev->adev.transfer_buffer[j]); - } - return -ENOMEM; - } - - urb->dev = dev->udev; - urb->context = dev; - urb->pipe = usb_rcvisocpipe(dev->udev, EM28XX_EP_AUDIO); - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = dev->adev.transfer_buffer[i]; - urb->interval = 1; - urb->complete = em28xx_audio_isocirq; - urb->number_of_packets = EM28XX_NUM_AUDIO_PACKETS; - urb->transfer_buffer_length = sb_size; - - for (j = k = 0; j < EM28XX_NUM_AUDIO_PACKETS; - j++, k += EM28XX_AUDIO_MAX_PACKET_SIZE) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = - EM28XX_AUDIO_MAX_PACKET_SIZE; - } - dev->adev.urb[i] = urb; - } - - for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { - errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); - if (errCode) { - em28xx_errdev("submit of audio urb failed\n"); - em28xx_deinit_isoc_audio(dev); - atomic_set(&dev->stream_started, 0); - return errCode; - } - - } - - return 0; -} - -static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, - size_t size) -{ - struct snd_pcm_runtime *runtime = subs->runtime; - - dprintk("Allocating vbuffer\n"); - if (runtime->dma_area) { - if (runtime->dma_bytes > size) - return 0; - - vfree(runtime->dma_area); - } - runtime->dma_area = vmalloc(size); - if (!runtime->dma_area) - return -ENOMEM; - - runtime->dma_bytes = size; - - return 0; -} - -static struct snd_pcm_hardware snd_em28xx_hw_capture = { - .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_MMAP_VALID, - - .formats = SNDRV_PCM_FMTBIT_S16_LE, - - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT, - - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 62720 * 8, /* just about the value in usbaudio.c */ - .period_bytes_min = 64, /* 12544/2, */ - .period_bytes_max = 12544, - .periods_min = 2, - .periods_max = 98, /* 12544, */ -}; - -static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) -{ - struct em28xx *dev = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int ret = 0; - - dprintk("opening device and trying to acquire exclusive lock\n"); - - if (!dev) { - em28xx_err("BUG: em28xx can't find device struct." - " Can't proceed with open\n"); - return -ENODEV; - } - - runtime->hw = snd_em28xx_hw_capture; - if ((dev->alt == 0 || dev->audio_ifnum) && dev->adev.users == 0) { - if (dev->audio_ifnum) - dev->alt = 1; - else - dev->alt = 7; - - dprintk("changing alternate number on interface %d to %d\n", - dev->audio_ifnum, dev->alt); - usb_set_interface(dev->udev, dev->audio_ifnum, dev->alt); - - /* Sets volume, mute, etc */ - dev->mute = 0; - mutex_lock(&dev->lock); - ret = em28xx_audio_analog_set(dev); - if (ret < 0) - goto err; - - dev->adev.users++; - mutex_unlock(&dev->lock); - } - - snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - dev->adev.capture_pcm_substream = substream; - - return 0; -err: - mutex_unlock(&dev->lock); - - em28xx_err("Error while configuring em28xx mixer\n"); - return ret; -} - -static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream) -{ - struct em28xx *dev = snd_pcm_substream_chip(substream); - - dprintk("closing device\n"); - - dev->mute = 1; - mutex_lock(&dev->lock); - dev->adev.users--; - if (atomic_read(&dev->stream_started) > 0) { - atomic_set(&dev->stream_started, 0); - schedule_work(&dev->wq_trigger); - } - - em28xx_audio_analog_set(dev); - if (substream->runtime->dma_area) { - dprintk("freeing\n"); - vfree(substream->runtime->dma_area); - substream->runtime->dma_area = NULL; - } - mutex_unlock(&dev->lock); - - return 0; -} - -static int snd_em28xx_hw_capture_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - int ret; - - dprintk("Setting capture parameters\n"); - - ret = snd_pcm_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); - if (ret < 0) - return ret; -#if 0 - /* TODO: set up em28xx audio chip to deliver the correct audio format, - current default is 48000hz multiplexed => 96000hz mono - which shouldn't matter since analogue TV only supports mono */ - unsigned int channels, rate, format; - - format = params_format(hw_params); - rate = params_rate(hw_params); - channels = params_channels(hw_params); -#endif - - return 0; -} - -static int snd_em28xx_hw_capture_free(struct snd_pcm_substream *substream) -{ - struct em28xx *dev = snd_pcm_substream_chip(substream); - - dprintk("Stop capture, if needed\n"); - - if (atomic_read(&dev->stream_started) > 0) { - atomic_set(&dev->stream_started, 0); - schedule_work(&dev->wq_trigger); - } - - return 0; -} - -static int snd_em28xx_prepare(struct snd_pcm_substream *substream) -{ - struct em28xx *dev = snd_pcm_substream_chip(substream); - - dev->adev.hwptr_done_capture = 0; - dev->adev.capture_transfer_done = 0; - - return 0; -} - -static void audio_trigger(struct work_struct *work) -{ - struct em28xx *dev = container_of(work, struct em28xx, wq_trigger); - - if (atomic_read(&dev->stream_started)) { - dprintk("starting capture"); - em28xx_init_audio_isoc(dev); - } else { - dprintk("stopping capture"); - em28xx_deinit_isoc_audio(dev); - } -} - -static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct em28xx *dev = snd_pcm_substream_chip(substream); - int retval = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ - case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ - case SNDRV_PCM_TRIGGER_START: - atomic_set(&dev->stream_started, 1); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ - case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ - case SNDRV_PCM_TRIGGER_STOP: - atomic_set(&dev->stream_started, 0); - break; - default: - retval = -EINVAL; - } - schedule_work(&dev->wq_trigger); - return retval; -} - -static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream - *substream) -{ - unsigned long flags; - struct em28xx *dev; - snd_pcm_uframes_t hwptr_done; - - dev = snd_pcm_substream_chip(substream); - spin_lock_irqsave(&dev->adev.slock, flags); - hwptr_done = dev->adev.hwptr_done_capture; - spin_unlock_irqrestore(&dev->adev.slock, flags); - - return hwptr_done; -} - -static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, - unsigned long offset) -{ - void *pageptr = subs->runtime->dma_area + offset; - - return vmalloc_to_page(pageptr); -} - -/* - * AC97 volume control support - */ -static int em28xx_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 2; - info->value.integer.min = 0; - info->value.integer.max = 0x1f; - - return 0; -} - -static int em28xx_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - struct em28xx *dev = snd_kcontrol_chip(kcontrol); - u16 val = (0x1f - (value->value.integer.value[0] & 0x1f)) | - (0x1f - (value->value.integer.value[1] & 0x1f)) << 8; - int rc; - - mutex_lock(&dev->lock); - rc = em28xx_read_ac97(dev, kcontrol->private_value); - if (rc < 0) - goto err; - - val |= rc & 0x8000; /* Preserve the mute flag */ - - rc = em28xx_write_ac97(dev, kcontrol->private_value, val); - if (rc < 0) - goto err; - - dprintk("%sleft vol %d, right vol %d (0x%04x) to ac97 volume control 0x%04x\n", - (val & 0x8000) ? "muted " : "", - 0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f), - val, (int)kcontrol->private_value); - -err: - mutex_unlock(&dev->lock); - return rc; -} - -static int em28xx_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - struct em28xx *dev = snd_kcontrol_chip(kcontrol); - int val; - - mutex_lock(&dev->lock); - val = em28xx_read_ac97(dev, kcontrol->private_value); - mutex_unlock(&dev->lock); - if (val < 0) - return val; - - dprintk("%sleft vol %d, right vol %d (0x%04x) from ac97 volume control 0x%04x\n", - (val & 0x8000) ? "muted " : "", - 0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f), - val, (int)kcontrol->private_value); - - value->value.integer.value[0] = 0x1f - (val & 0x1f); - value->value.integer.value[1] = 0x1f - ((val << 8) & 0x1f); - - return 0; -} - -static int em28xx_vol_put_mute(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - struct em28xx *dev = snd_kcontrol_chip(kcontrol); - u16 val = value->value.integer.value[0]; - int rc; - - mutex_lock(&dev->lock); - rc = em28xx_read_ac97(dev, kcontrol->private_value); - if (rc < 0) - goto err; - - if (val) - rc &= 0x1f1f; - else - rc |= 0x8000; - - rc = em28xx_write_ac97(dev, kcontrol->private_value, rc); - if (rc < 0) - goto err; - - dprintk("%sleft vol %d, right vol %d (0x%04x) to ac97 volume control 0x%04x\n", - (val & 0x8000) ? "muted " : "", - 0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f), - val, (int)kcontrol->private_value); - -err: - mutex_unlock(&dev->lock); - return rc; -} - -static int em28xx_vol_get_mute(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - struct em28xx *dev = snd_kcontrol_chip(kcontrol); - int val; - - mutex_lock(&dev->lock); - val = em28xx_read_ac97(dev, kcontrol->private_value); - mutex_unlock(&dev->lock); - if (val < 0) - return val; - - if (val & 0x8000) - value->value.integer.value[0] = 0; - else - value->value.integer.value[0] = 1; - - dprintk("%sleft vol %d, right vol %d (0x%04x) from ac97 volume control 0x%04x\n", - (val & 0x8000) ? "muted " : "", - 0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f), - val, (int)kcontrol->private_value); - - return 0; -} - -static const DECLARE_TLV_DB_SCALE(em28xx_db_scale, -3450, 150, 0); - -static int em28xx_cvol_new(struct snd_card *card, struct em28xx *dev, - char *name, int id) -{ - int err; - char ctl_name[44]; - struct snd_kcontrol *kctl; - struct snd_kcontrol_new tmp; - - memset (&tmp, 0, sizeof(tmp)); - tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER, - tmp.private_value = id, - tmp.name = ctl_name, - - /* Add Mute Control */ - sprintf(ctl_name, "%s Switch", name); - tmp.get = em28xx_vol_get_mute; - tmp.put = em28xx_vol_put_mute; - tmp.info = snd_ctl_boolean_mono_info; - kctl = snd_ctl_new1(&tmp, dev); - err = snd_ctl_add(card, kctl); - if (err < 0) - return err; - dprintk("Added control %s for ac97 volume control 0x%04x\n", - ctl_name, id); - - memset (&tmp, 0, sizeof(tmp)); - tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER, - tmp.private_value = id, - tmp.name = ctl_name, - - /* Add Volume Control */ - sprintf(ctl_name, "%s Volume", name); - tmp.get = em28xx_vol_get; - tmp.put = em28xx_vol_put; - tmp.info = em28xx_vol_info; - tmp.tlv.p = em28xx_db_scale, - kctl = snd_ctl_new1(&tmp, dev); - err = snd_ctl_add(card, kctl); - if (err < 0) - return err; - dprintk("Added control %s for ac97 volume control 0x%04x\n", - ctl_name, id); - - return 0; -} - -/* - * register/unregister code and data - */ -static struct snd_pcm_ops snd_em28xx_pcm_capture = { - .open = snd_em28xx_capture_open, - .close = snd_em28xx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_em28xx_hw_capture_params, - .hw_free = snd_em28xx_hw_capture_free, - .prepare = snd_em28xx_prepare, - .trigger = snd_em28xx_capture_trigger, - .pointer = snd_em28xx_capture_pointer, - .page = snd_pcm_get_vmalloc_page, -}; - -static int em28xx_audio_init(struct em28xx *dev) -{ - struct em28xx_audio *adev = &dev->adev; - struct snd_pcm *pcm; - struct snd_card *card; - static int devnr; - int err; - - if (!dev->has_alsa_audio || dev->audio_ifnum < 0) { - /* This device does not support the extension (in this case - the device is expecting the snd-usb-audio module or - doesn't have analog audio support at all) */ - return 0; - } - - printk(KERN_INFO "em28xx-audio.c: probing for em28xx Audio Vendor Class\n"); - printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " - "Rechberger\n"); - printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2007-2011 Mauro Carvalho Chehab\n"); - - err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0, - &card); - if (err < 0) - return err; - - spin_lock_init(&adev->slock); - err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm); - if (err < 0) { - snd_card_free(card); - return err; - } - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_em28xx_pcm_capture); - pcm->info_flags = 0; - pcm->private_data = dev; - strcpy(pcm->name, "Empia 28xx Capture"); - - snd_card_set_dev(card, &dev->udev->dev); - strcpy(card->driver, "Em28xx-Audio"); - strcpy(card->shortname, "Em28xx Audio"); - strcpy(card->longname, "Empia Em28xx Audio"); - - INIT_WORK(&dev->wq_trigger, audio_trigger); - - if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { - em28xx_cvol_new(card, dev, "Video", AC97_VIDEO); - em28xx_cvol_new(card, dev, "Line In", AC97_LINE); - em28xx_cvol_new(card, dev, "Phone", AC97_PHONE); - em28xx_cvol_new(card, dev, "Microphone", AC97_MIC); - em28xx_cvol_new(card, dev, "CD", AC97_CD); - em28xx_cvol_new(card, dev, "AUX", AC97_AUX); - em28xx_cvol_new(card, dev, "PCM", AC97_PCM); - - em28xx_cvol_new(card, dev, "Master", AC97_MASTER); - em28xx_cvol_new(card, dev, "Line", AC97_HEADPHONE); - em28xx_cvol_new(card, dev, "Mono", AC97_MASTER_MONO); - em28xx_cvol_new(card, dev, "LFE", AC97_CENTER_LFE_MASTER); - em28xx_cvol_new(card, dev, "Surround", AC97_SURROUND_MASTER); - } - - err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } - adev->sndcard = card; - adev->udev = dev->udev; - - return 0; -} - -static int em28xx_audio_fini(struct em28xx *dev) -{ - if (dev == NULL) - return 0; - - if (dev->has_alsa_audio != 1) { - /* This device does not support the extension (in this case - the device is expecting the snd-usb-audio module or - doesn't have analog audio support at all) */ - return 0; - } - - if (dev->adev.sndcard) { - snd_card_free(dev->adev.sndcard); - dev->adev.sndcard = NULL; - } - - return 0; -} - -static struct em28xx_ops audio_ops = { - .id = EM28XX_AUDIO, - .name = "Em28xx Audio Extension", - .init = em28xx_audio_init, - .fini = em28xx_audio_fini, -}; - -static int __init em28xx_alsa_register(void) -{ - return em28xx_register_extension(&audio_ops); -} - -static void __exit em28xx_alsa_unregister(void) -{ - em28xx_unregister_extension(&audio_ops); -} - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Markus Rechberger <mrechberger@gmail.com>"); -MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); -MODULE_DESCRIPTION("Em28xx Audio driver"); - -module_init(em28xx_alsa_register); -module_exit(em28xx_alsa_unregister); diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c deleted file mode 100644 index ca62b99..0000000 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ /dev/null @@ -1,3417 +0,0 @@ -/* - em28xx-cards.c - driver for Empia EM2800/EM2820/2840 USB - video capture devices - - Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> - Markus Rechberger <mrechberger@gmail.com> - Mauro Carvalho Chehab <mchehab@infradead.org> - Sascha Sommer <saschasommer@freenet.de> - - 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 <linux/init.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/usb.h> -#include <media/tuner.h> -#include <media/msp3400.h> -#include <media/saa7115.h> -#include <media/tvp5150.h> -#include <media/tvaudio.h> -#include <media/mt9v011.h> -#include <media/i2c-addr.h> -#include <media/tveeprom.h> -#include <media/v4l2-common.h> -#include <media/v4l2-chip-ident.h> - -#include "em28xx.h" - -#define DRIVER_NAME "em28xx" - -static int tuner = -1; -module_param(tuner, int, 0444); -MODULE_PARM_DESC(tuner, "tuner type"); - -static unsigned int disable_ir; -module_param(disable_ir, int, 0444); -MODULE_PARM_DESC(disable_ir, "disable infrared remote support"); - -static unsigned int disable_usb_speed_check; -module_param(disable_usb_speed_check, int, 0444); -MODULE_PARM_DESC(disable_usb_speed_check, - "override min bandwidth requirement of 480M bps"); - -static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; -module_param_array(card, int, NULL, 0444); -MODULE_PARM_DESC(card, "card type"); - -/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS - 1 */ -static unsigned long em28xx_devused; - -struct em28xx_hash_table { - unsigned long hash; - unsigned int model; - unsigned int tuner; -}; - -static void em28xx_pre_card_setup(struct em28xx *dev); - -/* - * Reset sequences for analog/digital modes - */ - -/* Reset for the most [analog] boards */ -static struct em28xx_reg_seq default_analog[] = { - {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, - { -1, -1, -1, -1}, -}; - -/* Reset for the most [digital] boards */ -static struct em28xx_reg_seq default_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, - { -1, -1, -1, -1}, -}; - -/* Board Hauppauge WinTV HVR 900 analog */ -static struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = { - {EM28XX_R08_GPIO, 0x2d, ~EM_GPIO_4, 10}, - {0x05, 0xff, 0x10, 10}, - { -1, -1, -1, -1}, -}; - -/* Board Hauppauge WinTV HVR 900 digital */ -static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { - {EM28XX_R08_GPIO, 0x2e, ~EM_GPIO_4, 10}, - {EM2880_R04_GPO, 0x04, 0x0f, 10}, - {EM2880_R04_GPO, 0x0c, 0x0f, 10}, - { -1, -1, -1, -1}, -}; - -/* Board Hauppauge WinTV HVR 900 (R2) digital */ -static struct em28xx_reg_seq hauppauge_wintv_hvr_900R2_digital[] = { - {EM28XX_R08_GPIO, 0x2e, ~EM_GPIO_4, 10}, - {EM2880_R04_GPO, 0x0c, 0x0f, 10}, - { -1, -1, -1, -1}, -}; - -/* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */ -static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = { - {EM28XX_R08_GPIO, 0x69, ~EM_GPIO_4, 10}, - { -1, -1, -1, -1}, -}; - -/* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */ - -/* Board - EM2870 Kworld 355u - Analog - No input analog */ - -/* Board - EM2882 Kworld 315U digital */ -static struct em28xx_reg_seq em2882_kworld_315u_digital[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM28XX_R08_GPIO, 0xfe, 0xff, 10}, - {EM2880_R04_GPO, 0x04, 0xff, 10}, - {EM2880_R04_GPO, 0x0c, 0xff, 10}, - {EM28XX_R08_GPIO, 0x7e, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq em2882_kworld_315u_tuner_gpio[] = { - {EM2880_R04_GPO, 0x08, 0xff, 10}, - {EM2880_R04_GPO, 0x0c, 0xff, 10}, - {EM2880_R04_GPO, 0x08, 0xff, 10}, - {EM2880_R04_GPO, 0x0c, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq kworld_330u_analog[] = { - {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, - {EM2880_R04_GPO, 0x00, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq kworld_330u_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, - {EM2880_R04_GPO, 0x08, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -/* Evga inDtube - GPIO0 - Enable digital power (s5h1409) - low to enable - GPIO1 - Enable analog power (tvp5150/emp202) - low to enable - GPIO4 - xc3028 reset - GOP3 - s5h1409 reset - */ -static struct em28xx_reg_seq evga_indtube_analog[] = { - {EM28XX_R08_GPIO, 0x79, 0xff, 60}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq evga_indtube_digital[] = { - {EM28XX_R08_GPIO, 0x7a, 0xff, 1}, - {EM2880_R04_GPO, 0x04, 0xff, 10}, - {EM2880_R04_GPO, 0x0c, 0xff, 1}, - { -1, -1, -1, -1}, -}; - -/* - * KWorld PlusTV 340U and UB435-Q (ATSC) GPIOs map: - * EM_GPIO_0 - currently unknown - * EM_GPIO_1 - LED disable/enable (1 = off, 0 = on) - * EM_GPIO_2 - currently unknown - * EM_GPIO_3 - currently unknown - * EM_GPIO_4 - TDA18271HD/C1 tuner (1 = active, 0 = in reset) - * EM_GPIO_5 - LGDT3304 ATSC/QAM demod (1 = active, 0 = in reset) - * EM_GPIO_6 - currently unknown - * EM_GPIO_7 - currently unknown - */ -static struct em28xx_reg_seq kworld_a340_digital[] = { - {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, - { -1, -1, -1, -1}, -}; - -/* Pinnacle Hybrid Pro eb1a:2881 */ -static struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = { - {EM28XX_R08_GPIO, 0xfd, ~EM_GPIO_4, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq pinnacle_hybrid_pro_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, - {EM2880_R04_GPO, 0x04, 0xff, 100},/* zl10353 reset */ - {EM2880_R04_GPO, 0x0c, 0xff, 1}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_analog[] = { - {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, - {EM2880_R04_GPO, 0x00, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, - {EM2880_R04_GPO, 0x08, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -/* eb1a:2868 Reddo DVB-C USB TV Box - GPIO4 - CU1216L NIM - Other GPIOs seems to be don't care. */ -static struct em28xx_reg_seq reddo_dvb_c_usb_box[] = { - {EM28XX_R08_GPIO, 0xfe, 0xff, 10}, - {EM28XX_R08_GPIO, 0xde, 0xff, 10}, - {EM28XX_R08_GPIO, 0xfe, 0xff, 10}, - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM28XX_R08_GPIO, 0x7f, 0xff, 10}, - {EM28XX_R08_GPIO, 0x6f, 0xff, 10}, - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {-1, -1, -1, -1}, -}; - -/* Callback for the most boards */ -static struct em28xx_reg_seq default_tuner_gpio[] = { - {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, - {EM28XX_R08_GPIO, 0, EM_GPIO_4, 10}, - {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, - { -1, -1, -1, -1}, -}; - -/* Mute/unmute */ -static struct em28xx_reg_seq compro_unmute_tv_gpio[] = { - {EM28XX_R08_GPIO, 5, 7, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq compro_unmute_svid_gpio[] = { - {EM28XX_R08_GPIO, 4, 7, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq compro_mute_gpio[] = { - {EM28XX_R08_GPIO, 6, 7, 10}, - { -1, -1, -1, -1}, -}; - -/* Terratec AV350 */ -static struct em28xx_reg_seq terratec_av350_mute_gpio[] = { - {EM28XX_R08_GPIO, 0xff, 0x7f, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq silvercrest_reg_seq[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM28XX_R08_GPIO, 0x01, 0xf7, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq vc211a_enable[] = { - {EM28XX_R08_GPIO, 0xff, 0x07, 10}, - {EM28XX_R08_GPIO, 0xff, 0x0f, 10}, - {EM28XX_R08_GPIO, 0xff, 0x0b, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq dikom_dk300_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, - {EM2880_R04_GPO, 0x08, 0xff, 10}, - { -1, -1, -1, -1}, -}; - - -/* Reset for the most [digital] boards */ -static struct em28xx_reg_seq leadership_digital[] = { - {EM2874_R80_GPIO, 0x70, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq leadership_reset[] = { - {EM2874_R80_GPIO, 0xf0, 0xff, 10}, - {EM2874_R80_GPIO, 0xb0, 0xff, 10}, - {EM2874_R80_GPIO, 0xf0, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -/* 2013:024f PCTV nanoStick T2 290e - * GPIO_6 - demod reset - * GPIO_7 - LED - */ -static struct em28xx_reg_seq pctv_290e[] = { - {EM2874_R80_GPIO, 0x00, 0xff, 80}, - {EM2874_R80_GPIO, 0x40, 0xff, 80}, /* GPIO_6 = 1 */ - {EM2874_R80_GPIO, 0xc0, 0xff, 80}, /* GPIO_7 = 1 */ - {-1, -1, -1, -1}, -}; - -#if 0 -static struct em28xx_reg_seq terratec_h5_gpio[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, - {EM2874_R80_GPIO, 0xf2, 0xff, 50}, - {EM2874_R80_GPIO, 0xf6, 0xff, 50}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq terratec_h5_digital[] = { - {EM2874_R80_GPIO, 0xf6, 0xff, 10}, - {EM2874_R80_GPIO, 0xe6, 0xff, 100}, - {EM2874_R80_GPIO, 0xa6, 0xff, 10}, - { -1, -1, -1, -1}, -}; -#endif - -/* 2013:024f PCTV DVB-S2 Stick 460e - * GPIO_0 - POWER_ON - * GPIO_1 - BOOST - * GPIO_2 - VUV_LNB (red LED) - * GPIO_3 - EXT_12V - * GPIO_4 - INT_DEM (DEMOD GPIO_0) - * GPIO_5 - INT_LNB - * GPIO_6 - RESET_DEM - * GPIO_7 - LED (green LED) - */ -static struct em28xx_reg_seq pctv_460e[] = { - {EM2874_R80_GPIO, 0x01, 0xff, 50}, - {0x0d, 0xff, 0xff, 50}, - {EM2874_R80_GPIO, 0x41, 0xff, 50}, /* GPIO_6=1 */ - {0x0d, 0x42, 0xff, 50}, - {EM2874_R80_GPIO, 0x61, 0xff, 50}, /* GPIO_5=1 */ - { -1, -1, -1, -1}, -}; - -#if 0 -static struct em28xx_reg_seq hauppauge_930c_gpio[] = { - {EM2874_R80_GPIO, 0x6f, 0xff, 10}, - {EM2874_R80_GPIO, 0x4f, 0xff, 10}, /* xc5000 reset */ - {EM2874_R80_GPIO, 0x6f, 0xff, 10}, - {EM2874_R80_GPIO, 0x4f, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq hauppauge_930c_digital[] = { - {EM2874_R80_GPIO, 0xf6, 0xff, 10}, - {EM2874_R80_GPIO, 0xe6, 0xff, 100}, - {EM2874_R80_GPIO, 0xa6, 0xff, 10}, - { -1, -1, -1, -1}, -}; -#endif - -/* 1b80:e425 MaxMedia UB425-TC - * GPIO_6 - demod reset, 0=active - * GPIO_7 - LED, 0=active - */ -static struct em28xx_reg_seq maxmedia_ub425_tc[] = { - {EM2874_R80_GPIO, 0x83, 0xff, 100}, - {EM2874_R80_GPIO, 0xc3, 0xff, 100}, /* GPIO_6 = 1 */ - {EM2874_R80_GPIO, 0x43, 0xff, 000}, /* GPIO_7 = 0 */ - {-1, -1, -1, -1}, -}; - -/* 2304:0242 PCTV QuatroStick (510e) - * GPIO_2: decoder reset, 0=active - * GPIO_4: decoder suspend, 0=active - * GPIO_6: demod reset, 0=active - * GPIO_7: LED, 1=active - */ -static struct em28xx_reg_seq pctv_510e[] = { - {EM2874_R80_GPIO, 0x10, 0xff, 100}, - {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ - {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ - { -1, -1, -1, -1}, -}; - -/* 2013:0251 PCTV QuatroStick nano (520e) - * GPIO_2: decoder reset, 0=active - * GPIO_4: decoder suspend, 0=active - * GPIO_6: demod reset, 0=active - * GPIO_7: LED, 1=active - */ -static struct em28xx_reg_seq pctv_520e[] = { - {EM2874_R80_GPIO, 0x10, 0xff, 100}, - {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ - {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ - {EM2874_R80_GPIO, 0xd4, 0xff, 000}, /* GPIO_7 = 1 */ - { -1, -1, -1, -1}, -}; - -/* - * Board definitions - */ -struct em28xx_board em28xx_boards[] = { - [EM2750_BOARD_UNKNOWN] = { - .name = "EM2710/EM2750/EM2751 webcam grabber", - .xclk = EM28XX_XCLK_FREQUENCY_20MHZ, - .tuner_type = TUNER_ABSENT, - .is_webcam = 1, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = silvercrest_reg_seq, - } }, - }, - [EM2800_BOARD_UNKNOWN] = { - .name = "Unknown EM2800 video grabber", - .is_em2800 = 1, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .tuner_type = TUNER_ABSENT, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_UNKNOWN] = { - .name = "Unknown EM2750/28xx video grabber", - .tuner_type = TUNER_ABSENT, - .is_webcam = 1, /* To enable sensor probe */ - }, - [EM2750_BOARD_DLCW_130] = { - /* Beijing Huaqi Information Digital Technology Co., Ltd */ - .name = "Huaqi DLCW-130", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, - .tuner_type = TUNER_ABSENT, - .is_webcam = 1, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, - .amux = EM28XX_AMUX_VIDEO, - } }, - }, - [EM2820_BOARD_KWORLD_PVRTV2800RF] = { - .name = "Kworld PVR TV 2800 RF", - .tuner_type = TUNER_TEMIC_PAL, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_GADMEI_TVR200] = { - .name = "Gadmei TVR200", - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_TERRATEC_CINERGY_250] = { - .name = "Terratec Cinergy 250 USB", - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .has_ir_i2c = 1, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_PINNACLE_USB_2] = { - .name = "Pinnacle PCTV USB 2", - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .has_ir_i2c = 1, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_HAUPPAUGE_WINTV_USB_2] = { - .name = "Hauppauge WinTV USB 2", - .tuner_type = TUNER_PHILIPS_FM1236_MK3, - .tda9887_conf = TDA9887_PRESENT | - TDA9887_PORT1_ACTIVE | - TDA9887_PORT2_ACTIVE, - .decoder = EM28XX_TVP5150, - .has_msp34xx = 1, - .has_ir_i2c = 1, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = MSP_INPUT_DEFAULT, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, - MSP_DSP_IN_SCART, MSP_DSP_IN_SCART), - } }, - }, - [EM2820_BOARD_DLINK_USB_TV] = { - .name = "D-Link DUB-T210 TV Tuner", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_HERCULES_SMART_TV_USB2] = { - .name = "Hercules Smart TV USB 2.0", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_PINNACLE_USB_2_FM1216ME] = { - .name = "Pinnacle PCTV USB 2 (Philips FM1216ME)", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_GADMEI_UTV310] = { - .name = "Gadmei UTV310", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_TNF_5335MF, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE] = { - .name = "Leadtek Winfast USB II Deluxe", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .has_ir_i2c = 1, - .tvaudio_addr = 0x58, - .tda9887_conf = TDA9887_PRESENT | - TDA9887_PORT2_ACTIVE | - TDA9887_QSS, - .decoder = EM28XX_SAA711X, - .adecoder = EM28XX_TVAUDIO, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE4, - .amux = EM28XX_AMUX_AUX, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE5, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - .radio = { - .type = EM28XX_RADIO, - .amux = EM28XX_AMUX_AUX, - } - }, - [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = { - .name = "Videology 20K14XUSB USB2.0", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_ABSENT, - .is_webcam = 1, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, - .amux = EM28XX_AMUX_VIDEO, - } }, - }, - [EM2820_BOARD_SILVERCREST_WEBCAM] = { - .name = "Silvercrest Webcam 1.3mpix", - .tuner_type = TUNER_ABSENT, - .is_webcam = 1, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = silvercrest_reg_seq, - } }, - }, - [EM2821_BOARD_SUPERCOMP_USB_2] = { - .name = "Supercomp USB 2.0 TV", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_PHILIPS_FM1236_MK3, - .tda9887_conf = TDA9887_PRESENT | - TDA9887_PORT1_ACTIVE | - TDA9887_PORT2_ACTIVE, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2821_BOARD_USBGEAR_VD204] = { - .name = "Usbgear VD204v9", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_ABSENT, /* Capture only device */ - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2860_BOARD_NETGMBH_CAM] = { - /* Beijing Huaqi Information Digital Technology Co., Ltd */ - .name = "NetGMBH Cam", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_ABSENT, - .is_webcam = 1, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, - .amux = EM28XX_AMUX_VIDEO, - } }, - }, - [EM2860_BOARD_TYPHOON_DVD_MAKER] = { - .name = "Typhoon DVD Maker", - .decoder = EM28XX_SAA711X, - .tuner_type = TUNER_ABSENT, /* Capture only device */ - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2860_BOARD_GADMEI_UTV330] = { - .name = "Gadmei UTV330", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_TNF_5335MF, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2861_BOARD_GADMEI_UTV330PLUS] = { - .name = "Gadmei UTV330+", - .tuner_type = TUNER_TNF_5335MF, - .tda9887_conf = TDA9887_PRESENT, - .ir_codes = RC_MAP_GADMEI_RM008Z, - .decoder = EM28XX_SAA711X, - .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2860_BOARD_TERRATEC_HYBRID_XS] = { - .name = "Terratec Cinergy A Hybrid XS", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2861_BOARD_KWORLD_PVRTV_300U] = { - .name = "KWorld PVRTV 300U", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2861_BOARD_YAKUMO_MOVIE_MIXER] = { - .name = "Yakumo MovieMixer", - .tuner_type = TUNER_ABSENT, /* Capture only device */ - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2860_BOARD_TVP5150_REFERENCE_DESIGN] = { - .name = "EM2860/TVP5150 Reference Design", - .tuner_type = TUNER_ABSENT, /* Capture only device */ - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2861_BOARD_PLEXTOR_PX_TV100U] = { - .name = "Plextor ConvertX PX-TV100U", - .tuner_type = TUNER_TNF_5335MF, - .xclk = EM28XX_XCLK_I2S_MSB_TIMING | - EM28XX_XCLK_FREQUENCY_12MHZ, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_TVP5150, - .has_msp34xx = 1, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = pinnacle_hybrid_pro_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = pinnacle_hybrid_pro_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = pinnacle_hybrid_pro_analog, - } }, - }, - - /* Those boards with em2870 are DVB Only*/ - - [EM2870_BOARD_TERRATEC_XS] = { - .name = "Terratec Cinergy T XS", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - }, - [EM2870_BOARD_TERRATEC_XS_MT2060] = { - .name = "Terratec Cinergy T XS (MT2060)", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_ABSENT, /* MT2060 */ - }, - [EM2870_BOARD_KWORLD_350U] = { - .name = "Kworld 350 U DVB-T", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - }, - [EM2870_BOARD_KWORLD_355U] = { - .name = "Kworld 355 U DVB-T", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_ABSENT, - .tuner_gpio = default_tuner_gpio, - .has_dvb = 1, - .dvb_gpio = default_digital, - }, - [EM2870_BOARD_PINNACLE_PCTV_DVB] = { - .name = "Pinnacle PCTV DVB-T", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_ABSENT, /* MT2060 */ - /* djh - I have serious doubts this is right... */ - .xclk = EM28XX_XCLK_IR_RC5_MODE | - EM28XX_XCLK_FREQUENCY_10MHZ, - }, - [EM2870_BOARD_COMPRO_VIDEOMATE] = { - .name = "Compro, VideoMate U3", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_ABSENT, /* MT2060 */ - }, - - [EM2880_BOARD_TERRATEC_HYBRID_XS_FR] = { - .name = "Terratec Hybrid XS Secam", - .has_msp34xx = 1, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .has_dvb = 1, - .dvb_gpio = terratec_cinergy_USB_XS_FR_digital, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = terratec_cinergy_USB_XS_FR_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = terratec_cinergy_USB_XS_FR_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = terratec_cinergy_USB_XS_FR_analog, - } }, - }, - [EM2884_BOARD_TERRATEC_H5] = { - .name = "Terratec Cinergy H5", - .has_dvb = 1, -#if 0 - .tuner_type = TUNER_PHILIPS_TDA8290, - .tuner_addr = 0x41, - .dvb_gpio = terratec_h5_digital, /* FIXME: probably wrong */ - .tuner_gpio = terratec_h5_gpio, -#else - .tuner_type = TUNER_ABSENT, -#endif - .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_400_KHZ, - }, - [EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C] = { - .name = "Hauppauge WinTV HVR 930C", - .has_dvb = 1, -#if 0 /* FIXME: Add analog support */ - .tuner_type = TUNER_XC5000, - .tuner_addr = 0x41, - .dvb_gpio = hauppauge_930c_digital, - .tuner_gpio = hauppauge_930c_gpio, -#else - .tuner_type = TUNER_ABSENT, -#endif - .ir_codes = RC_MAP_HAUPPAUGE, - .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_400_KHZ, - }, - [EM2884_BOARD_CINERGY_HTC_STICK] = { - .name = "Terratec Cinergy HTC Stick", - .has_dvb = 1, - .ir_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS, - .tuner_type = TUNER_ABSENT, - .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_400_KHZ, - }, - [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = { - .name = "Hauppauge WinTV HVR 900", - .tda9887_conf = TDA9887_PRESENT, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = RC_MAP_HAUPPAUGE, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2] = { - .name = "Hauppauge WinTV HVR 900 (R2)", - .tda9887_conf = TDA9887_PRESENT, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900R2_digital, - .ir_codes = RC_MAP_HAUPPAUGE, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850] = { - .name = "Hauppauge WinTV HVR 850", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = RC_MAP_HAUPPAUGE, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950] = { - .name = "Hauppauge WinTV HVR 950", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = RC_MAP_HAUPPAUGE, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2880_BOARD_PINNACLE_PCTV_HD_PRO] = { - .name = "Pinnacle PCTV HD Pro Stick", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = RC_MAP_PINNACLE_PCTV_HD, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600] = { - .name = "AMD ATI TV Wonder HD 600", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = RC_MAP_ATI_TV_WONDER_HD_600, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2880_BOARD_TERRATEC_HYBRID_XS] = { - .name = "Terratec Hybrid XS", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .has_dvb = 1, - .dvb_gpio = default_digital, - .ir_codes = RC_MAP_TERRATEC_CINERGY_XS, - .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = default_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, - } }, - }, - /* maybe there's a reason behind it why Terratec sells the Hybrid XS - as Prodigy XS with a different PID, let's keep it separated for now - maybe we'll need it lateron */ - [EM2880_BOARD_TERRATEC_PRODIGY_XS] = { - .name = "Terratec Prodigy XS", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2820_BOARD_MSI_VOX_USB_2] = { - .name = "MSI VOX USB 2.0", - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .tda9887_conf = TDA9887_PRESENT | - TDA9887_PORT1_ACTIVE | - TDA9887_PORT2_ACTIVE, - .max_range_640_480 = 1, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE4, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2800_BOARD_TERRATEC_CINERGY_200] = { - .name = "Terratec Cinergy 200 USB", - .is_em2800 = 1, - .has_ir_i2c = 1, - .tuner_type = TUNER_LG_TALN, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2800_BOARD_GRABBEEX_USB2800] = { - .name = "eMPIA Technology, Inc. GrabBeeX+ Video Encoder", - .is_em2800 = 1, - .decoder = EM28XX_SAA711X, - .tuner_type = TUNER_ABSENT, /* capture only board */ - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2800_BOARD_VC211A] = { - .name = "Actionmaster/LinXcel/Digitus VC211A", - .is_em2800 = 1, - .tuner_type = TUNER_ABSENT, /* Capture-only board */ - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = vc211a_enable, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = vc211a_enable, - } }, - }, - [EM2800_BOARD_LEADTEK_WINFAST_USBII] = { - .name = "Leadtek Winfast USB II", - .is_em2800 = 1, - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2800_BOARD_KWORLD_USB2800] = { - .name = "Kworld USB2800", - .is_em2800 = 1, - .tuner_type = TUNER_PHILIPS_FCV1236D, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_PINNACLE_DVC_90] = { - .name = "Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker " - "/ Kworld DVD Maker 2 / Plextor ConvertX PX-AV100U", - .tuner_type = TUNER_ABSENT, /* capture only board */ - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2800_BOARD_VGEAR_POCKETTV] = { - .name = "V-Gear PocketTV", - .is_em2800 = 1, - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2] = { - .name = "Pixelview PlayTV Box 4 USB 2.0", - .tda9887_conf = TDA9887_PRESENT, - .tuner_type = TUNER_YMEC_TVF_5533MF, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - .aout = EM28XX_AOUT_MONO | /* I2S */ - EM28XX_AOUT_MASTER, /* Line out pin */ - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_PROLINK_PLAYTV_USB2] = { - .name = "SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0", - .has_snapshot_button = 1, - .tda9887_conf = TDA9887_PRESENT, - .tuner_type = TUNER_YMEC_TVF_5533MF, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - .aout = EM28XX_AOUT_MONO | /* I2S */ - EM28XX_AOUT_MASTER, /* Line out pin */ - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2860_BOARD_SAA711X_REFERENCE_DESIGN] = { - .name = "EM2860/SAA711X Reference Design", - .has_snapshot_button = 1, - .tuner_type = TUNER_ABSENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - } }, - }, - - [EM2874_BOARD_LEADERSHIP_ISDBT] = { - .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_100_KHZ, - .xclk = EM28XX_XCLK_FREQUENCY_10MHZ, - .name = "EM2874 Leadership ISDBT", - .tuner_type = TUNER_ABSENT, - .tuner_gpio = leadership_reset, - .dvb_gpio = leadership_digital, - .has_dvb = 1, - }, - - [EM2880_BOARD_MSI_DIGIVOX_AD] = { - .name = "MSI DigiVox A/D", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = em2880_msi_digivox_ad_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = em2880_msi_digivox_ad_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = em2880_msi_digivox_ad_analog, - } }, - }, - [EM2880_BOARD_MSI_DIGIVOX_AD_II] = { - .name = "MSI DigiVox A/D II", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = em2880_msi_digivox_ad_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = em2880_msi_digivox_ad_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = em2880_msi_digivox_ad_analog, - } }, - }, - [EM2880_BOARD_KWORLD_DVB_305U] = { - .name = "KWorld DVB-T 305U", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2880_BOARD_KWORLD_DVB_310U] = { - .name = "KWorld DVB-T 310U", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .has_dvb = 1, - .dvb_gpio = default_digital, - .mts_firmware = 1, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = default_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, - }, { /* S-video has not been tested yet */ - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, - } }, - }, - [EM2882_BOARD_KWORLD_ATSC_315U] = { - .name = "KWorld ATSC 315U HDTV TV Box", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_THOMSON_DTT761X, - .tuner_gpio = em2882_kworld_315u_tuner_gpio, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .has_dvb = 1, - .dvb_gpio = em2882_kworld_315u_digital, - .ir_codes = RC_MAP_KWORLD_315U, - .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, - .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE, - /* Analog mode - still not ready */ - /*.input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - .gpio = em2882_kworld_315u_analog, - .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = em2882_kworld_315u_analog1, - .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = em2882_kworld_315u_analog1, - .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, - } }, */ - }, - [EM2880_BOARD_EMPIRE_DUAL_TV] = { - .name = "Empire dual TV", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .has_dvb = 1, - .dvb_gpio = default_digital, - .mts_firmware = 1, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = default_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, - } }, - }, - [EM2881_BOARD_DNT_DA2_HYBRID] = { - .name = "DNT DA2 Hybrid", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = default_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, - } }, - }, - [EM2881_BOARD_PINNACLE_HYBRID_PRO] = { - .name = "Pinnacle Hybrid Pro", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .has_dvb = 1, - .dvb_gpio = pinnacle_hybrid_pro_digital, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = pinnacle_hybrid_pro_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = pinnacle_hybrid_pro_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = pinnacle_hybrid_pro_analog, - } }, - }, - [EM2882_BOARD_PINNACLE_HYBRID_PRO_330E] = { - .name = "Pinnacle Hybrid Pro (330e)", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900R2_digital, - .ir_codes = RC_MAP_PINNACLE_PCTV_HD, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2882_BOARD_KWORLD_VS_DVBT] = { - .name = "Kworld VS-DVB-T 323UR", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = kworld_330u_digital, - .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ - .ir_codes = RC_MAP_KWORLD_315U, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2882_BOARD_TERRATEC_HYBRID_XS] = { - .name = "Terratec Cinnergy Hybrid T USB XS (em2882)", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .mts_firmware = 1, - .decoder = EM28XX_TVP5150, - .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = RC_MAP_TERRATEC_CINERGY_XS, - .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2882_BOARD_DIKOM_DK300] = { - .name = "Dikom DK300", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = dikom_dk300_digital, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = default_analog, - } }, - }, - [EM2883_BOARD_KWORLD_HYBRID_330U] = { - .name = "Kworld PlusTV HD Hybrid 330", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = kworld_330u_digital, - .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, - .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_EEPROM_ON_BOARD | - EM28XX_I2C_EEPROM_KEY_VALID, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = kworld_330u_analog, - .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = kworld_330u_analog, - .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = kworld_330u_analog, - } }, - }, - [EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = { - .name = "Compro VideoMate ForYou/Stereo", - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .tvaudio_addr = 0xb0, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_TVP5150, - .adecoder = EM28XX_TVAUDIO, - .mute_gpio = compro_mute_gpio, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = compro_unmute_tv_gpio, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = compro_unmute_svid_gpio, - } }, - }, - [EM2860_BOARD_KAIOMY_TVNPC_U2] = { - .name = "Kaiomy TVnPC U2", - .vchannels = 3, - .tuner_type = TUNER_XC2028, - .tuner_addr = 0x61, - .mts_firmware = 1, - .decoder = EM28XX_TVP5150, - .tuner_gpio = default_tuner_gpio, - .ir_codes = RC_MAP_KAIOMY, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - } }, - .radio = { - .type = EM28XX_RADIO, - .amux = EM28XX_AMUX_LINE_IN, - } - }, - [EM2860_BOARD_EASYCAP] = { - .name = "Easy Cap Capture DC-60", - .vchannels = 2, - .tuner_type = TUNER_ABSENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_IODATA_GVMVP_SZ] = { - .name = "IO-DATA GV-MVP/SZ", - .tuner_type = TUNER_PHILIPS_FM1236_MK3, - .tuner_gpio = default_tuner_gpio, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - }, { /* Composite has not been tested yet */ - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_VIDEO, - }, { /* S-video has not been tested yet */ - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_VIDEO, - } }, - }, - [EM2860_BOARD_TERRATEC_GRABBY] = { - .name = "Terratec Grabby", - .vchannels = 2, - .tuner_type = TUNER_ABSENT, - .decoder = EM28XX_SAA711X, - .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2860_BOARD_TERRATEC_AV350] = { - .name = "Terratec AV350", - .vchannels = 2, - .tuner_type = TUNER_ABSENT, - .decoder = EM28XX_TVP5150, - .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, - .mute_gpio = terratec_av350_mute_gpio, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AUDIO_SRC_LINE, - .gpio = terratec_av350_unmute_gpio, - - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AUDIO_SRC_LINE, - .gpio = terratec_av350_unmute_gpio, - } }, - }, - - [EM2860_BOARD_ELGATO_VIDEO_CAPTURE] = { - .name = "Elgato Video Capture", - .decoder = EM28XX_SAA711X, - .tuner_type = TUNER_ABSENT, /* Capture only device */ - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - - [EM2882_BOARD_EVGA_INDTUBE] = { - .name = "Evga inDtube", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = evga_indtube_digital, - .ir_codes = RC_MAP_EVGA_INDTUBE, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = evga_indtube_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = evga_indtube_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = evga_indtube_analog, - } }, - }, - /* eb1a:2868 Empia EM2870 + Philips CU1216L NIM (Philips TDA10023 + - Infineon TUA6034) */ - [EM2870_BOARD_REDDO_DVB_C_USB_BOX] = { - .name = "Reddo DVB-C USB TV Box", - .tuner_type = TUNER_ABSENT, - .tuner_gpio = reddo_dvb_c_usb_box, - .has_dvb = 1, - }, - /* 1b80:a340 - Empia EM2870, NXP TDA18271HD and LG DT3304, sold - * initially as the KWorld PlusTV 340U, then as the UB435-Q. - * Early variants have a TDA18271HD/C1, later ones a TDA18271HD/C2 */ - [EM2870_BOARD_KWORLD_A340] = { - .name = "KWorld PlusTV 340U or UB435-Q (ATSC)", - .tuner_type = TUNER_ABSENT, /* Digital-only TDA18271HD */ - .has_dvb = 1, - .dvb_gpio = kworld_a340_digital, - .tuner_gpio = default_tuner_gpio, - }, - /* 2013:024f PCTV nanoStick T2 290e. - * Empia EM28174, Sony CXD2820R and NXP TDA18271HD/C2 */ - [EM28174_BOARD_PCTV_290E] = { - .name = "PCTV nanoStick T2 290e", - .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ, - .tuner_type = TUNER_ABSENT, - .tuner_gpio = pctv_290e, - .has_dvb = 1, - .ir_codes = RC_MAP_PINNACLE_PCTV_HD, - }, - /* 2013:024f PCTV DVB-S2 Stick 460e - * Empia EM28174, NXP TDA10071, Conexant CX24118A and Allegro A8293 */ - [EM28174_BOARD_PCTV_460E] = { - .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ, - .name = "PCTV DVB-S2 Stick (460e)", - .tuner_type = TUNER_ABSENT, - .tuner_gpio = pctv_460e, - .has_dvb = 1, - .ir_codes = RC_MAP_PINNACLE_PCTV_HD, - }, - /* eb1a:5006 Honestech VIDBOX NW03 - * Empia EM2860, Philips SAA7113, Empia EMP202, No Tuner */ - [EM2860_BOARD_HT_VIDBOX_NW03] = { - .name = "Honestech Vidbox NW03", - .tuner_type = TUNER_ABSENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, /* S-VIDEO needs confirming */ - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - /* 1b80:e425 MaxMedia UB425-TC - * Empia EM2874B + Micronas DRX 3913KA2 + NXP TDA18271HDC2 */ - [EM2874_BOARD_MAXMEDIA_UB425_TC] = { - .name = "MaxMedia UB425-TC", - .tuner_type = TUNER_ABSENT, - .tuner_gpio = maxmedia_ub425_tc, - .has_dvb = 1, - .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_400_KHZ, - }, - /* 2304:0242 PCTV QuatroStick (510e) - * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2 */ - [EM2884_BOARD_PCTV_510E] = { - .name = "PCTV QuatroStick (510e)", - .tuner_type = TUNER_ABSENT, - .tuner_gpio = pctv_510e, - .has_dvb = 1, - .ir_codes = RC_MAP_PINNACLE_PCTV_HD, - .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_400_KHZ, - }, - /* 2013:0251 PCTV QuatroStick nano (520e) - * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2 */ - [EM2884_BOARD_PCTV_520E] = { - .name = "PCTV QuatroStick nano (520e)", - .tuner_type = TUNER_ABSENT, - .tuner_gpio = pctv_520e, - .has_dvb = 1, - .ir_codes = RC_MAP_PINNACLE_PCTV_HD, - .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_400_KHZ, - }, -}; -const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); - -/* table of devices that work with this driver */ -struct usb_device_id em28xx_id_table[] = { - { USB_DEVICE(0xeb1a, 0x2750), - .driver_info = EM2750_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2751), - .driver_info = EM2750_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2800), - .driver_info = EM2800_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2710), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2820), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2821), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2860), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2861), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2862), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2863), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2870), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2881), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2883), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2868), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2875), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0xe300), - .driver_info = EM2861_BOARD_KWORLD_PVRTV_300U }, - { USB_DEVICE(0xeb1a, 0xe303), - .driver_info = EM2860_BOARD_KAIOMY_TVNPC_U2 }, - { USB_DEVICE(0xeb1a, 0xe305), - .driver_info = EM2880_BOARD_KWORLD_DVB_305U }, - { USB_DEVICE(0xeb1a, 0xe310), - .driver_info = EM2880_BOARD_MSI_DIGIVOX_AD }, - { USB_DEVICE(0xeb1a, 0xa313), - .driver_info = EM2882_BOARD_KWORLD_ATSC_315U }, - { USB_DEVICE(0xeb1a, 0xa316), - .driver_info = EM2883_BOARD_KWORLD_HYBRID_330U }, - { USB_DEVICE(0xeb1a, 0xe320), - .driver_info = EM2880_BOARD_MSI_DIGIVOX_AD_II }, - { USB_DEVICE(0xeb1a, 0xe323), - .driver_info = EM2882_BOARD_KWORLD_VS_DVBT }, - { USB_DEVICE(0xeb1a, 0xe350), - .driver_info = EM2870_BOARD_KWORLD_350U }, - { USB_DEVICE(0xeb1a, 0xe355), - .driver_info = EM2870_BOARD_KWORLD_355U }, - { USB_DEVICE(0xeb1a, 0x2801), - .driver_info = EM2800_BOARD_GRABBEEX_USB2800 }, - { USB_DEVICE(0xeb1a, 0xe357), - .driver_info = EM2870_BOARD_KWORLD_355U }, - { USB_DEVICE(0xeb1a, 0xe359), - .driver_info = EM2870_BOARD_KWORLD_355U }, - { USB_DEVICE(0x1b80, 0xe302), - .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kaiser Baas Video to DVD maker */ - { USB_DEVICE(0x1b80, 0xe304), - .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kworld DVD Maker 2 */ - { USB_DEVICE(0x0ccd, 0x0036), - .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 }, - { USB_DEVICE(0x0ccd, 0x004c), - .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS_FR }, - { USB_DEVICE(0x0ccd, 0x004f), - .driver_info = EM2860_BOARD_TERRATEC_HYBRID_XS }, - { USB_DEVICE(0x0ccd, 0x005e), - .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS }, - { USB_DEVICE(0x0ccd, 0x0042), - .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS }, - { USB_DEVICE(0x0ccd, 0x0043), - .driver_info = EM2870_BOARD_TERRATEC_XS }, - { USB_DEVICE(0x0ccd, 0x008e), /* Cinergy HTC USB XS Rev. 1 */ - .driver_info = EM2884_BOARD_TERRATEC_H5 }, - { USB_DEVICE(0x0ccd, 0x00ac), /* Cinergy HTC USB XS Rev. 2 */ - .driver_info = EM2884_BOARD_TERRATEC_H5 }, - { USB_DEVICE(0x0ccd, 0x10a2), /* H5 Rev. 1 */ - .driver_info = EM2884_BOARD_TERRATEC_H5 }, - { USB_DEVICE(0x0ccd, 0x10ad), /* H5 Rev. 2 */ - .driver_info = EM2884_BOARD_TERRATEC_H5 }, - { USB_DEVICE(0x0ccd, 0x0084), - .driver_info = EM2860_BOARD_TERRATEC_AV350 }, - { USB_DEVICE(0x0ccd, 0x0096), - .driver_info = EM2860_BOARD_TERRATEC_GRABBY }, - { USB_DEVICE(0x0ccd, 0x10AF), - .driver_info = EM2860_BOARD_TERRATEC_GRABBY }, - { USB_DEVICE(0x0ccd, 0x00b2), - .driver_info = EM2884_BOARD_CINERGY_HTC_STICK }, - { USB_DEVICE(0x0fd9, 0x0033), - .driver_info = EM2860_BOARD_ELGATO_VIDEO_CAPTURE}, - { USB_DEVICE(0x185b, 0x2870), - .driver_info = EM2870_BOARD_COMPRO_VIDEOMATE }, - { USB_DEVICE(0x185b, 0x2041), - .driver_info = EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU }, - { USB_DEVICE(0x2040, 0x4200), - .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, - { USB_DEVICE(0x2040, 0x4201), - .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, - { USB_DEVICE(0x2040, 0x6500), - .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, - { USB_DEVICE(0x2040, 0x6502), - .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2 }, - { USB_DEVICE(0x2040, 0x6513), /* HCW HVR-980 */ - .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 }, - { USB_DEVICE(0x2040, 0x6517), /* HP HVR-950 */ - .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 }, - { USB_DEVICE(0x2040, 0x651b), /* RP HVR-950 */ - .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 }, - { USB_DEVICE(0x2040, 0x651f), - .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 }, - { USB_DEVICE(0x0438, 0xb002), - .driver_info = EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 }, - { USB_DEVICE(0x2001, 0xf112), - .driver_info = EM2820_BOARD_DLINK_USB_TV }, - { USB_DEVICE(0x2304, 0x0207), - .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, - { USB_DEVICE(0x2304, 0x0208), - .driver_info = EM2820_BOARD_PINNACLE_USB_2 }, - { USB_DEVICE(0x2304, 0x021a), - .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, - { USB_DEVICE(0x2304, 0x0226), - .driver_info = EM2882_BOARD_PINNACLE_HYBRID_PRO_330E }, - { USB_DEVICE(0x2304, 0x0227), - .driver_info = EM2880_BOARD_PINNACLE_PCTV_HD_PRO }, - { USB_DEVICE(0x0413, 0x6023), - .driver_info = EM2800_BOARD_LEADTEK_WINFAST_USBII }, - { USB_DEVICE(0x093b, 0xa003), - .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, - { USB_DEVICE(0x093b, 0xa005), - .driver_info = EM2861_BOARD_PLEXTOR_PX_TV100U }, - { USB_DEVICE(0x04bb, 0x0515), - .driver_info = EM2820_BOARD_IODATA_GVMVP_SZ }, - { USB_DEVICE(0xeb1a, 0x50a6), - .driver_info = EM2860_BOARD_GADMEI_UTV330 }, - { USB_DEVICE(0x1b80, 0xa340), - .driver_info = EM2870_BOARD_KWORLD_A340 }, - { USB_DEVICE(0x2013, 0x024f), - .driver_info = EM28174_BOARD_PCTV_290E }, - { USB_DEVICE(0x2013, 0x024c), - .driver_info = EM28174_BOARD_PCTV_460E }, - { USB_DEVICE(0x2040, 0x1605), - .driver_info = EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C }, - { USB_DEVICE(0xeb1a, 0x5006), - .driver_info = EM2860_BOARD_HT_VIDBOX_NW03 }, - { USB_DEVICE(0x1b80, 0xe309), /* Sveon STV40 */ - .driver_info = EM2860_BOARD_EASYCAP }, - { USB_DEVICE(0x1b80, 0xe425), - .driver_info = EM2874_BOARD_MAXMEDIA_UB425_TC }, - { USB_DEVICE(0x2304, 0x0242), - .driver_info = EM2884_BOARD_PCTV_510E }, - { USB_DEVICE(0x2013, 0x0251), - .driver_info = EM2884_BOARD_PCTV_520E }, - { }, -}; -MODULE_DEVICE_TABLE(usb, em28xx_id_table); - -/* - * EEPROM hash table for devices with generic USB IDs - */ -static struct em28xx_hash_table em28xx_eeprom_hash[] = { - /* P/N: SA 60002070465 Tuner: TVF7533-MF */ - {0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF}, - {0x72cc5a8b, EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2, TUNER_YMEC_TVF_5533MF}, - {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028}, - {0x166a0441, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028}, - {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028}, - {0xb8846b20, EM2881_BOARD_PINNACLE_HYBRID_PRO, TUNER_XC2028}, - {0x63f653bd, EM2870_BOARD_REDDO_DVB_C_USB_BOX, TUNER_ABSENT}, - {0x4e913442, EM2882_BOARD_DIKOM_DK300, TUNER_XC2028}, -}; - -/* I2C devicelist hash table for devices with generic USB IDs */ -static struct em28xx_hash_table em28xx_i2c_hash[] = { - {0xb06a32c3, EM2800_BOARD_TERRATEC_CINERGY_200, TUNER_LG_PAL_NEW_TAPC}, - {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC}, - {0x1ba50080, EM2860_BOARD_SAA711X_REFERENCE_DESIGN, TUNER_ABSENT}, - {0x77800080, EM2860_BOARD_TVP5150_REFERENCE_DESIGN, TUNER_ABSENT}, - {0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC}, - {0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF}, - {0x6b800080, EM2874_BOARD_LEADERSHIP_ISDBT, TUNER_ABSENT}, -}; - -/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */ -static unsigned short saa711x_addrs[] = { - 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */ - 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */ - I2C_CLIENT_END }; - -static unsigned short tvp5150_addrs[] = { - 0xb8 >> 1, - 0xba >> 1, - I2C_CLIENT_END -}; - -static unsigned short msp3400_addrs[] = { - 0x80 >> 1, - 0x88 >> 1, - I2C_CLIENT_END -}; - -int em28xx_tuner_callback(void *ptr, int component, int command, int arg) -{ - int rc = 0; - struct em28xx *dev = ptr; - - if (dev->tuner_type != TUNER_XC2028 && dev->tuner_type != TUNER_XC5000) - return 0; - - if (command != XC2028_TUNER_RESET && command != XC5000_TUNER_RESET) - return 0; - - rc = em28xx_gpio_set(dev, dev->board.tuner_gpio); - - return rc; -} -EXPORT_SYMBOL_GPL(em28xx_tuner_callback); - -static inline void em28xx_set_model(struct em28xx *dev) -{ - memcpy(&dev->board, &em28xx_boards[dev->model], sizeof(dev->board)); - - /* Those are the default values for the majority of boards - Use those values if not specified otherwise at boards entry - */ - if (!dev->board.xclk) - dev->board.xclk = EM28XX_XCLK_IR_RC5_MODE | - EM28XX_XCLK_FREQUENCY_12MHZ; - - if (!dev->board.i2c_speed) - dev->board.i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_100_KHZ; -} - - -/* FIXME: Should be replaced by a proper mt9m111 driver */ -static int em28xx_initialize_mt9m111(struct em28xx *dev) -{ - int i; - unsigned char regs[][3] = { - { 0x0d, 0x00, 0x01, }, /* reset and use defaults */ - { 0x0d, 0x00, 0x00, }, - { 0x0a, 0x00, 0x21, }, - { 0x21, 0x04, 0x00, }, /* full readout speed, no row/col skipping */ - }; - - for (i = 0; i < ARRAY_SIZE(regs); i++) - i2c_master_send(&dev->i2c_client, ®s[i][0], 3); - - return 0; -} - - -/* FIXME: Should be replaced by a proper mt9m001 driver */ -static int em28xx_initialize_mt9m001(struct em28xx *dev) -{ - int i; - unsigned char regs[][3] = { - { 0x0d, 0x00, 0x01, }, - { 0x0d, 0x00, 0x00, }, - { 0x04, 0x05, 0x00, }, /* hres = 1280 */ - { 0x03, 0x04, 0x00, }, /* vres = 1024 */ - { 0x20, 0x11, 0x00, }, - { 0x06, 0x00, 0x10, }, - { 0x2b, 0x00, 0x24, }, - { 0x2e, 0x00, 0x24, }, - { 0x35, 0x00, 0x24, }, - { 0x2d, 0x00, 0x20, }, - { 0x2c, 0x00, 0x20, }, - { 0x09, 0x0a, 0xd4, }, - { 0x35, 0x00, 0x57, }, - }; - - for (i = 0; i < ARRAY_SIZE(regs); i++) - i2c_master_send(&dev->i2c_client, ®s[i][0], 3); - - return 0; -} - -/* HINT method: webcam I2C chips - * - * This method works for webcams with Micron sensors - */ -static int em28xx_hint_sensor(struct em28xx *dev) -{ - int rc; - char *sensor_name; - unsigned char cmd; - __be16 version_be; - u16 version; - - /* Micron sensor detection */ - dev->i2c_client.addr = 0xba >> 1; - cmd = 0; - i2c_master_send(&dev->i2c_client, &cmd, 1); - rc = i2c_master_recv(&dev->i2c_client, (char *)&version_be, 2); - if (rc != 2) - return -EINVAL; - - version = be16_to_cpu(version_be); - switch (version) { - case 0x8232: /* mt9v011 640x480 1.3 Mpix sensor */ - case 0x8243: /* mt9v011 rev B 640x480 1.3 Mpix sensor */ - dev->model = EM2820_BOARD_SILVERCREST_WEBCAM; - em28xx_set_model(dev); - - sensor_name = "mt9v011"; - dev->em28xx_sensor = EM28XX_MT9V011; - dev->sensor_xres = 640; - dev->sensor_yres = 480; - /* - * FIXME: mt9v011 uses I2S speed as xtal clk - at least with - * the Silvercrest cam I have here for testing - for higher - * resolutions, a high clock cause horizontal artifacts, so we - * need to use a lower xclk frequency. - * Yet, it would be possible to adjust xclk depending on the - * desired resolution, since this affects directly the - * frame rate. - */ - dev->board.xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ; - dev->sensor_xtal = 4300000; - - /* probably means GRGB 16 bit bayer */ - dev->vinmode = 0x0d; - dev->vinctl = 0x00; - - break; - - case 0x143a: /* MT9M111 as found in the ECS G200 */ - dev->model = EM2750_BOARD_UNKNOWN; - em28xx_set_model(dev); - - sensor_name = "mt9m111"; - dev->board.xclk = EM28XX_XCLK_FREQUENCY_48MHZ; - dev->em28xx_sensor = EM28XX_MT9M111; - em28xx_initialize_mt9m111(dev); - dev->sensor_xres = 640; - dev->sensor_yres = 512; - - dev->vinmode = 0x0a; - dev->vinctl = 0x00; - - break; - - case 0x8431: - dev->model = EM2750_BOARD_UNKNOWN; - em28xx_set_model(dev); - - sensor_name = "mt9m001"; - dev->em28xx_sensor = EM28XX_MT9M001; - em28xx_initialize_mt9m001(dev); - dev->sensor_xres = 1280; - dev->sensor_yres = 1024; - - /* probably means BGGR 16 bit bayer */ - dev->vinmode = 0x0c; - dev->vinctl = 0x00; - - break; - default: - printk("Unknown Micron Sensor 0x%04x\n", version); - return -EINVAL; - } - - /* Setup webcam defaults */ - em28xx_pre_card_setup(dev); - - em28xx_errdev("Sensor is %s, using model %s entry.\n", - sensor_name, em28xx_boards[dev->model].name); - - return 0; -} - -/* Since em28xx_pre_card_setup() requires a proper dev->model, - * this won't work for boards with generic PCI IDs - */ -static void em28xx_pre_card_setup(struct em28xx *dev) -{ - /* Set the initial XCLK and I2C clock values based on the board - definition */ - em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk & 0x7f); - if (!dev->board.is_em2800) - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed); - msleep(50); - - /* request some modules */ - switch (dev->model) { - case EM2861_BOARD_PLEXTOR_PX_TV100U: - /* Sets the msp34xx I2S speed */ - dev->i2s_speed = 2048000; - break; - case EM2861_BOARD_KWORLD_PVRTV_300U: - case EM2880_BOARD_KWORLD_DVB_305U: - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x6d); - msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x7d); - msleep(10); - break; - case EM2870_BOARD_COMPRO_VIDEOMATE: - /* TODO: someone can do some cleanup here... - not everything's needed */ - em28xx_write_reg(dev, EM2880_R04_GPO, 0x00); - msleep(10); - em28xx_write_reg(dev, EM2880_R04_GPO, 0x01); - msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); - mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfc); - mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xdc); - mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfc); - mdelay(70); - break; - case EM2870_BOARD_TERRATEC_XS_MT2060: - /* this device needs some gpio writes to get the DVB-T - demod work */ - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); - mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xde); - mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); - mdelay(70); - break; - case EM2870_BOARD_PINNACLE_PCTV_DVB: - /* this device needs some gpio writes to get the - DVB-T demod work */ - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); - mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xde); - mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); - mdelay(70); - break; - case EM2820_BOARD_GADMEI_UTV310: - case EM2820_BOARD_MSI_VOX_USB_2: - /* enables audio for that devices */ - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); - break; - - case EM2882_BOARD_KWORLD_ATSC_315U: - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); - msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); - msleep(10); - em28xx_write_reg(dev, EM2880_R04_GPO, 0x00); - msleep(10); - em28xx_write_reg(dev, EM2880_R04_GPO, 0x08); - msleep(10); - break; - - case EM2860_BOARD_KAIOMY_TVNPC_U2: - em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x07", 1); - em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1); - em28xx_write_regs(dev, 0x0d, "\x42", 1); - em28xx_write_regs(dev, 0x08, "\xfd", 1); - msleep(10); - em28xx_write_regs(dev, 0x08, "\xff", 1); - msleep(10); - em28xx_write_regs(dev, 0x08, "\x7f", 1); - msleep(10); - em28xx_write_regs(dev, 0x08, "\x6b", 1); - - break; - case EM2860_BOARD_EASYCAP: - em28xx_write_regs(dev, 0x08, "\xf8", 1); - break; - - case EM2820_BOARD_IODATA_GVMVP_SZ: - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); - msleep(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7); - msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); - msleep(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); - msleep(70); - break; - } - - em28xx_gpio_set(dev, dev->board.tuner_gpio); - em28xx_set_mode(dev, EM28XX_ANALOG_MODE); - - /* Unlock device */ - em28xx_set_mode(dev, EM28XX_SUSPEND); -} - -static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) -{ - memset(ctl, 0, sizeof(*ctl)); - - ctl->fname = XC2028_DEFAULT_FIRMWARE; - ctl->max_len = 64; - ctl->mts = em28xx_boards[dev->model].mts_firmware; - - switch (dev->model) { - case EM2880_BOARD_EMPIRE_DUAL_TV: - case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: - case EM2882_BOARD_TERRATEC_HYBRID_XS: - ctl->demod = XC3028_FE_ZARLINK456; - break; - case EM2880_BOARD_TERRATEC_HYBRID_XS: - case EM2880_BOARD_TERRATEC_HYBRID_XS_FR: - case EM2881_BOARD_PINNACLE_HYBRID_PRO: - ctl->demod = XC3028_FE_ZARLINK456; - break; - case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: - case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E: - ctl->demod = XC3028_FE_DEFAULT; - break; - case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: - ctl->demod = XC3028_FE_DEFAULT; - ctl->fname = XC3028L_DEFAULT_FIRMWARE; - break; - case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: - case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: - case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: - /* FIXME: Better to specify the needed IF */ - ctl->demod = XC3028_FE_DEFAULT; - break; - case EM2883_BOARD_KWORLD_HYBRID_330U: - case EM2882_BOARD_DIKOM_DK300: - case EM2882_BOARD_KWORLD_VS_DVBT: - ctl->demod = XC3028_FE_CHINA; - ctl->fname = XC2028_DEFAULT_FIRMWARE; - break; - case EM2882_BOARD_EVGA_INDTUBE: - ctl->demod = XC3028_FE_CHINA; - ctl->fname = XC3028L_DEFAULT_FIRMWARE; - break; - default: - ctl->demod = XC3028_FE_OREN538; - } -} - -static void em28xx_tuner_setup(struct em28xx *dev) -{ - struct tuner_setup tun_setup; - struct v4l2_frequency f; - - if (dev->tuner_type == TUNER_ABSENT) - return; - - memset(&tun_setup, 0, sizeof(tun_setup)); - - tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; - tun_setup.tuner_callback = em28xx_tuner_callback; - - if (dev->board.radio.type) { - tun_setup.type = dev->board.radio.type; - tun_setup.addr = dev->board.radio_addr; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup); - } - - if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) { - tun_setup.type = dev->tuner_type; - tun_setup.addr = dev->tuner_addr; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup); - } - - if (dev->tda9887_conf) { - struct v4l2_priv_tun_config tda9887_cfg; - - tda9887_cfg.tuner = TUNER_TDA9887; - tda9887_cfg.priv = &dev->tda9887_conf; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &tda9887_cfg); - } - - if (dev->tuner_type == TUNER_XC2028) { - struct v4l2_priv_tun_config xc2028_cfg; - struct xc2028_ctrl ctl; - - memset(&xc2028_cfg, 0, sizeof(xc2028_cfg)); - memset(&ctl, 0, sizeof(ctl)); - - em28xx_setup_xc3028(dev, &ctl); - - xc2028_cfg.tuner = TUNER_XC2028; - xc2028_cfg.priv = &ctl; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &xc2028_cfg); - } - - /* configure tuner */ - f.tuner = 0; - f.type = V4L2_TUNER_ANALOG_TV; - f.frequency = 9076; /* just a magic number */ - dev->ctl_freq = f.frequency; - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f); -} - -static int em28xx_hint_board(struct em28xx *dev) -{ - int i; - - /* HINT method: EEPROM - * - * This method works only for boards with eeprom. - * Uses a hash of all eeprom bytes. The hash should be - * unique for a vendor/tuner pair. - * There are a high chance that tuners for different - * video standards produce different hashes. - */ - for (i = 0; i < ARRAY_SIZE(em28xx_eeprom_hash); i++) { - if (dev->hash == em28xx_eeprom_hash[i].hash) { - dev->model = em28xx_eeprom_hash[i].model; - dev->tuner_type = em28xx_eeprom_hash[i].tuner; - - em28xx_errdev("Your board has no unique USB ID.\n"); - em28xx_errdev("A hint were successfully done, " - "based on eeprom hash.\n"); - em28xx_errdev("This method is not 100%% failproof.\n"); - em28xx_errdev("If the board were missdetected, " - "please email this log to:\n"); - em28xx_errdev("\tV4L Mailing List " - " <linux-media@vger.kernel.org>\n"); - em28xx_errdev("Board detected as %s\n", - em28xx_boards[dev->model].name); - - return 0; - } - } - - /* HINT method: I2C attached devices - * - * This method works for all boards. - * Uses a hash of i2c scanned devices. - * Devices with the same i2c attached chips will - * be considered equal. - * This method is less precise than the eeprom one. - */ - - /* user did not request i2c scanning => do it now */ - if (!dev->i2c_hash) - em28xx_do_i2c_scan(dev); - - for (i = 0; i < ARRAY_SIZE(em28xx_i2c_hash); i++) { - if (dev->i2c_hash == em28xx_i2c_hash[i].hash) { - dev->model = em28xx_i2c_hash[i].model; - dev->tuner_type = em28xx_i2c_hash[i].tuner; - em28xx_errdev("Your board has no unique USB ID.\n"); - em28xx_errdev("A hint were successfully done, " - "based on i2c devicelist hash.\n"); - em28xx_errdev("This method is not 100%% failproof.\n"); - em28xx_errdev("If the board were missdetected, " - "please email this log to:\n"); - em28xx_errdev("\tV4L Mailing List " - " <linux-media@vger.kernel.org>\n"); - em28xx_errdev("Board detected as %s\n", - em28xx_boards[dev->model].name); - - return 0; - } - } - - em28xx_errdev("Your board has no unique USB ID and thus need a " - "hint to be detected.\n"); - em28xx_errdev("You may try to use card=<n> insmod option to " - "workaround that.\n"); - em28xx_errdev("Please send an email with this log to:\n"); - em28xx_errdev("\tV4L Mailing List <linux-media@vger.kernel.org>\n"); - em28xx_errdev("Board eeprom hash is 0x%08lx\n", dev->hash); - em28xx_errdev("Board i2c devicelist hash is 0x%08lx\n", dev->i2c_hash); - - em28xx_errdev("Here is a list of valid choices for the card=<n>" - " insmod option:\n"); - for (i = 0; i < em28xx_bcount; i++) { - em28xx_errdev(" card=%d -> %s\n", - i, em28xx_boards[i].name); - } - return -1; -} - -static void em28xx_card_setup(struct em28xx *dev) -{ - /* - * If the device can be a webcam, seek for a sensor. - * If sensor is not found, then it isn't a webcam. - */ - if (dev->board.is_webcam) { - if (em28xx_hint_sensor(dev) < 0) - dev->board.is_webcam = 0; - else - dev->progressive = 1; - } - - if (!dev->board.is_webcam) { - switch (dev->model) { - case EM2820_BOARD_UNKNOWN: - case EM2800_BOARD_UNKNOWN: - /* - * The K-WORLD DVB-T 310U is detected as an MSI Digivox AD. - * - * This occurs because they share identical USB vendor and - * product IDs. - * - * What we do here is look up the EEPROM hash of the K-WORLD - * and if it is found then we decide that we do not have - * a DIGIVOX and reset the device to the K-WORLD instead. - * - * This solution is only valid if they do not share eeprom - * hash identities which has not been determined as yet. - */ - if (em28xx_hint_board(dev) < 0) - em28xx_errdev("Board not discovered\n"); - else { - em28xx_set_model(dev); - em28xx_pre_card_setup(dev); - } - break; - default: - em28xx_set_model(dev); - } - } - - em28xx_info("Identified as %s (card=%d)\n", - dev->board.name, dev->model); - - dev->tuner_type = em28xx_boards[dev->model].tuner_type; - if (em28xx_boards[dev->model].tuner_addr) - dev->tuner_addr = em28xx_boards[dev->model].tuner_addr; - - if (em28xx_boards[dev->model].tda9887_conf) - dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf; - - /* request some modules */ - switch (dev->model) { - case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: - case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: - case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: - case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: - case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: - { - struct tveeprom tv; -#if defined(CONFIG_MODULES) && defined(MODULE) - request_module("tveeprom"); -#endif - /* Call first TVeeprom */ - - dev->i2c_client.addr = 0xa0 >> 1; - tveeprom_hauppauge_analog(&dev->i2c_client, &tv, dev->eedata); - - dev->tuner_type = tv.tuner_type; - - if (tv.audio_processor == V4L2_IDENT_MSPX4XX) { - dev->i2s_speed = 2048000; - dev->board.has_msp34xx = 1; - } - break; - } - case EM2882_BOARD_KWORLD_ATSC_315U: - em28xx_write_reg(dev, 0x0d, 0x42); - msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); - msleep(10); - break; - case EM2820_BOARD_KWORLD_PVRTV2800RF: - /* GPIO enables sound on KWORLD PVR TV 2800RF */ - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf9); - break; - case EM2820_BOARD_UNKNOWN: - case EM2800_BOARD_UNKNOWN: - /* - * The K-WORLD DVB-T 310U is detected as an MSI Digivox AD. - * - * This occurs because they share identical USB vendor and - * product IDs. - * - * What we do here is look up the EEPROM hash of the K-WORLD - * and if it is found then we decide that we do not have - * a DIGIVOX and reset the device to the K-WORLD instead. - * - * This solution is only valid if they do not share eeprom - * hash identities which has not been determined as yet. - */ - case EM2880_BOARD_MSI_DIGIVOX_AD: - if (!em28xx_hint_board(dev)) - em28xx_set_model(dev); - - /* In cases where we had to use a board hint, the call to - em28xx_set_mode() in em28xx_pre_card_setup() was a no-op, - so make the call now so the analog GPIOs are set properly - before probing the i2c bus. */ - em28xx_gpio_set(dev, dev->board.tuner_gpio); - em28xx_set_mode(dev, EM28XX_ANALOG_MODE); - break; - -/* - * The Dikom DK300 is detected as an Kworld VS-DVB-T 323UR. - * - * This occurs because they share identical USB vendor and - * product IDs. - * - * What we do here is look up the EEPROM hash of the Dikom - * and if it is found then we decide that we do not have - * a Kworld and reset the device to the Dikom instead. - * - * This solution is only valid if they do not share eeprom - * hash identities which has not been determined as yet. - */ - case EM2882_BOARD_KWORLD_VS_DVBT: - if (!em28xx_hint_board(dev)) - em28xx_set_model(dev); - - /* In cases where we had to use a board hint, the call to - em28xx_set_mode() in em28xx_pre_card_setup() was a no-op, - so make the call now so the analog GPIOs are set properly - before probing the i2c bus. */ - em28xx_gpio_set(dev, dev->board.tuner_gpio); - em28xx_set_mode(dev, EM28XX_ANALOG_MODE); - break; - } - - if (dev->board.valid == EM28XX_BOARD_NOT_VALIDATED) { - em28xx_errdev("\n\n"); - em28xx_errdev("The support for this board weren't " - "valid yet.\n"); - em28xx_errdev("Please send a report of having this working\n"); - em28xx_errdev("not to V4L mailing list (and/or to other " - "addresses)\n\n"); - } - - /* Allow override tuner type by a module parameter */ - if (tuner >= 0) - dev->tuner_type = tuner; - - /* request some modules */ - if (dev->board.has_msp34xx) - v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "msp3400", 0, msp3400_addrs); - - if (dev->board.decoder == EM28XX_SAA711X) - v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "saa7115_auto", 0, saa711x_addrs); - - if (dev->board.decoder == EM28XX_TVP5150) - v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tvp5150", 0, tvp5150_addrs); - - if (dev->em28xx_sensor == EM28XX_MT9V011) { - struct mt9v011_platform_data pdata; - struct i2c_board_info mt9v011_info = { - .type = "mt9v011", - .addr = 0xba >> 1, - .platform_data = &pdata, - }; - - pdata.xtal = dev->sensor_xtal; - v4l2_i2c_new_subdev_board(&dev->v4l2_dev, &dev->i2c_adap, - &mt9v011_info, NULL); - } - - - if (dev->board.adecoder == EM28XX_TVAUDIO) - v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tvaudio", dev->board.tvaudio_addr, NULL); - - if (dev->board.tuner_type != TUNER_ABSENT) { - int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); - - if (dev->board.radio.type) - v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tuner", dev->board.radio_addr, NULL); - - if (has_demod) - v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_adap, "tuner", - 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); - if (dev->tuner_addr == 0) { - enum v4l2_i2c_tuner_type type = - has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; - struct v4l2_subdev *sd; - - sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_adap, "tuner", - 0, v4l2_i2c_tuner_addrs(type)); - - if (sd) - dev->tuner_addr = v4l2_i2c_subdev_addr(sd); - } else { - v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tuner", dev->tuner_addr, NULL); - } - } - - em28xx_tuner_setup(dev); -} - - -#if defined(CONFIG_MODULES) && defined(MODULE) -static void request_module_async(struct work_struct *work) -{ - struct em28xx *dev = container_of(work, - struct em28xx, request_module_wk); - - if (dev->has_audio_class) - request_module("snd-usb-audio"); - else if (dev->has_alsa_audio) - request_module("em28xx-alsa"); - - if (dev->board.has_dvb) - request_module("em28xx-dvb"); - if (dev->board.ir_codes && !disable_ir) - request_module("em28xx-rc"); -} - -static void request_modules(struct em28xx *dev) -{ - INIT_WORK(&dev->request_module_wk, request_module_async); - schedule_work(&dev->request_module_wk); -} - -static void flush_request_modules(struct em28xx *dev) -{ - flush_work_sync(&dev->request_module_wk); -} -#else -#define request_modules(dev) -#define flush_request_modules(dev) -#endif /* CONFIG_MODULES */ - -/* - * em28xx_release_resources() - * unregisters the v4l2,i2c and usb devices - * called when the device gets disconnected or at module unload -*/ -void em28xx_release_resources(struct em28xx *dev) -{ - /*FIXME: I2C IR should be disconnected */ - - em28xx_release_analog_resources(dev); - - em28xx_i2c_unregister(dev); - - v4l2_device_unregister(&dev->v4l2_dev); - - usb_put_dev(dev->udev); - - /* Mark device as unused */ - clear_bit(dev->devno, &em28xx_devused); -}; - -/* - * em28xx_init_dev() - * allocates and inits the device structs, registers i2c bus and v4l device - */ -static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, - struct usb_interface *interface, - int minor) -{ - int retval; - - dev->udev = udev; - mutex_init(&dev->ctrl_urb_lock); - spin_lock_init(&dev->slock); - - dev->em28xx_write_regs = em28xx_write_regs; - dev->em28xx_read_reg = em28xx_read_reg; - dev->em28xx_read_reg_req_len = em28xx_read_reg_req_len; - dev->em28xx_write_regs_req = em28xx_write_regs_req; - dev->em28xx_read_reg_req = em28xx_read_reg_req; - dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800; - - em28xx_set_model(dev); - - /* Set the default GPO/GPIO for legacy devices */ - dev->reg_gpo_num = EM2880_R04_GPO; - dev->reg_gpio_num = EM28XX_R08_GPIO; - - dev->wait_after_write = 5; - - /* Based on the Chip ID, set the device configuration */ - retval = em28xx_read_reg(dev, EM28XX_R0A_CHIPID); - if (retval > 0) { - dev->chip_id = retval; - - switch (dev->chip_id) { - case CHIP_ID_EM2800: - em28xx_info("chip ID is em2800\n"); - break; - case CHIP_ID_EM2710: - em28xx_info("chip ID is em2710\n"); - break; - case CHIP_ID_EM2750: - em28xx_info("chip ID is em2750\n"); - break; - case CHIP_ID_EM2820: - em28xx_info("chip ID is em2820 (or em2710)\n"); - break; - case CHIP_ID_EM2840: - em28xx_info("chip ID is em2840\n"); - break; - case CHIP_ID_EM2860: - em28xx_info("chip ID is em2860\n"); - break; - case CHIP_ID_EM2870: - em28xx_info("chip ID is em2870\n"); - dev->wait_after_write = 0; - break; - case CHIP_ID_EM2874: - em28xx_info("chip ID is em2874\n"); - dev->reg_gpio_num = EM2874_R80_GPIO; - dev->wait_after_write = 0; - break; - case CHIP_ID_EM28174: - em28xx_info("chip ID is em28174\n"); - dev->reg_gpio_num = EM2874_R80_GPIO; - dev->wait_after_write = 0; - break; - case CHIP_ID_EM2883: - em28xx_info("chip ID is em2882/em2883\n"); - dev->wait_after_write = 0; - break; - case CHIP_ID_EM2884: - em28xx_info("chip ID is em2884\n"); - dev->reg_gpio_num = EM2874_R80_GPIO; - dev->wait_after_write = 0; - break; - default: - em28xx_info("em28xx chip ID = %d\n", dev->chip_id); - } - } - - if (dev->is_audio_only) { - retval = em28xx_audio_setup(dev); - if (retval) - return -ENODEV; - em28xx_init_extension(dev); - - return 0; - } - - /* Prepopulate cached GPO register content */ - retval = em28xx_read_reg(dev, dev->reg_gpo_num); - if (retval >= 0) - dev->reg_gpo = retval; - - em28xx_pre_card_setup(dev); - - if (!dev->board.is_em2800) { - /* Resets I2C speed */ - retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed); - if (retval < 0) { - em28xx_errdev("%s: em28xx_write_reg failed!" - " retval [%d]\n", - __func__, retval); - return retval; - } - } - - retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); - if (retval < 0) { - em28xx_errdev("Call to v4l2_device_register() failed!\n"); - return retval; - } - - /* register i2c bus */ - retval = em28xx_i2c_register(dev); - if (retval < 0) { - em28xx_errdev("%s: em28xx_i2c_register - error [%d]!\n", - __func__, retval); - goto unregister_dev; - } - - /* - * Default format, used for tvp5150 or saa711x output formats - */ - dev->vinmode = 0x10; - dev->vinctl = EM28XX_VINCTRL_INTERLACED | - EM28XX_VINCTRL_CCIR656_ENABLE; - - /* Do board specific init and eeprom reading */ - em28xx_card_setup(dev); - - /* Configure audio */ - retval = em28xx_audio_setup(dev); - if (retval < 0) { - em28xx_errdev("%s: Error while setting audio - error [%d]!\n", - __func__, retval); - goto fail; - } - - /* wake i2c devices */ - em28xx_wake_i2c(dev); - - /* init video dma queues */ - INIT_LIST_HEAD(&dev->vidq.active); - INIT_LIST_HEAD(&dev->vbiq.active); - - if (dev->board.has_msp34xx) { - /* Send a reset to other chips via gpio */ - retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7); - if (retval < 0) { - em28xx_errdev("%s: em28xx_write_reg - " - "msp34xx(1) failed! error [%d]\n", - __func__, retval); - goto fail; - } - msleep(3); - - retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); - if (retval < 0) { - em28xx_errdev("%s: em28xx_write_reg - " - "msp34xx(2) failed! error [%d]\n", - __func__, retval); - goto fail; - } - msleep(3); - } - - retval = em28xx_register_analog_devices(dev); - if (retval < 0) { - goto fail; - } - - /* Save some power by putting tuner to sleep */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); - - return 0; - -fail: - em28xx_i2c_unregister(dev); - -unregister_dev: - v4l2_device_unregister(&dev->v4l2_dev); - - return retval; -} - -/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */ -#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) - -/* - * em28xx_usb_probe() - * checks for supported devices - */ -static int em28xx_usb_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct usb_device *udev; - struct em28xx *dev = NULL; - int retval; - bool has_audio = false, has_video = false, has_dvb = false; - int i, nr; - const int ifnum = interface->altsetting[0].desc.bInterfaceNumber; - char *speed; - - udev = usb_get_dev(interface_to_usbdev(interface)); - - /* Check to see next free device and mark as used */ - do { - nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS); - if (nr >= EM28XX_MAXBOARDS) { - /* No free device slots */ - printk(DRIVER_NAME ": Supports only %i em28xx boards.\n", - EM28XX_MAXBOARDS); - retval = -ENOMEM; - goto err_no_slot; - } - } while (test_and_set_bit(nr, &em28xx_devused)); - - /* Don't register audio interfaces */ - if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { - em28xx_err(DRIVER_NAME " audio device (%04x:%04x): " - "interface %i, class %i\n", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct), - ifnum, - interface->altsetting[0].desc.bInterfaceClass); - - retval = -ENODEV; - goto err; - } - - /* allocate memory for our device state and initialize it */ - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - em28xx_err(DRIVER_NAME ": out of memory!\n"); - retval = -ENOMEM; - goto err; - } - - /* compute alternate max packet sizes */ - dev->alt_max_pkt_size = kmalloc(sizeof(dev->alt_max_pkt_size[0]) * - interface->num_altsetting, GFP_KERNEL); - if (dev->alt_max_pkt_size == NULL) { - em28xx_errdev("out of memory!\n"); - kfree(dev); - retval = -ENOMEM; - goto err; - } - - /* Get endpoints */ - for (i = 0; i < interface->num_altsetting; i++) { - int ep; - - for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) { - const struct usb_endpoint_descriptor *e; - int sizedescr, size; - - e = &interface->altsetting[i].endpoint[ep].desc; - - sizedescr = le16_to_cpu(e->wMaxPacketSize); - size = sizedescr & 0x7ff; - - if (udev->speed == USB_SPEED_HIGH) - size = size * hb_mult(sizedescr); - - if (usb_endpoint_xfer_isoc(e) && - usb_endpoint_dir_in(e)) { - switch (e->bEndpointAddress) { - case EM28XX_EP_AUDIO: - has_audio = true; - break; - case EM28XX_EP_ANALOG: - has_video = true; - dev->alt_max_pkt_size[i] = size; - break; - case EM28XX_EP_DIGITAL: - has_dvb = true; - if (size > dev->dvb_max_pkt_size) { - dev->dvb_max_pkt_size = size; - dev->dvb_alt = i; - } - break; - } - } - } - } - - if (!(has_audio || has_video || has_dvb)) { - retval = -ENODEV; - goto err_free; - } - - switch (udev->speed) { - case USB_SPEED_LOW: - speed = "1.5"; - break; - case USB_SPEED_UNKNOWN: - case USB_SPEED_FULL: - speed = "12"; - break; - case USB_SPEED_HIGH: - speed = "480"; - break; - default: - speed = "unknown"; - } - - printk(KERN_INFO DRIVER_NAME - ": New device %s %s @ %s Mbps " - "(%04x:%04x, interface %d, class %d)\n", - udev->manufacturer ? udev->manufacturer : "", - udev->product ? udev->product : "", - speed, - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct), - ifnum, - interface->altsetting->desc.bInterfaceNumber); - - if (has_audio) - printk(KERN_INFO DRIVER_NAME - ": Audio Vendor Class interface %i found\n", - ifnum); - if (has_video) - printk(KERN_INFO DRIVER_NAME - ": Video interface %i found\n", - ifnum); - if (has_dvb) - printk(KERN_INFO DRIVER_NAME - ": DVB interface %i found\n", - ifnum); - - /* - * Make sure we have 480 Mbps of bandwidth, otherwise things like - * video stream wouldn't likely work, since 12 Mbps is generally - * not enough even for most Digital TV streams. - */ - if (udev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) { - printk(DRIVER_NAME ": Device initialization failed.\n"); - printk(DRIVER_NAME ": Device must be connected to a high-speed" - " USB 2.0 port.\n"); - retval = -ENODEV; - goto err_free; - } - - snprintf(dev->name, sizeof(dev->name), "em28xx #%d", nr); - dev->devno = nr; - dev->model = id->driver_info; - dev->alt = -1; - dev->is_audio_only = has_audio && !(has_video || has_dvb); - dev->has_alsa_audio = has_audio; - dev->audio_ifnum = ifnum; - - /* Checks if audio is provided by some interface */ - for (i = 0; i < udev->config->desc.bNumInterfaces; i++) { - struct usb_interface *uif = udev->config->interface[i]; - if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { - dev->has_audio_class = 1; - break; - } - } - - dev->num_alt = interface->num_altsetting; - - if ((card[nr] >= 0) && (card[nr] < em28xx_bcount)) - dev->model = card[nr]; - - /* save our data pointer in this interface device */ - usb_set_intfdata(interface, dev); - - /* allocate device struct */ - mutex_init(&dev->lock); - mutex_lock(&dev->lock); - retval = em28xx_init_dev(dev, udev, interface, nr); - if (retval) { - goto unlock_and_free; - } - - if (has_dvb) { - /* pre-allocate DVB isoc transfer buffers */ - retval = em28xx_alloc_isoc(dev, EM28XX_DIGITAL_MODE, - EM28XX_DVB_MAX_PACKETS, - EM28XX_DVB_NUM_BUFS, - dev->dvb_max_pkt_size); - if (retval) { - goto unlock_and_free; - } - } - - request_modules(dev); - - /* Should be the last thing to do, to avoid newer udev's to - open the device before fully initializing it - */ - mutex_unlock(&dev->lock); - - /* - * These extensions can be modules. If the modules are already - * loaded then we can initialise the device now, otherwise we - * will initialise it when the modules load instead. - */ - em28xx_init_extension(dev); - - return 0; - -unlock_and_free: - mutex_unlock(&dev->lock); - -err_free: - kfree(dev->alt_max_pkt_size); - kfree(dev); - -err: - clear_bit(nr, &em28xx_devused); - -err_no_slot: - usb_put_dev(udev); - return retval; -} - -/* - * em28xx_usb_disconnect() - * called when the device gets disconnected - * video device will be unregistered on v4l2_close in case it is still open - */ -static void em28xx_usb_disconnect(struct usb_interface *interface) -{ - struct em28xx *dev; - - dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - - if (!dev) - return; - - if (dev->is_audio_only) { - mutex_lock(&dev->lock); - em28xx_close_extension(dev); - mutex_unlock(&dev->lock); - return; - } - - em28xx_info("disconnecting %s\n", dev->vdev->name); - - flush_request_modules(dev); - - /* wait until all current v4l2 io is finished then deallocate - resources */ - mutex_lock(&dev->lock); - - v4l2_device_disconnect(&dev->v4l2_dev); - - if (dev->users) { - em28xx_warn - ("device %s is open! Deregistration and memory " - "deallocation are deferred on close.\n", - video_device_node_name(dev->vdev)); - - dev->state |= DEV_MISCONFIGURED; - em28xx_uninit_isoc(dev, dev->mode); - dev->state |= DEV_DISCONNECTED; - } else { - dev->state |= DEV_DISCONNECTED; - em28xx_release_resources(dev); - } - - /* free DVB isoc buffers */ - em28xx_uninit_isoc(dev, EM28XX_DIGITAL_MODE); - - mutex_unlock(&dev->lock); - - em28xx_close_extension(dev); - - if (!dev->users) { - kfree(dev->alt_max_pkt_size); - kfree(dev); - } -} - -static struct usb_driver em28xx_usb_driver = { - .name = "em28xx", - .probe = em28xx_usb_probe, - .disconnect = em28xx_usb_disconnect, - .id_table = em28xx_id_table, -}; - -module_usb_driver(em28xx_usb_driver); diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c deleted file mode 100644 index bed07a6..0000000 --- a/drivers/media/video/em28xx/em28xx-core.c +++ /dev/null @@ -1,1260 +0,0 @@ -/* - em28xx-core.c - driver for Empia EM2800/EM2820/2840 USB video capture devices - - Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> - Markus Rechberger <mrechberger@gmail.com> - Mauro Carvalho Chehab <mchehab@infradead.org> - Sascha Sommer <saschasommer@freenet.de> - - 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 <linux/init.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/vmalloc.h> -#include <sound/ac97_codec.h> -#include <media/v4l2-common.h> - -#include "em28xx.h" - -/* #define ENABLE_DEBUG_ISOC_FRAMES */ - -static unsigned int core_debug; -module_param(core_debug, int, 0644); -MODULE_PARM_DESC(core_debug, "enable debug messages [core]"); - -#define em28xx_coredbg(fmt, arg...) do {\ - if (core_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __func__ , ##arg); } while (0) - -static unsigned int reg_debug; -module_param(reg_debug, int, 0644); -MODULE_PARM_DESC(reg_debug, "enable debug messages [URB reg]"); - -#define em28xx_regdbg(fmt, arg...) do {\ - if (reg_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __func__ , ##arg); } while (0) - -static int alt; -module_param(alt, int, 0644); -MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); - -static unsigned int disable_vbi; -module_param(disable_vbi, int, 0644); -MODULE_PARM_DESC(disable_vbi, "disable vbi support"); - -/* FIXME */ -#define em28xx_isocdbg(fmt, arg...) do {\ - if (core_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __func__ , ##arg); } while (0) - -/* - * em28xx_read_reg_req() - * reads data from the usb device specifying bRequest - */ -int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, - char *buf, int len) -{ - int ret; - int pipe = usb_rcvctrlpipe(dev->udev, 0); - - if (dev->state & DEV_DISCONNECTED) - return -ENODEV; - - if (len > URB_MAX_CTRL_SIZE) - return -EINVAL; - - if (reg_debug) { - printk(KERN_DEBUG "(pipe 0x%08x): " - "IN: %02x %02x %02x %02x %02x %02x %02x %02x ", - pipe, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - req, 0, 0, - reg & 0xff, reg >> 8, - len & 0xff, len >> 8); - } - - mutex_lock(&dev->ctrl_urb_lock); - ret = usb_control_msg(dev->udev, pipe, req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0000, reg, dev->urb_buf, len, HZ); - if (ret < 0) { - if (reg_debug) - printk(" failed!\n"); - mutex_unlock(&dev->ctrl_urb_lock); - return ret; - } - - if (len) - memcpy(buf, dev->urb_buf, len); - - mutex_unlock(&dev->ctrl_urb_lock); - - if (reg_debug) { - int byte; - - printk("<<<"); - for (byte = 0; byte < len; byte++) - printk(" %02x", (unsigned char)buf[byte]); - printk("\n"); - } - - return ret; -} - -/* - * em28xx_read_reg_req() - * reads data from the usb device specifying bRequest - */ -int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg) -{ - int ret; - u8 val; - - ret = em28xx_read_reg_req_len(dev, req, reg, &val, 1); - if (ret < 0) - return ret; - - return val; -} - -int em28xx_read_reg(struct em28xx *dev, u16 reg) -{ - return em28xx_read_reg_req(dev, USB_REQ_GET_STATUS, reg); -} -EXPORT_SYMBOL_GPL(em28xx_read_reg); - -/* - * em28xx_write_regs_req() - * sends data to the usb device, specifying bRequest - */ -int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, - int len) -{ - int ret; - int pipe = usb_sndctrlpipe(dev->udev, 0); - - if (dev->state & DEV_DISCONNECTED) - return -ENODEV; - - if ((len < 1) || (len > URB_MAX_CTRL_SIZE)) - return -EINVAL; - - if (reg_debug) { - int byte; - - printk(KERN_DEBUG "(pipe 0x%08x): " - "OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>", - pipe, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - req, 0, 0, - reg & 0xff, reg >> 8, - len & 0xff, len >> 8); - - for (byte = 0; byte < len; byte++) - printk(" %02x", (unsigned char)buf[byte]); - printk("\n"); - } - - mutex_lock(&dev->ctrl_urb_lock); - memcpy(dev->urb_buf, buf, len); - ret = usb_control_msg(dev->udev, pipe, req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0000, reg, dev->urb_buf, len, HZ); - mutex_unlock(&dev->ctrl_urb_lock); - - if (dev->wait_after_write) - msleep(dev->wait_after_write); - - return ret; -} - -int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len) -{ - int rc; - - rc = em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len); - - /* Stores GPO/GPIO values at the cache, if changed - Only write values should be stored, since input on a GPIO - register will return the input bits. - Not sure what happens on reading GPO register. - */ - if (rc >= 0) { - if (reg == dev->reg_gpo_num) - dev->reg_gpo = buf[0]; - else if (reg == dev->reg_gpio_num) - dev->reg_gpio = buf[0]; - } - - return rc; -} -EXPORT_SYMBOL_GPL(em28xx_write_regs); - -/* Write a single register */ -int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val) -{ - return em28xx_write_regs(dev, reg, &val, 1); -} -EXPORT_SYMBOL_GPL(em28xx_write_reg); - -/* - * em28xx_write_reg_bits() - * sets only some bits (specified by bitmask) of a register, by first reading - * the actual value - */ -int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, - u8 bitmask) -{ - int oldval; - u8 newval; - - /* Uses cache for gpo/gpio registers */ - if (reg == dev->reg_gpo_num) - oldval = dev->reg_gpo; - else if (reg == dev->reg_gpio_num) - oldval = dev->reg_gpio; - else - oldval = em28xx_read_reg(dev, reg); - - if (oldval < 0) - return oldval; - - newval = (((u8) oldval) & ~bitmask) | (val & bitmask); - - return em28xx_write_regs(dev, reg, &newval, 1); -} -EXPORT_SYMBOL_GPL(em28xx_write_reg_bits); - -/* - * em28xx_is_ac97_ready() - * Checks if ac97 is ready - */ -static int em28xx_is_ac97_ready(struct em28xx *dev) -{ - int ret, i; - - /* Wait up to 50 ms for AC97 command to complete */ - for (i = 0; i < 10; i++, msleep(5)) { - ret = em28xx_read_reg(dev, EM28XX_R43_AC97BUSY); - if (ret < 0) - return ret; - - if (!(ret & 0x01)) - return 0; - } - - em28xx_warn("AC97 command still being executed: not handled properly!\n"); - return -EBUSY; -} - -/* - * em28xx_read_ac97() - * write a 16 bit value to the specified AC97 address (LSB first!) - */ -int em28xx_read_ac97(struct em28xx *dev, u8 reg) -{ - int ret; - u8 addr = (reg & 0x7f) | 0x80; - u16 val; - - ret = em28xx_is_ac97_ready(dev); - if (ret < 0) - return ret; - - ret = em28xx_write_regs(dev, EM28XX_R42_AC97ADDR, &addr, 1); - if (ret < 0) - return ret; - - ret = dev->em28xx_read_reg_req_len(dev, 0, EM28XX_R40_AC97LSB, - (u8 *)&val, sizeof(val)); - - if (ret < 0) - return ret; - return le16_to_cpu(val); -} -EXPORT_SYMBOL_GPL(em28xx_read_ac97); - -/* - * em28xx_write_ac97() - * write a 16 bit value to the specified AC97 address (LSB first!) - */ -int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val) -{ - int ret; - u8 addr = reg & 0x7f; - __le16 value; - - value = cpu_to_le16(val); - - ret = em28xx_is_ac97_ready(dev); - if (ret < 0) - return ret; - - ret = em28xx_write_regs(dev, EM28XX_R40_AC97LSB, (u8 *) &value, 2); - if (ret < 0) - return ret; - - ret = em28xx_write_regs(dev, EM28XX_R42_AC97ADDR, &addr, 1); - if (ret < 0) - return ret; - - return 0; -} -EXPORT_SYMBOL_GPL(em28xx_write_ac97); - -struct em28xx_vol_itable { - enum em28xx_amux mux; - u8 reg; -}; - -static struct em28xx_vol_itable inputs[] = { - { EM28XX_AMUX_VIDEO, AC97_VIDEO }, - { EM28XX_AMUX_LINE_IN, AC97_LINE }, - { EM28XX_AMUX_PHONE, AC97_PHONE }, - { EM28XX_AMUX_MIC, AC97_MIC }, - { EM28XX_AMUX_CD, AC97_CD }, - { EM28XX_AMUX_AUX, AC97_AUX }, - { EM28XX_AMUX_PCM_OUT, AC97_PCM }, -}; - -static int set_ac97_input(struct em28xx *dev) -{ - int ret, i; - enum em28xx_amux amux = dev->ctl_ainput; - - /* EM28XX_AMUX_VIDEO2 is a special case used to indicate that - em28xx should point to LINE IN, while AC97 should use VIDEO - */ - if (amux == EM28XX_AMUX_VIDEO2) - amux = EM28XX_AMUX_VIDEO; - - /* Mute all entres but the one that were selected */ - for (i = 0; i < ARRAY_SIZE(inputs); i++) { - if (amux == inputs[i].mux) - ret = em28xx_write_ac97(dev, inputs[i].reg, 0x0808); - else - ret = em28xx_write_ac97(dev, inputs[i].reg, 0x8000); - - if (ret < 0) - em28xx_warn("couldn't setup AC97 register %d\n", - inputs[i].reg); - } - return 0; -} - -static int em28xx_set_audio_source(struct em28xx *dev) -{ - int ret; - u8 input; - - if (dev->board.is_em2800) { - if (dev->ctl_ainput == EM28XX_AMUX_VIDEO) - input = EM2800_AUDIO_SRC_TUNER; - else - input = EM2800_AUDIO_SRC_LINE; - - ret = em28xx_write_regs(dev, EM2800_R08_AUDIOSRC, &input, 1); - if (ret < 0) - return ret; - } - - if (dev->board.has_msp34xx) - input = EM28XX_AUDIO_SRC_TUNER; - else { - switch (dev->ctl_ainput) { - case EM28XX_AMUX_VIDEO: - input = EM28XX_AUDIO_SRC_TUNER; - break; - default: - input = EM28XX_AUDIO_SRC_LINE; - break; - } - } - - if (dev->board.mute_gpio && dev->mute) - em28xx_gpio_set(dev, dev->board.mute_gpio); - else - em28xx_gpio_set(dev, INPUT(dev->ctl_input)->gpio); - - ret = em28xx_write_reg_bits(dev, EM28XX_R0E_AUDIOSRC, input, 0xc0); - if (ret < 0) - return ret; - msleep(5); - - switch (dev->audio_mode.ac97) { - case EM28XX_NO_AC97: - break; - default: - ret = set_ac97_input(dev); - } - - return ret; -} - -struct em28xx_vol_otable { - enum em28xx_aout mux; - u8 reg; -}; - -static const struct em28xx_vol_otable outputs[] = { - { EM28XX_AOUT_MASTER, AC97_MASTER }, - { EM28XX_AOUT_LINE, AC97_HEADPHONE }, - { EM28XX_AOUT_MONO, AC97_MASTER_MONO }, - { EM28XX_AOUT_LFE, AC97_CENTER_LFE_MASTER }, - { EM28XX_AOUT_SURR, AC97_SURROUND_MASTER }, -}; - -int em28xx_audio_analog_set(struct em28xx *dev) -{ - int ret, i; - u8 xclk; - - if (!dev->audio_mode.has_audio) - return 0; - - /* It is assumed that all devices use master volume for output. - It would be possible to use also line output. - */ - if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { - /* Mute all outputs */ - for (i = 0; i < ARRAY_SIZE(outputs); i++) { - ret = em28xx_write_ac97(dev, outputs[i].reg, 0x8000); - if (ret < 0) - em28xx_warn("couldn't setup AC97 register %d\n", - outputs[i].reg); - } - } - - xclk = dev->board.xclk & 0x7f; - if (!dev->mute) - xclk |= EM28XX_XCLK_AUDIO_UNMUTE; - - ret = em28xx_write_reg(dev, EM28XX_R0F_XCLK, xclk); - if (ret < 0) - return ret; - msleep(10); - - /* Selects the proper audio input */ - ret = em28xx_set_audio_source(dev); - - /* Sets volume */ - if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { - int vol; - - em28xx_write_ac97(dev, AC97_POWERDOWN, 0x4200); - em28xx_write_ac97(dev, AC97_EXTENDED_STATUS, 0x0031); - em28xx_write_ac97(dev, AC97_PCM_LR_ADC_RATE, 0xbb80); - - /* LSB: left channel - both channels with the same level */ - vol = (0x1f - dev->volume) | ((0x1f - dev->volume) << 8); - - /* Mute device, if needed */ - if (dev->mute) - vol |= 0x8000; - - /* Sets volume */ - for (i = 0; i < ARRAY_SIZE(outputs); i++) { - if (dev->ctl_aoutput & outputs[i].mux) - ret = em28xx_write_ac97(dev, outputs[i].reg, - vol); - if (ret < 0) - em28xx_warn("couldn't setup AC97 register %d\n", - outputs[i].reg); - } - - if (dev->ctl_aoutput & EM28XX_AOUT_PCM_IN) { - int sel = ac97_return_record_select(dev->ctl_aoutput); - - /* Use the same input for both left and right - channels */ - sel |= (sel << 8); - - em28xx_write_ac97(dev, AC97_REC_SEL, sel); - } - } - - return ret; -} -EXPORT_SYMBOL_GPL(em28xx_audio_analog_set); - -int em28xx_audio_setup(struct em28xx *dev) -{ - int vid1, vid2, feat, cfg; - u32 vid; - - if (dev->chip_id == CHIP_ID_EM2870 || dev->chip_id == CHIP_ID_EM2874 - || dev->chip_id == CHIP_ID_EM28174) { - /* Digital only device - don't load any alsa module */ - dev->audio_mode.has_audio = false; - dev->has_audio_class = false; - dev->has_alsa_audio = false; - return 0; - } - - dev->audio_mode.has_audio = true; - - /* See how this device is configured */ - cfg = em28xx_read_reg(dev, EM28XX_R00_CHIPCFG); - em28xx_info("Config register raw data: 0x%02x\n", cfg); - if (cfg < 0) { - /* Register read error? */ - cfg = EM28XX_CHIPCFG_AC97; /* Be conservative */ - } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == 0x00) { - /* The device doesn't have vendor audio at all */ - dev->has_alsa_audio = false; - dev->audio_mode.has_audio = false; - return 0; - } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == - EM28XX_CHIPCFG_I2S_3_SAMPRATES) { - em28xx_info("I2S Audio (3 sample rates)\n"); - dev->audio_mode.i2s_3rates = 1; - } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == - EM28XX_CHIPCFG_I2S_5_SAMPRATES) { - em28xx_info("I2S Audio (5 sample rates)\n"); - dev->audio_mode.i2s_5rates = 1; - } - - if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) != EM28XX_CHIPCFG_AC97) { - /* Skip the code that does AC97 vendor detection */ - dev->audio_mode.ac97 = EM28XX_NO_AC97; - goto init_audio; - } - - dev->audio_mode.ac97 = EM28XX_AC97_OTHER; - - vid1 = em28xx_read_ac97(dev, AC97_VENDOR_ID1); - if (vid1 < 0) { - /* - * Device likely doesn't support AC97 - * Note: (some) em2800 devices without eeprom reports 0x91 on - * CHIPCFG register, even not having an AC97 chip - */ - em28xx_warn("AC97 chip type couldn't be determined\n"); - dev->audio_mode.ac97 = EM28XX_NO_AC97; - dev->has_alsa_audio = false; - dev->audio_mode.has_audio = false; - goto init_audio; - } - - vid2 = em28xx_read_ac97(dev, AC97_VENDOR_ID2); - if (vid2 < 0) - goto init_audio; - - vid = vid1 << 16 | vid2; - - dev->audio_mode.ac97_vendor_id = vid; - em28xx_warn("AC97 vendor ID = 0x%08x\n", vid); - - feat = em28xx_read_ac97(dev, AC97_RESET); - if (feat < 0) - goto init_audio; - - dev->audio_mode.ac97_feat = feat; - em28xx_warn("AC97 features = 0x%04x\n", feat); - - /* Try to identify what audio processor we have */ - if (((vid == 0xffffffff) || (vid == 0x83847650)) && (feat == 0x6a90)) - dev->audio_mode.ac97 = EM28XX_AC97_EM202; - else if ((vid >> 8) == 0x838476) - dev->audio_mode.ac97 = EM28XX_AC97_SIGMATEL; - -init_audio: - /* Reports detected AC97 processor */ - switch (dev->audio_mode.ac97) { - case EM28XX_NO_AC97: - em28xx_info("No AC97 audio processor\n"); - break; - case EM28XX_AC97_EM202: - em28xx_info("Empia 202 AC97 audio processor detected\n"); - break; - case EM28XX_AC97_SIGMATEL: - em28xx_info("Sigmatel audio processor detected(stac 97%02x)\n", - dev->audio_mode.ac97_vendor_id & 0xff); - break; - case EM28XX_AC97_OTHER: - em28xx_warn("Unknown AC97 audio processor detected!\n"); - break; - default: - break; - } - - return em28xx_audio_analog_set(dev); -} -EXPORT_SYMBOL_GPL(em28xx_audio_setup); - -int em28xx_colorlevels_set_default(struct em28xx *dev) -{ - em28xx_write_reg(dev, EM28XX_R20_YGAIN, 0x10); /* contrast */ - em28xx_write_reg(dev, EM28XX_R21_YOFFSET, 0x00); /* brightness */ - em28xx_write_reg(dev, EM28XX_R22_UVGAIN, 0x10); /* saturation */ - em28xx_write_reg(dev, EM28XX_R23_UOFFSET, 0x00); - em28xx_write_reg(dev, EM28XX_R24_VOFFSET, 0x00); - em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, 0x00); - - em28xx_write_reg(dev, EM28XX_R14_GAMMA, 0x20); - em28xx_write_reg(dev, EM28XX_R15_RGAIN, 0x20); - em28xx_write_reg(dev, EM28XX_R16_GGAIN, 0x20); - em28xx_write_reg(dev, EM28XX_R17_BGAIN, 0x20); - em28xx_write_reg(dev, EM28XX_R18_ROFFSET, 0x00); - em28xx_write_reg(dev, EM28XX_R19_GOFFSET, 0x00); - return em28xx_write_reg(dev, EM28XX_R1A_BOFFSET, 0x00); -} - -int em28xx_capture_start(struct em28xx *dev, int start) -{ - int rc; - - if (dev->chip_id == CHIP_ID_EM2874 || - dev->chip_id == CHIP_ID_EM2884 || - dev->chip_id == CHIP_ID_EM28174) { - /* The Transport Stream Enable Register moved in em2874 */ - if (!start) { - rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE, - 0x00, - EM2874_TS1_CAPTURE_ENABLE); - return rc; - } - - /* Enable Transport Stream */ - rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE, - EM2874_TS1_CAPTURE_ENABLE, - EM2874_TS1_CAPTURE_ENABLE); - return rc; - } - - - /* FIXME: which is the best order? */ - /* video registers are sampled by VREF */ - rc = em28xx_write_reg_bits(dev, EM28XX_R0C_USBSUSP, - start ? 0x10 : 0x00, 0x10); - if (rc < 0) - return rc; - - if (!start) { - /* disable video capture */ - rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x27); - return rc; - } - - if (dev->board.is_webcam) - rc = em28xx_write_reg(dev, 0x13, 0x0c); - - /* enable video capture */ - rc = em28xx_write_reg(dev, 0x48, 0x00); - - if (dev->mode == EM28XX_ANALOG_MODE) - rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x67); - else - rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37); - - msleep(6); - - return rc; -} - -int em28xx_vbi_supported(struct em28xx *dev) -{ - /* Modprobe option to manually disable */ - if (disable_vbi == 1) - return 0; - - if (dev->chip_id == CHIP_ID_EM2860 || - dev->chip_id == CHIP_ID_EM2883) - return 1; - - /* Version of em28xx that does not support VBI */ - return 0; -} - -int em28xx_set_outfmt(struct em28xx *dev) -{ - int ret; - u8 vinctrl; - - ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT, - dev->format->reg | 0x20, 0xff); - if (ret < 0) - return ret; - - ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode); - if (ret < 0) - return ret; - - vinctrl = dev->vinctl; - if (em28xx_vbi_supported(dev) == 1) { - vinctrl |= EM28XX_VINCTRL_VBI_RAW; - em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00); - em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, dev->vbi_width/4); - em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, dev->vbi_height); - if (dev->norm & V4L2_STD_525_60) { - /* NTSC */ - em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09); - } else if (dev->norm & V4L2_STD_625_50) { - /* PAL */ - em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07); - } - } - - return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl); -} - -static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, - u8 ymin, u8 ymax) -{ - em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n", - xmin, ymin, xmax, ymax); - - em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1); - em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1); - em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1); - return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1); -} - -static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart, - u16 width, u16 height) -{ - u8 cwidth = width; - u8 cheight = height; - u8 overflow = (height >> 7 & 0x02) | (width >> 8 & 0x01); - - em28xx_coredbg("em28xx Area Set: (%d,%d)\n", - (width | (overflow & 2) << 7), - (height | (overflow & 1) << 8)); - - em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1); - em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1); - em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1); - em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1); - return em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1); -} - -static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) -{ - u8 mode; - /* the em2800 scaler only supports scaling down to 50% */ - - if (dev->board.is_em2800) { - mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00); - } else { - u8 buf[2]; - - buf[0] = h; - buf[1] = h >> 8; - em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2); - - buf[0] = v; - buf[1] = v >> 8; - em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2); - /* it seems that both H and V scalers must be active - to work correctly */ - mode = (h || v) ? 0x30 : 0x00; - } - return em28xx_write_reg_bits(dev, EM28XX_R26_COMPR, mode, 0x30); -} - -/* FIXME: this only function read values from dev */ -int em28xx_resolution_set(struct em28xx *dev) -{ - int width, height; - width = norm_maxw(dev); - height = norm_maxh(dev); - - /* Properly setup VBI */ - dev->vbi_width = 720; - if (dev->norm & V4L2_STD_525_60) - dev->vbi_height = 12; - else - dev->vbi_height = 18; - - em28xx_set_outfmt(dev); - - em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); - - /* If we don't set the start position to 2 in VBI mode, we end up - with line 20/21 being YUYV encoded instead of being in 8-bit - greyscale. The core of the issue is that line 21 (and line 23 for - PAL WSS) are inside of active video region, and as a result they - get the pixelformatting associated with that area. So by cropping - it out, we end up with the same format as the rest of the VBI - region */ - if (em28xx_vbi_supported(dev) == 1) - em28xx_capture_area_set(dev, 0, 2, width >> 2, height >> 2); - else - em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); - - return em28xx_scaler_set(dev, dev->hscale, dev->vscale); -} - -int em28xx_set_alternate(struct em28xx *dev) -{ - int errCode, prev_alt = dev->alt; - int i; - unsigned int min_pkt_size = dev->width * 2 + 4; - - /* - * alt = 0 is used only for control messages, so, only values - * greater than 0 can be used for streaming. - */ - if (alt && alt < dev->num_alt) { - em28xx_coredbg("alternate forced to %d\n", dev->alt); - dev->alt = alt; - goto set_alt; - } - - /* When image size is bigger than a certain value, - the frame size should be increased, otherwise, only - green screen will be received. - */ - if (dev->width * 2 * dev->height > 720 * 240 * 2) - min_pkt_size *= 2; - - for (i = 0; i < dev->num_alt; i++) { - /* stop when the selected alt setting offers enough bandwidth */ - if (dev->alt_max_pkt_size[i] >= min_pkt_size) { - dev->alt = i; - break; - /* otherwise make sure that we end up with the maximum bandwidth - because the min_pkt_size equation might be wrong... - */ - } else if (dev->alt_max_pkt_size[i] > - dev->alt_max_pkt_size[dev->alt]) - dev->alt = i; - } - -set_alt: - if (dev->alt != prev_alt) { - em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n", - min_pkt_size, dev->alt); - dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt]; - em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n", - dev->alt, dev->max_pkt_size); - errCode = usb_set_interface(dev->udev, 0, dev->alt); - if (errCode < 0) { - em28xx_errdev("cannot change alternate number to %d (error=%i)\n", - dev->alt, errCode); - return errCode; - } - } - return 0; -} - -int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio) -{ - int rc = 0; - - if (!gpio) - return rc; - - if (dev->mode != EM28XX_SUSPEND) { - em28xx_write_reg(dev, 0x48, 0x00); - if (dev->mode == EM28XX_ANALOG_MODE) - em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x67); - else - em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37); - msleep(6); - } - - /* Send GPIO reset sequences specified at board entry */ - while (gpio->sleep >= 0) { - if (gpio->reg >= 0) { - rc = em28xx_write_reg_bits(dev, - gpio->reg, - gpio->val, - gpio->mask); - if (rc < 0) - return rc; - } - if (gpio->sleep > 0) - msleep(gpio->sleep); - - gpio++; - } - return rc; -} -EXPORT_SYMBOL_GPL(em28xx_gpio_set); - -int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode) -{ - if (dev->mode == set_mode) - return 0; - - if (set_mode == EM28XX_SUSPEND) { - dev->mode = set_mode; - - /* FIXME: add suspend support for ac97 */ - - return em28xx_gpio_set(dev, dev->board.suspend_gpio); - } - - dev->mode = set_mode; - - if (dev->mode == EM28XX_DIGITAL_MODE) - return em28xx_gpio_set(dev, dev->board.dvb_gpio); - else - return em28xx_gpio_set(dev, INPUT(dev->ctl_input)->gpio); -} -EXPORT_SYMBOL_GPL(em28xx_set_mode); - -/* ------------------------------------------------------------------ - URB control - ------------------------------------------------------------------*/ - -/* - * IRQ callback, called by URB callback - */ -static void em28xx_irq_callback(struct urb *urb) -{ - struct em28xx *dev = urb->context; - int i; - - switch (urb->status) { - case 0: /* success */ - case -ETIMEDOUT: /* NAK */ - break; - case -ECONNRESET: /* kill */ - case -ENOENT: - case -ESHUTDOWN: - return; - default: /* error */ - em28xx_isocdbg("urb completition error %d.\n", urb->status); - break; - } - - /* Copy data from URB */ - spin_lock(&dev->slock); - dev->isoc_ctl.isoc_copy(dev, urb); - spin_unlock(&dev->slock); - - /* Reset urb buffers */ - for (i = 0; i < urb->number_of_packets; i++) { - urb->iso_frame_desc[i].status = 0; - urb->iso_frame_desc[i].actual_length = 0; - } - urb->status = 0; - - urb->status = usb_submit_urb(urb, GFP_ATOMIC); - if (urb->status) { - em28xx_isocdbg("urb resubmit failed (error=%i)\n", - urb->status); - } -} - -/* - * Stop and Deallocate URBs - */ -void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode) -{ - struct urb *urb; - struct em28xx_usb_isoc_bufs *isoc_bufs; - int i; - - em28xx_isocdbg("em28xx: called em28xx_uninit_isoc in mode %d\n", mode); - - if (mode == EM28XX_DIGITAL_MODE) - isoc_bufs = &dev->isoc_ctl.digital_bufs; - else - isoc_bufs = &dev->isoc_ctl.analog_bufs; - - for (i = 0; i < isoc_bufs->num_bufs; i++) { - urb = isoc_bufs->urb[i]; - if (urb) { - if (!irqs_disabled()) - usb_kill_urb(urb); - else - usb_unlink_urb(urb); - - if (isoc_bufs->transfer_buffer[i]) { - usb_free_coherent(dev->udev, - urb->transfer_buffer_length, - isoc_bufs->transfer_buffer[i], - urb->transfer_dma); - } - usb_free_urb(urb); - isoc_bufs->urb[i] = NULL; - } - isoc_bufs->transfer_buffer[i] = NULL; - } - - kfree(isoc_bufs->urb); - kfree(isoc_bufs->transfer_buffer); - - isoc_bufs->urb = NULL; - isoc_bufs->transfer_buffer = NULL; - isoc_bufs->num_bufs = 0; - - em28xx_capture_start(dev, 0); -} -EXPORT_SYMBOL_GPL(em28xx_uninit_isoc); - -/* - * Stop URBs - */ -void em28xx_stop_urbs(struct em28xx *dev) -{ - int i; - struct urb *urb; - struct em28xx_usb_isoc_bufs *isoc_bufs = &dev->isoc_ctl.digital_bufs; - - em28xx_isocdbg("em28xx: called em28xx_stop_urbs\n"); - - for (i = 0; i < isoc_bufs->num_bufs; i++) { - urb = isoc_bufs->urb[i]; - if (urb) { - if (!irqs_disabled()) - usb_kill_urb(urb); - else - usb_unlink_urb(urb); - } - } - - em28xx_capture_start(dev, 0); -} -EXPORT_SYMBOL_GPL(em28xx_stop_urbs); - -/* - * Allocate URBs - */ -int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode, - int max_packets, int num_bufs, int max_pkt_size) -{ - struct em28xx_usb_isoc_bufs *isoc_bufs; - int i; - int sb_size, pipe; - struct urb *urb; - int j, k; - - em28xx_isocdbg("em28xx: called em28xx_alloc_isoc in mode %d\n", mode); - - if (mode == EM28XX_DIGITAL_MODE) - isoc_bufs = &dev->isoc_ctl.digital_bufs; - else - isoc_bufs = &dev->isoc_ctl.analog_bufs; - - /* De-allocates all pending stuff */ - em28xx_uninit_isoc(dev, mode); - - isoc_bufs->num_bufs = num_bufs; - - isoc_bufs->urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); - if (!isoc_bufs->urb) { - em28xx_errdev("cannot alloc memory for usb buffers\n"); - return -ENOMEM; - } - - isoc_bufs->transfer_buffer = kzalloc(sizeof(void *)*num_bufs, - GFP_KERNEL); - if (!isoc_bufs->transfer_buffer) { - em28xx_errdev("cannot allocate memory for usb transfer\n"); - kfree(isoc_bufs->urb); - return -ENOMEM; - } - - isoc_bufs->max_pkt_size = max_pkt_size; - isoc_bufs->num_packets = max_packets; - dev->isoc_ctl.vid_buf = NULL; - dev->isoc_ctl.vbi_buf = NULL; - - sb_size = isoc_bufs->num_packets * isoc_bufs->max_pkt_size; - - /* allocate urbs and transfer buffers */ - for (i = 0; i < isoc_bufs->num_bufs; i++) { - urb = usb_alloc_urb(isoc_bufs->num_packets, GFP_KERNEL); - if (!urb) { - em28xx_err("cannot alloc isoc_ctl.urb %i\n", i); - em28xx_uninit_isoc(dev, mode); - return -ENOMEM; - } - isoc_bufs->urb[i] = urb; - - isoc_bufs->transfer_buffer[i] = usb_alloc_coherent(dev->udev, - sb_size, GFP_KERNEL, &urb->transfer_dma); - if (!isoc_bufs->transfer_buffer[i]) { - em28xx_err("unable to allocate %i bytes for transfer" - " buffer %i%s\n", - sb_size, i, - in_interrupt() ? " while in int" : ""); - em28xx_uninit_isoc(dev, mode); - return -ENOMEM; - } - memset(isoc_bufs->transfer_buffer[i], 0, sb_size); - - /* FIXME: this is a hack - should be - 'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK' - should also be using 'desc.bInterval' - */ - pipe = usb_rcvisocpipe(dev->udev, - mode == EM28XX_ANALOG_MODE ? - EM28XX_EP_ANALOG : EM28XX_EP_DIGITAL); - - usb_fill_int_urb(urb, dev->udev, pipe, - isoc_bufs->transfer_buffer[i], sb_size, - em28xx_irq_callback, dev, 1); - - urb->number_of_packets = isoc_bufs->num_packets; - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; - - k = 0; - for (j = 0; j < isoc_bufs->num_packets; j++) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = - isoc_bufs->max_pkt_size; - k += isoc_bufs->max_pkt_size; - } - } - - return 0; -} -EXPORT_SYMBOL_GPL(em28xx_alloc_isoc); - -/* - * Allocate URBs and start IRQ - */ -int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode, - int max_packets, int num_bufs, int max_pkt_size, - int (*isoc_copy) (struct em28xx *dev, struct urb *urb)) -{ - struct em28xx_dmaqueue *dma_q = &dev->vidq; - struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq; - struct em28xx_usb_isoc_bufs *isoc_bufs; - int i; - int rc; - int alloc; - - em28xx_isocdbg("em28xx: called em28xx_init_isoc in mode %d\n", mode); - - dev->isoc_ctl.isoc_copy = isoc_copy; - - if (mode == EM28XX_DIGITAL_MODE) { - isoc_bufs = &dev->isoc_ctl.digital_bufs; - /* no need to free/alloc isoc buffers in digital mode */ - alloc = 0; - } else { - isoc_bufs = &dev->isoc_ctl.analog_bufs; - alloc = 1; - } - - if (alloc) { - rc = em28xx_alloc_isoc(dev, mode, max_packets, - num_bufs, max_pkt_size); - if (rc) - return rc; - } - - init_waitqueue_head(&dma_q->wq); - init_waitqueue_head(&vbi_dma_q->wq); - - em28xx_capture_start(dev, 1); - - /* submit urbs and enables IRQ */ - for (i = 0; i < isoc_bufs->num_bufs; i++) { - rc = usb_submit_urb(isoc_bufs->urb[i], GFP_ATOMIC); - if (rc) { - em28xx_err("submit of urb %i failed (error=%i)\n", i, - rc); - em28xx_uninit_isoc(dev, mode); - return rc; - } - } - - return 0; -} -EXPORT_SYMBOL_GPL(em28xx_init_isoc); - -/* - * em28xx_wake_i2c() - * configure i2c attached devices - */ -void em28xx_wake_i2c(struct em28xx *dev) -{ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0); - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, - INPUT(dev->ctl_input)->vmux, 0, 0); - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); -} - -/* - * Device control list - */ - -static LIST_HEAD(em28xx_devlist); -static DEFINE_MUTEX(em28xx_devlist_mutex); - -/* - * Extension interface - */ - -static LIST_HEAD(em28xx_extension_devlist); - -int em28xx_register_extension(struct em28xx_ops *ops) -{ - struct em28xx *dev = NULL; - - mutex_lock(&em28xx_devlist_mutex); - list_add_tail(&ops->next, &em28xx_extension_devlist); - list_for_each_entry(dev, &em28xx_devlist, devlist) { - ops->init(dev); - } - mutex_unlock(&em28xx_devlist_mutex); - printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); - return 0; -} -EXPORT_SYMBOL(em28xx_register_extension); - -void em28xx_unregister_extension(struct em28xx_ops *ops) -{ - struct em28xx *dev = NULL; - - mutex_lock(&em28xx_devlist_mutex); - list_for_each_entry(dev, &em28xx_devlist, devlist) { - ops->fini(dev); - } - list_del(&ops->next); - mutex_unlock(&em28xx_devlist_mutex); - printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); -} -EXPORT_SYMBOL(em28xx_unregister_extension); - -void em28xx_init_extension(struct em28xx *dev) -{ - const struct em28xx_ops *ops = NULL; - - mutex_lock(&em28xx_devlist_mutex); - list_add_tail(&dev->devlist, &em28xx_devlist); - list_for_each_entry(ops, &em28xx_extension_devlist, next) { - if (ops->init) - ops->init(dev); - } - mutex_unlock(&em28xx_devlist_mutex); -} - -void em28xx_close_extension(struct em28xx *dev) -{ - const struct em28xx_ops *ops = NULL; - - mutex_lock(&em28xx_devlist_mutex); - list_for_each_entry(ops, &em28xx_extension_devlist, next) { - if (ops->fini) - ops->fini(dev); - } - list_del(&dev->devlist); - mutex_unlock(&em28xx_devlist_mutex); -} diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c deleted file mode 100644 index a16531f..0000000 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ /dev/null @@ -1,1197 +0,0 @@ -/* - DVB device driver for em28xx - - (c) 2008-2011 Mauro Carvalho Chehab <mchehab@infradead.org> - - (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com> - - Fixes for the driver to properly work with HVR-950 - - Fixes for the driver to properly work with Pinnacle PCTV HD Pro Stick - - Fixes for the driver to properly work with AMD ATI TV Wonder HD 600 - - (c) 2008 Aidan Thornton <makosoft@googlemail.com> - - Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by: - (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au> - (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] - - 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. - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/usb.h> - -#include "em28xx.h" -#include <media/v4l2-common.h> -#include <media/videobuf-vmalloc.h> -#include <media/tuner.h> -#include "tuner-simple.h" - -#include "lgdt330x.h" -#include "lgdt3305.h" -#include "zl10353.h" -#include "s5h1409.h" -#include "mt352.h" -#include "mt352_priv.h" /* FIXME */ -#include "tda1002x.h" -#include "tda18271.h" -#include "s921.h" -#include "drxd.h" -#include "cxd2820r.h" -#include "tda18271c2dd.h" -#include "drxk.h" -#include "tda10071.h" -#include "a8293.h" -#include "qt1010.h" - -MODULE_DESCRIPTION("driver for em28xx based DVB cards"); -MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); -MODULE_LICENSE("GPL"); - -static unsigned int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "enable debug messages [dvb]"); - -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - -#define dprintk(level, fmt, arg...) do { \ -if (debug >= level) \ - printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \ -} while (0) - -struct em28xx_dvb { - struct dvb_frontend *fe[2]; - - /* feed count management */ - struct mutex lock; - int nfeeds; - - /* general boilerplate stuff */ - struct dvb_adapter adapter; - struct dvb_demux demux; - struct dmxdev dmxdev; - struct dmx_frontend fe_hw; - struct dmx_frontend fe_mem; - struct dvb_net net; - - /* Due to DRX-K - probably need changes */ - int (*gate_ctrl)(struct dvb_frontend *, int); - struct semaphore pll_mutex; - bool dont_attach_fe1; -}; - - -static inline void print_err_status(struct em28xx *dev, - int packet, int status) -{ - char *errmsg = "Unknown"; - - switch (status) { - case -ENOENT: - errmsg = "unlinked synchronuously"; - break; - case -ECONNRESET: - errmsg = "unlinked asynchronuously"; - break; - case -ENOSR: - errmsg = "Buffer error (overrun)"; - break; - case -EPIPE: - errmsg = "Stalled (device not responding)"; - break; - case -EOVERFLOW: - errmsg = "Babble (bad cable?)"; - break; - case -EPROTO: - errmsg = "Bit-stuff error (bad cable?)"; - break; - case -EILSEQ: - errmsg = "CRC/Timeout (could be anything)"; - break; - case -ETIME: - errmsg = "Device does not respond"; - break; - } - if (packet < 0) { - dprintk(1, "URB status %d [%s].\n", status, errmsg); - } else { - dprintk(1, "URB packet %d, status %d [%s].\n", - packet, status, errmsg); - } -} - -static inline int em28xx_dvb_isoc_copy(struct em28xx *dev, struct urb *urb) -{ - int i; - - if (!dev) - return 0; - - if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) - return 0; - - if (urb->status < 0) { - print_err_status(dev, -1, urb->status); - if (urb->status == -ENOENT) - return 0; - } - - for (i = 0; i < urb->number_of_packets; i++) { - int status = urb->iso_frame_desc[i].status; - - if (status < 0) { - print_err_status(dev, i, status); - if (urb->iso_frame_desc[i].status != -EPROTO) - continue; - } - - dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer + - urb->iso_frame_desc[i].offset, - urb->iso_frame_desc[i].actual_length); - } - - return 0; -} - -static int em28xx_start_streaming(struct em28xx_dvb *dvb) -{ - int rc; - struct em28xx *dev = dvb->adapter.priv; - int max_dvb_packet_size; - - usb_set_interface(dev->udev, 0, dev->dvb_alt); - rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); - if (rc < 0) - return rc; - - max_dvb_packet_size = dev->dvb_max_pkt_size; - if (max_dvb_packet_size < 0) - return max_dvb_packet_size; - dprintk(1, "Using %d buffers each with %d x %d bytes\n", - EM28XX_DVB_NUM_BUFS, - EM28XX_DVB_MAX_PACKETS, - max_dvb_packet_size); - - return em28xx_init_isoc(dev, EM28XX_DIGITAL_MODE, - EM28XX_DVB_MAX_PACKETS, EM28XX_DVB_NUM_BUFS, - max_dvb_packet_size, em28xx_dvb_isoc_copy); -} - -static int em28xx_stop_streaming(struct em28xx_dvb *dvb) -{ - struct em28xx *dev = dvb->adapter.priv; - - em28xx_stop_urbs(dev); - - em28xx_set_mode(dev, EM28XX_SUSPEND); - - return 0; -} - -static int em28xx_start_feed(struct dvb_demux_feed *feed) -{ - struct dvb_demux *demux = feed->demux; - struct em28xx_dvb *dvb = demux->priv; - int rc, ret; - - if (!demux->dmx.frontend) - return -EINVAL; - - mutex_lock(&dvb->lock); - dvb->nfeeds++; - rc = dvb->nfeeds; - - if (dvb->nfeeds == 1) { - ret = em28xx_start_streaming(dvb); - if (ret < 0) - rc = ret; - } - - mutex_unlock(&dvb->lock); - return rc; -} - -static int em28xx_stop_feed(struct dvb_demux_feed *feed) -{ - struct dvb_demux *demux = feed->demux; - struct em28xx_dvb *dvb = demux->priv; - int err = 0; - - mutex_lock(&dvb->lock); - dvb->nfeeds--; - - if (0 == dvb->nfeeds) - err = em28xx_stop_streaming(dvb); - - mutex_unlock(&dvb->lock); - return err; -} - - - -/* ------------------------------------------------------------------ */ -static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) -{ - struct em28xx *dev = fe->dvb->priv; - - if (acquire) - return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); - else - return em28xx_set_mode(dev, EM28XX_SUSPEND); -} - -/* ------------------------------------------------------------------ */ - -static struct lgdt330x_config em2880_lgdt3303_dev = { - .demod_address = 0x0e, - .demod_chip = LGDT3303, -}; - -static struct lgdt3305_config em2870_lgdt3304_dev = { - .i2c_addr = 0x0e, - .demod_chip = LGDT3304, - .spectral_inversion = 1, - .deny_i2c_rptr = 1, - .mpeg_mode = LGDT3305_MPEG_PARALLEL, - .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE, - .tpvalid_polarity = LGDT3305_TP_VALID_HIGH, - .vsb_if_khz = 3250, - .qam_if_khz = 4000, -}; - -static struct s921_config sharp_isdbt = { - .demod_address = 0x30 >> 1 -}; - -static struct zl10353_config em28xx_zl10353_with_xc3028 = { - .demod_address = (0x1e >> 1), - .no_tuner = 1, - .parallel_ts = 1, - .if2 = 45600, -}; - -static struct s5h1409_config em28xx_s5h1409_with_xc3028 = { - .demod_address = 0x32 >> 1, - .output_mode = S5H1409_PARALLEL_OUTPUT, - .gpio = S5H1409_GPIO_OFF, - .inversion = S5H1409_INVERSION_OFF, - .status_mode = S5H1409_DEMODLOCKING, - .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK -}; - -static struct tda18271_std_map kworld_a340_std_map = { - .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 0, - .if_lvl = 1, .rfagc_top = 0x37, }, - .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 1, - .if_lvl = 1, .rfagc_top = 0x37, }, -}; - -static struct tda18271_config kworld_a340_config = { - .std_map = &kworld_a340_std_map, -}; - -static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = { - .demod_address = (0x1e >> 1), - .no_tuner = 1, - .disable_i2c_gate_ctrl = 1, - .parallel_ts = 1, - .if2 = 45600, -}; - -static struct drxd_config em28xx_drxd = { - .demod_address = 0x70, - .demod_revision = 0xa2, - .pll_type = DRXD_PLL_NONE, - .clock = 12000, - .insert_rs_byte = 1, - .IF = 42800000, - .disable_i2c_gate_ctrl = 1, -}; - -static struct drxk_config terratec_h5_drxk = { - .adr = 0x29, - .single_master = 1, - .no_i2c_bridge = 1, - .microcode_name = "dvb-usb-terratec-h5-drxk.fw", - .qam_demod_parameter_count = 2, -}; - -static struct drxk_config hauppauge_930c_drxk = { - .adr = 0x29, - .single_master = 1, - .no_i2c_bridge = 1, - .microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw", - .chunk_size = 56, - .qam_demod_parameter_count = 2, -}; - -struct drxk_config terratec_htc_stick_drxk = { - .adr = 0x29, - .single_master = 1, - .no_i2c_bridge = 1, - .microcode_name = "dvb-usb-terratec-htc-stick-drxk.fw", - .chunk_size = 54, - .qam_demod_parameter_count = 2, - /* Required for the antenna_gpio to disable LNA. */ - .antenna_dvbt = true, - /* The windows driver uses the same. This will disable LNA. */ - .antenna_gpio = 0x6, -}; - -static struct drxk_config maxmedia_ub425_tc_drxk = { - .adr = 0x29, - .single_master = 1, - .no_i2c_bridge = 1, -}; - -static struct drxk_config pctv_520e_drxk = { - .adr = 0x29, - .single_master = 1, - .microcode_name = "dvb-demod-drxk-pctv.fw", - .qam_demod_parameter_count = 2, - .chunk_size = 58, - .antenna_dvbt = true, /* disable LNA */ - .antenna_gpio = (1 << 2), /* disable LNA */ -}; - -static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) -{ - struct em28xx_dvb *dvb = fe->sec_priv; - int status; - - if (!dvb) - return -EINVAL; - - if (enable) { - down(&dvb->pll_mutex); - status = dvb->gate_ctrl(fe, 1); - } else { - status = dvb->gate_ctrl(fe, 0); - up(&dvb->pll_mutex); - } - return status; -} - -static void hauppauge_hvr930c_init(struct em28xx *dev) -{ - int i; - - struct em28xx_reg_seq hauppauge_hvr930c_init[] = { - {EM2874_R80_GPIO, 0xff, 0xff, 0x65}, - {EM2874_R80_GPIO, 0xfb, 0xff, 0x32}, - {EM2874_R80_GPIO, 0xff, 0xff, 0xb8}, - { -1, -1, -1, -1}, - }; - struct em28xx_reg_seq hauppauge_hvr930c_end[] = { - {EM2874_R80_GPIO, 0xef, 0xff, 0x01}, - {EM2874_R80_GPIO, 0xaf, 0xff, 0x65}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x76}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x01}, - {EM2874_R80_GPIO, 0xcf, 0xff, 0x0b}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x40}, - - {EM2874_R80_GPIO, 0xcf, 0xff, 0x65}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x65}, - {EM2874_R80_GPIO, 0xcf, 0xff, 0x0b}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x65}, - - { -1, -1, -1, -1}, - }; - - struct { - unsigned char r[4]; - int len; - } regs[] = { - {{ 0x06, 0x02, 0x00, 0x31 }, 4}, - {{ 0x01, 0x02 }, 2}, - {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, - {{ 0x01, 0x00 }, 2}, - {{ 0x01, 0x00, 0xff, 0xaf }, 4}, - {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, - {{ 0x01, 0x00 }, 2}, - {{ 0x01, 0x00, 0x73, 0xaf }, 4}, - {{ 0x04, 0x00 }, 2}, - {{ 0x00, 0x04 }, 2}, - {{ 0x00, 0x04, 0x00, 0x0a }, 4}, - {{ 0x04, 0x14 }, 2}, - {{ 0x04, 0x14, 0x00, 0x00 }, 4}, - }; - - em28xx_gpio_set(dev, hauppauge_hvr930c_init); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); - msleep(10); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); - msleep(10); - - dev->i2c_client.addr = 0x82 >> 1; - - for (i = 0; i < ARRAY_SIZE(regs); i++) - i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len); - em28xx_gpio_set(dev, hauppauge_hvr930c_end); - - msleep(100); - - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); - msleep(30); - - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45); - msleep(10); - -} - -static void terratec_h5_init(struct em28xx *dev) -{ - int i; - struct em28xx_reg_seq terratec_h5_init[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, - {EM2874_R80_GPIO, 0xf2, 0xff, 50}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, - { -1, -1, -1, -1}, - }; - struct em28xx_reg_seq terratec_h5_end[] = { - {EM2874_R80_GPIO, 0xe6, 0xff, 100}, - {EM2874_R80_GPIO, 0xa6, 0xff, 50}, - {EM2874_R80_GPIO, 0xe6, 0xff, 100}, - { -1, -1, -1, -1}, - }; - struct { - unsigned char r[4]; - int len; - } regs[] = { - {{ 0x06, 0x02, 0x00, 0x31 }, 4}, - {{ 0x01, 0x02 }, 2}, - {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, - {{ 0x01, 0x00 }, 2}, - {{ 0x01, 0x00, 0xff, 0xaf }, 4}, - {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, - {{ 0x01, 0x00 }, 2}, - {{ 0x01, 0x00, 0x73, 0xaf }, 4}, - {{ 0x04, 0x00 }, 2}, - {{ 0x00, 0x04 }, 2}, - {{ 0x00, 0x04, 0x00, 0x0a }, 4}, - {{ 0x04, 0x14 }, 2}, - {{ 0x04, 0x14, 0x00, 0x00 }, 4}, - }; - - em28xx_gpio_set(dev, terratec_h5_init); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); - msleep(10); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45); - msleep(10); - - dev->i2c_client.addr = 0x82 >> 1; - - for (i = 0; i < ARRAY_SIZE(regs); i++) - i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len); - em28xx_gpio_set(dev, terratec_h5_end); -}; - -static void terratec_htc_stick_init(struct em28xx *dev) -{ - int i; - - /* - * GPIO configuration: - * 0xff: unknown (does not affect DVB-T). - * 0xf6: DRX-K (demodulator). - * 0xe6: unknown (does not affect DVB-T). - * 0xb6: unknown (does not affect DVB-T). - */ - struct em28xx_reg_seq terratec_htc_stick_init[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, - {EM2874_R80_GPIO, 0xe6, 0xff, 50}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, - { -1, -1, -1, -1}, - }; - struct em28xx_reg_seq terratec_htc_stick_end[] = { - {EM2874_R80_GPIO, 0xb6, 0xff, 100}, - {EM2874_R80_GPIO, 0xf6, 0xff, 50}, - { -1, -1, -1, -1}, - }; - - /* Init the analog decoder? */ - struct { - unsigned char r[4]; - int len; - } regs[] = { - {{ 0x06, 0x02, 0x00, 0x31 }, 4}, - {{ 0x01, 0x02 }, 2}, - {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, - {{ 0x01, 0x00 }, 2}, - {{ 0x01, 0x00, 0xff, 0xaf }, 4}, - }; - - em28xx_gpio_set(dev, terratec_htc_stick_init); - - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); - msleep(10); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); - msleep(10); - - dev->i2c_client.addr = 0x82 >> 1; - - for (i = 0; i < ARRAY_SIZE(regs); i++) - i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len); - - em28xx_gpio_set(dev, terratec_htc_stick_end); -}; - -static void pctv_520e_init(struct em28xx *dev) -{ - /* - * Init AVF4910B analog decoder. Looks like I2C traffic to - * digital demodulator and tuner are routed via AVF4910B. - */ - int i; - struct { - unsigned char r[4]; - int len; - } regs[] = { - {{ 0x06, 0x02, 0x00, 0x31 }, 4}, - {{ 0x01, 0x02 }, 2}, - {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, - {{ 0x01, 0x00 }, 2}, - {{ 0x01, 0x00, 0xff, 0xaf }, 4}, - {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, - {{ 0x01, 0x00 }, 2}, - {{ 0x01, 0x00, 0x73, 0xaf }, 4}, - }; - - dev->i2c_client.addr = 0x82 >> 1; /* 0x41 */ - - for (i = 0; i < ARRAY_SIZE(regs); i++) - i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len); -}; - -static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe) -{ - /* Values extracted from a USB trace of the Terratec Windows driver */ - static u8 clock_config[] = { CLOCK_CTL, 0x38, 0x2c }; - static u8 reset[] = { RESET, 0x80 }; - static u8 adc_ctl_1_cfg[] = { ADC_CTL_1, 0x40 }; - static u8 agc_cfg[] = { AGC_TARGET, 0x28, 0xa0 }; - static u8 input_freq_cfg[] = { INPUT_FREQ_1, 0x31, 0xb8 }; - static u8 rs_err_cfg[] = { RS_ERR_PER_1, 0x00, 0x4d }; - static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; - static u8 trl_nom_cfg[] = { TRL_NOMINAL_RATE_1, 0x64, 0x00 }; - static u8 tps_given_cfg[] = { TPS_GIVEN_1, 0x40, 0x80, 0x50 }; - static u8 tuner_go[] = { TUNER_GO, 0x01}; - - mt352_write(fe, clock_config, sizeof(clock_config)); - udelay(200); - mt352_write(fe, reset, sizeof(reset)); - mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); - mt352_write(fe, agc_cfg, sizeof(agc_cfg)); - mt352_write(fe, input_freq_cfg, sizeof(input_freq_cfg)); - mt352_write(fe, rs_err_cfg, sizeof(rs_err_cfg)); - mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); - mt352_write(fe, trl_nom_cfg, sizeof(trl_nom_cfg)); - mt352_write(fe, tps_given_cfg, sizeof(tps_given_cfg)); - mt352_write(fe, tuner_go, sizeof(tuner_go)); - return 0; -} - -static struct mt352_config terratec_xs_mt352_cfg = { - .demod_address = (0x1e >> 1), - .no_tuner = 1, - .if2 = 45600, - .demod_init = em28xx_mt352_terratec_xs_init, -}; - -static struct tda10023_config em28xx_tda10023_config = { - .demod_address = 0x0c, - .invert = 1, -}; - -static struct cxd2820r_config em28xx_cxd2820r_config = { - .i2c_address = (0xd8 >> 1), - .ts_mode = CXD2820R_TS_SERIAL, - - /* enable LNA for DVB-T, DVB-T2 and DVB-C */ - .gpio_dvbt[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L, - .gpio_dvbt2[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L, - .gpio_dvbc[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L, -}; - -static struct tda18271_config em28xx_cxd2820r_tda18271_config = { - .output_opt = TDA18271_OUTPUT_LT_OFF, - .gate = TDA18271_GATE_DIGITAL, -}; - -static const struct tda10071_config em28xx_tda10071_config = { - .i2c_address = 0x55, /* (0xaa >> 1) */ - .i2c_wr_max = 64, - .ts_mode = TDA10071_TS_SERIAL, - .spec_inv = 0, - .xtal = 40444000, /* 40.444 MHz */ - .pll_multiplier = 20, -}; - -static const struct a8293_config em28xx_a8293_config = { - .i2c_addr = 0x08, /* (0x10 >> 1) */ -}; - -static struct zl10353_config em28xx_zl10353_no_i2c_gate_dev = { - .demod_address = (0x1e >> 1), - .disable_i2c_gate_ctrl = 1, - .no_tuner = 1, - .parallel_ts = 1, -}; -static struct qt1010_config em28xx_qt1010_config = { - .i2c_address = 0x62 - -}; - -/* ------------------------------------------------------------------ */ - -static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev) -{ - struct dvb_frontend *fe; - struct xc2028_config cfg; - - memset(&cfg, 0, sizeof(cfg)); - cfg.i2c_adap = &dev->i2c_adap; - cfg.i2c_addr = addr; - - if (!dev->dvb->fe[0]) { - em28xx_errdev("/2: dvb frontend not attached. " - "Can't attach xc3028\n"); - return -EINVAL; - } - - fe = dvb_attach(xc2028_attach, dev->dvb->fe[0], &cfg); - if (!fe) { - em28xx_errdev("/2: xc3028 attach failed\n"); - dvb_frontend_detach(dev->dvb->fe[0]); - dev->dvb->fe[0] = NULL; - return -EINVAL; - } - - em28xx_info("%s/2: xc3028 attached\n", dev->name); - - return 0; -} - -/* ------------------------------------------------------------------ */ - -static int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module, - struct em28xx *dev, struct device *device) -{ - int result; - - mutex_init(&dvb->lock); - - /* register adapter */ - result = dvb_register_adapter(&dvb->adapter, dev->name, module, device, - adapter_nr); - if (result < 0) { - printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", - dev->name, result); - goto fail_adapter; - } - - /* Ensure all frontends negotiate bus access */ - dvb->fe[0]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; - if (dvb->fe[1]) - dvb->fe[1]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; - - dvb->adapter.priv = dev; - - /* register frontend */ - result = dvb_register_frontend(&dvb->adapter, dvb->fe[0]); - if (result < 0) { - printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", - dev->name, result); - goto fail_frontend0; - } - - /* register 2nd frontend */ - if (dvb->fe[1]) { - result = dvb_register_frontend(&dvb->adapter, dvb->fe[1]); - if (result < 0) { - printk(KERN_WARNING "%s: 2nd dvb_register_frontend failed (errno = %d)\n", - dev->name, result); - goto fail_frontend1; - } - } - - /* register demux stuff */ - dvb->demux.dmx.capabilities = - DMX_TS_FILTERING | DMX_SECTION_FILTERING | - DMX_MEMORY_BASED_FILTERING; - dvb->demux.priv = dvb; - dvb->demux.filternum = 256; - dvb->demux.feednum = 256; - dvb->demux.start_feed = em28xx_start_feed; - dvb->demux.stop_feed = em28xx_stop_feed; - - result = dvb_dmx_init(&dvb->demux); - if (result < 0) { - printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n", - dev->name, result); - goto fail_dmx; - } - - dvb->dmxdev.filternum = 256; - dvb->dmxdev.demux = &dvb->demux.dmx; - dvb->dmxdev.capabilities = 0; - result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); - if (result < 0) { - printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n", - dev->name, result); - goto fail_dmxdev; - } - - dvb->fe_hw.source = DMX_FRONTEND_0; - result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); - if (result < 0) { - printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", - dev->name, result); - goto fail_fe_hw; - } - - dvb->fe_mem.source = DMX_MEMORY_FE; - result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); - if (result < 0) { - printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", - dev->name, result); - goto fail_fe_mem; - } - - result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw); - if (result < 0) { - printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n", - dev->name, result); - goto fail_fe_conn; - } - - /* register network adapter */ - dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); - return 0; - -fail_fe_conn: - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); -fail_fe_mem: - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); -fail_fe_hw: - dvb_dmxdev_release(&dvb->dmxdev); -fail_dmxdev: - dvb_dmx_release(&dvb->demux); -fail_dmx: - if (dvb->fe[1]) - dvb_unregister_frontend(dvb->fe[1]); - dvb_unregister_frontend(dvb->fe[0]); -fail_frontend1: - if (dvb->fe[1]) - dvb_frontend_detach(dvb->fe[1]); -fail_frontend0: - dvb_frontend_detach(dvb->fe[0]); - dvb_unregister_adapter(&dvb->adapter); -fail_adapter: - return result; -} - -static void em28xx_unregister_dvb(struct em28xx_dvb *dvb) -{ - dvb_net_release(&dvb->net); - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); - dvb_dmxdev_release(&dvb->dmxdev); - dvb_dmx_release(&dvb->demux); - if (dvb->fe[1]) - dvb_unregister_frontend(dvb->fe[1]); - dvb_unregister_frontend(dvb->fe[0]); - if (dvb->fe[1] && !dvb->dont_attach_fe1) - dvb_frontend_detach(dvb->fe[1]); - dvb_frontend_detach(dvb->fe[0]); - dvb_unregister_adapter(&dvb->adapter); -} - -static int em28xx_dvb_init(struct em28xx *dev) -{ - int result = 0, mfe_shared = 0; - struct em28xx_dvb *dvb; - - if (!dev->board.has_dvb) { - /* This device does not support the extension */ - printk(KERN_INFO "em28xx_dvb: This device does not support the extension\n"); - return 0; - } - - dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); - - if (dvb == NULL) { - em28xx_info("em28xx_dvb: memory allocation failed\n"); - return -ENOMEM; - } - dev->dvb = dvb; - dvb->fe[0] = dvb->fe[1] = NULL; - - mutex_lock(&dev->lock); - em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); - /* init frontend */ - switch (dev->model) { - case EM2874_BOARD_LEADERSHIP_ISDBT: - dvb->fe[0] = dvb_attach(s921_attach, - &sharp_isdbt, &dev->i2c_adap); - - if (!dvb->fe[0]) { - result = -EINVAL; - goto out_free; - } - - break; - case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: - case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: - case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: - case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: - dvb->fe[0] = dvb_attach(lgdt330x_attach, - &em2880_lgdt3303_dev, - &dev->i2c_adap); - if (em28xx_attach_xc3028(0x61, dev) < 0) { - result = -EINVAL; - goto out_free; - } - break; - case EM2880_BOARD_KWORLD_DVB_310U: - dvb->fe[0] = dvb_attach(zl10353_attach, - &em28xx_zl10353_with_xc3028, - &dev->i2c_adap); - if (em28xx_attach_xc3028(0x61, dev) < 0) { - result = -EINVAL; - goto out_free; - } - break; - case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: - case EM2882_BOARD_TERRATEC_HYBRID_XS: - case EM2880_BOARD_EMPIRE_DUAL_TV: - dvb->fe[0] = dvb_attach(zl10353_attach, - &em28xx_zl10353_xc3028_no_i2c_gate, - &dev->i2c_adap); - if (em28xx_attach_xc3028(0x61, dev) < 0) { - result = -EINVAL; - goto out_free; - } - break; - case EM2880_BOARD_TERRATEC_HYBRID_XS: - case EM2880_BOARD_TERRATEC_HYBRID_XS_FR: - case EM2881_BOARD_PINNACLE_HYBRID_PRO: - case EM2882_BOARD_DIKOM_DK300: - case EM2882_BOARD_KWORLD_VS_DVBT: - dvb->fe[0] = dvb_attach(zl10353_attach, - &em28xx_zl10353_xc3028_no_i2c_gate, - &dev->i2c_adap); - if (dvb->fe[0] == NULL) { - /* This board could have either a zl10353 or a mt352. - If the chip id isn't for zl10353, try mt352 */ - dvb->fe[0] = dvb_attach(mt352_attach, - &terratec_xs_mt352_cfg, - &dev->i2c_adap); - } - - if (em28xx_attach_xc3028(0x61, dev) < 0) { - result = -EINVAL; - goto out_free; - } - break; - case EM2870_BOARD_KWORLD_355U: - dvb->fe[0] = dvb_attach(zl10353_attach, - &em28xx_zl10353_no_i2c_gate_dev, - &dev->i2c_adap); - if (dvb->fe[0] != NULL) - dvb_attach(qt1010_attach, dvb->fe[0], - &dev->i2c_adap, &em28xx_qt1010_config); - break; - case EM2883_BOARD_KWORLD_HYBRID_330U: - case EM2882_BOARD_EVGA_INDTUBE: - dvb->fe[0] = dvb_attach(s5h1409_attach, - &em28xx_s5h1409_with_xc3028, - &dev->i2c_adap); - if (em28xx_attach_xc3028(0x61, dev) < 0) { - result = -EINVAL; - goto out_free; - } - break; - case EM2882_BOARD_KWORLD_ATSC_315U: - dvb->fe[0] = dvb_attach(lgdt330x_attach, - &em2880_lgdt3303_dev, - &dev->i2c_adap); - if (dvb->fe[0] != NULL) { - if (!dvb_attach(simple_tuner_attach, dvb->fe[0], - &dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) { - result = -EINVAL; - goto out_free; - } - } - break; - case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: - case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E: - dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL, - &dev->i2c_adap, &dev->udev->dev); - if (em28xx_attach_xc3028(0x61, dev) < 0) { - result = -EINVAL; - goto out_free; - } - break; - case EM2870_BOARD_REDDO_DVB_C_USB_BOX: - /* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */ - dvb->fe[0] = dvb_attach(tda10023_attach, - &em28xx_tda10023_config, - &dev->i2c_adap, 0x48); - if (dvb->fe[0]) { - if (!dvb_attach(simple_tuner_attach, dvb->fe[0], - &dev->i2c_adap, 0x60, TUNER_PHILIPS_CU1216L)) { - result = -EINVAL; - goto out_free; - } - } - break; - case EM2870_BOARD_KWORLD_A340: - dvb->fe[0] = dvb_attach(lgdt3305_attach, - &em2870_lgdt3304_dev, - &dev->i2c_adap); - if (dvb->fe[0] != NULL) - dvb_attach(tda18271_attach, dvb->fe[0], 0x60, - &dev->i2c_adap, &kworld_a340_config); - break; - case EM28174_BOARD_PCTV_290E: - dvb->fe[0] = dvb_attach(cxd2820r_attach, - &em28xx_cxd2820r_config, - &dev->i2c_adap); - if (dvb->fe[0]) { - /* FE 0 attach tuner */ - if (!dvb_attach(tda18271_attach, - dvb->fe[0], - 0x60, - &dev->i2c_adap, - &em28xx_cxd2820r_tda18271_config)) { - - dvb_frontend_detach(dvb->fe[0]); - result = -EINVAL; - goto out_free; - } - } - break; - case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C: - { - struct xc5000_config cfg; - hauppauge_hvr930c_init(dev); - - dvb->fe[0] = dvb_attach(drxk_attach, - &hauppauge_930c_drxk, &dev->i2c_adap); - if (!dvb->fe[0]) { - result = -EINVAL; - goto out_free; - } - /* FIXME: do we need a pll semaphore? */ - dvb->fe[0]->sec_priv = dvb; - sema_init(&dvb->pll_mutex, 1); - dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl; - dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; - - /* Attach xc5000 */ - memset(&cfg, 0, sizeof(cfg)); - cfg.i2c_address = 0x61; - cfg.if_khz = 4000; - - if (dvb->fe[0]->ops.i2c_gate_ctrl) - dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1); - if (!dvb_attach(xc5000_attach, dvb->fe[0], &dev->i2c_adap, - &cfg)) { - result = -EINVAL; - goto out_free; - } - if (dvb->fe[0]->ops.i2c_gate_ctrl) - dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0); - - break; - } - case EM2884_BOARD_TERRATEC_H5: - terratec_h5_init(dev); - - dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap); - if (!dvb->fe[0]) { - result = -EINVAL; - goto out_free; - } - /* FIXME: do we need a pll semaphore? */ - dvb->fe[0]->sec_priv = dvb; - sema_init(&dvb->pll_mutex, 1); - dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl; - dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; - - /* Attach tda18271 to DVB-C frontend */ - if (dvb->fe[0]->ops.i2c_gate_ctrl) - dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1); - if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], &dev->i2c_adap, 0x60)) { - result = -EINVAL; - goto out_free; - } - if (dvb->fe[0]->ops.i2c_gate_ctrl) - dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0); - - break; - case EM28174_BOARD_PCTV_460E: - /* attach demod */ - dvb->fe[0] = dvb_attach(tda10071_attach, - &em28xx_tda10071_config, &dev->i2c_adap); - - /* attach SEC */ - if (dvb->fe[0]) - dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap, - &em28xx_a8293_config); - break; - case EM2874_BOARD_MAXMEDIA_UB425_TC: - /* attach demodulator */ - dvb->fe[0] = dvb_attach(drxk_attach, &maxmedia_ub425_tc_drxk, - &dev->i2c_adap); - - if (dvb->fe[0]) { - /* disable I2C-gate */ - dvb->fe[0]->ops.i2c_gate_ctrl = NULL; - - /* attach tuner */ - if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], - &dev->i2c_adap, 0x60)) { - dvb_frontend_detach(dvb->fe[0]); - result = -EINVAL; - goto out_free; - } - } - - /* TODO: we need drx-3913k firmware in order to support DVB-T */ - em28xx_info("MaxMedia UB425-TC: only DVB-C supported by that " \ - "driver version\n"); - - break; - case EM2884_BOARD_PCTV_510E: - case EM2884_BOARD_PCTV_520E: - pctv_520e_init(dev); - - /* attach demodulator */ - dvb->fe[0] = dvb_attach(drxk_attach, &pctv_520e_drxk, - &dev->i2c_adap); - - if (dvb->fe[0]) { - /* attach tuner */ - if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, - &dev->i2c_adap, - &em28xx_cxd2820r_tda18271_config)) { - dvb_frontend_detach(dvb->fe[0]); - result = -EINVAL; - goto out_free; - } - } - break; - case EM2884_BOARD_CINERGY_HTC_STICK: - terratec_htc_stick_init(dev); - - /* attach demodulator */ - dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk, - &dev->i2c_adap); - if (!dvb->fe[0]) { - result = -EINVAL; - goto out_free; - } - - /* Attach the demodulator. */ - if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, - &dev->i2c_adap, - &em28xx_cxd2820r_tda18271_config)) { - result = -EINVAL; - goto out_free; - } - break; - default: - em28xx_errdev("/2: The frontend of your DVB/ATSC card" - " isn't supported yet\n"); - break; - } - if (NULL == dvb->fe[0]) { - em28xx_errdev("/2: frontend initialization failed\n"); - result = -EINVAL; - goto out_free; - } - /* define general-purpose callback pointer */ - dvb->fe[0]->callback = em28xx_tuner_callback; - if (dvb->fe[1]) - dvb->fe[1]->callback = em28xx_tuner_callback; - - /* register everything */ - result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); - - if (result < 0) - goto out_free; - - /* MFE lock */ - dvb->adapter.mfe_shared = mfe_shared; - - em28xx_info("Successfully loaded em28xx-dvb\n"); -ret: - em28xx_set_mode(dev, EM28XX_SUSPEND); - mutex_unlock(&dev->lock); - return result; - -out_free: - kfree(dvb); - dev->dvb = NULL; - goto ret; -} - -static inline void prevent_sleep(struct dvb_frontend_ops *ops) -{ - ops->set_voltage = NULL; - ops->sleep = NULL; - ops->tuner_ops.sleep = NULL; -} - -static int em28xx_dvb_fini(struct em28xx *dev) -{ - if (!dev->board.has_dvb) { - /* This device does not support the extension */ - return 0; - } - - if (dev->dvb) { - struct em28xx_dvb *dvb = dev->dvb; - - if (dev->state & DEV_DISCONNECTED) { - /* We cannot tell the device to sleep - * once it has been unplugged. */ - if (dvb->fe[0]) - prevent_sleep(&dvb->fe[0]->ops); - if (dvb->fe[1]) - prevent_sleep(&dvb->fe[1]->ops); - } - - em28xx_unregister_dvb(dvb); - kfree(dvb); - dev->dvb = NULL; - } - - return 0; -} - -static struct em28xx_ops dvb_ops = { - .id = EM28XX_DVB, - .name = "Em28xx dvb Extension", - .init = em28xx_dvb_init, - .fini = em28xx_dvb_fini, -}; - -static int __init em28xx_dvb_register(void) -{ - return em28xx_register_extension(&dvb_ops); -} - -static void __exit em28xx_dvb_unregister(void) -{ - em28xx_unregister_extension(&dvb_ops); -} - -module_init(em28xx_dvb_register); -module_exit(em28xx_dvb_unregister); diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c deleted file mode 100644 index 1683bd9..0000000 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ /dev/null @@ -1,568 +0,0 @@ -/* - em28xx-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices - - Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> - Markus Rechberger <mrechberger@gmail.com> - Mauro Carvalho Chehab <mchehab@infradead.org> - Sascha Sommer <saschasommer@freenet.de> - - 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 <linux/module.h> -#include <linux/kernel.h> -#include <linux/usb.h> -#include <linux/i2c.h> - -#include "em28xx.h" -#include "tuner-xc2028.h" -#include <media/v4l2-common.h> -#include <media/tuner.h> - -/* ----------------------------------------------------------- */ - -static unsigned int i2c_scan; -module_param(i2c_scan, int, 0444); -MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); - -static unsigned int i2c_debug; -module_param(i2c_debug, int, 0644); -MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); - -#define dprintk2(lvl, fmt, args...) \ -do { \ - if (i2c_debug >= lvl) { \ - printk(KERN_DEBUG "%s at %s: " fmt, \ - dev->name, __func__ , ##args); \ - } \ -} while (0) - -/* - * em2800_i2c_send_max4() - * send up to 4 bytes to the i2c device - */ -static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr, - char *buf, int len) -{ - int ret; - int write_timeout; - unsigned char b2[6]; - BUG_ON(len < 1 || len > 4); - b2[5] = 0x80 + len - 1; - b2[4] = addr; - b2[3] = buf[0]; - if (len > 1) - b2[2] = buf[1]; - if (len > 2) - b2[1] = buf[2]; - if (len > 3) - b2[0] = buf[3]; - - ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len); - if (ret != 2 + len) { - em28xx_warn("writing to i2c device failed (error=%i)\n", ret); - return -EIO; - } - for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; - write_timeout -= 5) { - ret = dev->em28xx_read_reg(dev, 0x05); - if (ret == 0x80 + len - 1) - return len; - msleep(5); - } - em28xx_warn("i2c write timed out\n"); - return -EIO; -} - -/* - * em2800_i2c_send_bytes() - */ -static int em2800_i2c_send_bytes(void *data, unsigned char addr, char *buf, - short len) -{ - char *bufPtr = buf; - int ret; - int wrcount = 0; - int count; - int maxLen = 4; - struct em28xx *dev = (struct em28xx *)data; - while (len > 0) { - count = (len > maxLen) ? maxLen : len; - ret = em2800_i2c_send_max4(dev, addr, bufPtr, count); - if (ret > 0) { - len -= count; - bufPtr += count; - wrcount += count; - } else - return (ret < 0) ? ret : -EFAULT; - } - return wrcount; -} - -/* - * em2800_i2c_check_for_device() - * check if there is a i2c_device at the supplied address - */ -static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr) -{ - char msg; - int ret; - int write_timeout; - msg = addr; - ret = dev->em28xx_write_regs(dev, 0x04, &msg, 1); - if (ret < 0) { - em28xx_warn("setting i2c device address failed (error=%i)\n", - ret); - return ret; - } - msg = 0x84; - ret = dev->em28xx_write_regs(dev, 0x05, &msg, 1); - if (ret < 0) { - em28xx_warn("preparing i2c read failed (error=%i)\n", ret); - return ret; - } - for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; - write_timeout -= 5) { - unsigned reg = dev->em28xx_read_reg(dev, 0x5); - - if (reg == 0x94) - return -ENODEV; - else if (reg == 0x84) - return 0; - msleep(5); - } - return -ENODEV; -} - -/* - * em2800_i2c_recv_bytes() - * read from the i2c device - */ -static int em2800_i2c_recv_bytes(struct em28xx *dev, unsigned char addr, - char *buf, int len) -{ - int ret; - /* check for the device and set i2c read address */ - ret = em2800_i2c_check_for_device(dev, addr); - if (ret) { - em28xx_warn - ("preparing read at i2c address 0x%x failed (error=%i)\n", - addr, ret); - return ret; - } - ret = dev->em28xx_read_reg_req_len(dev, 0x0, 0x3, buf, len); - if (ret < 0) { - em28xx_warn("reading from i2c device at 0x%x failed (error=%i)", - addr, ret); - return ret; - } - return ret; -} - -/* - * em28xx_i2c_send_bytes() - */ -static int em28xx_i2c_send_bytes(void *data, unsigned char addr, char *buf, - short len, int stop) -{ - int wrcount = 0; - struct em28xx *dev = (struct em28xx *)data; - int write_timeout, ret; - - wrcount = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len); - - /* Seems to be required after a write */ - for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; - write_timeout -= 5) { - ret = dev->em28xx_read_reg(dev, 0x05); - if (!ret) - break; - msleep(5); - } - - return wrcount; -} - -/* - * em28xx_i2c_recv_bytes() - * read a byte from the i2c device - */ -static int em28xx_i2c_recv_bytes(struct em28xx *dev, unsigned char addr, - char *buf, int len) -{ - int ret; - ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len); - if (ret < 0) { - em28xx_warn("reading i2c device failed (error=%i)\n", ret); - return ret; - } - if (dev->em28xx_read_reg(dev, 0x5) != 0) - return -ENODEV; - return ret; -} - -/* - * em28xx_i2c_check_for_device() - * check if there is a i2c_device at the supplied address - */ -static int em28xx_i2c_check_for_device(struct em28xx *dev, unsigned char addr) -{ - int ret; - - ret = dev->em28xx_read_reg_req(dev, 2, addr); - if (ret < 0) { - em28xx_warn("reading from i2c device failed (error=%i)\n", ret); - return ret; - } - if (dev->em28xx_read_reg(dev, 0x5) != 0) - return -ENODEV; - return 0; -} - -/* - * em28xx_i2c_xfer() - * the main i2c transfer function - */ -static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg msgs[], int num) -{ - struct em28xx *dev = i2c_adap->algo_data; - int addr, rc, i, byte; - - if (num <= 0) - return 0; - for (i = 0; i < num; i++) { - addr = msgs[i].addr << 1; - dprintk2(2, "%s %s addr=%x len=%d:", - (msgs[i].flags & I2C_M_RD) ? "read" : "write", - i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); - if (!msgs[i].len) { /* no len: check only for device presence */ - if (dev->board.is_em2800) - rc = em2800_i2c_check_for_device(dev, addr); - else - rc = em28xx_i2c_check_for_device(dev, addr); - if (rc < 0) { - dprintk2(2, " no device\n"); - return rc; - } - - } else if (msgs[i].flags & I2C_M_RD) { - /* read bytes */ - if (dev->board.is_em2800) - rc = em2800_i2c_recv_bytes(dev, addr, - msgs[i].buf, - msgs[i].len); - else - rc = em28xx_i2c_recv_bytes(dev, addr, - msgs[i].buf, - msgs[i].len); - if (i2c_debug >= 2) { - for (byte = 0; byte < msgs[i].len; byte++) - printk(" %02x", msgs[i].buf[byte]); - } - } else { - /* write bytes */ - if (i2c_debug >= 2) { - for (byte = 0; byte < msgs[i].len; byte++) - printk(" %02x", msgs[i].buf[byte]); - } - if (dev->board.is_em2800) - rc = em2800_i2c_send_bytes(dev, addr, - msgs[i].buf, - msgs[i].len); - else - rc = em28xx_i2c_send_bytes(dev, addr, - msgs[i].buf, - msgs[i].len, - i == num - 1); - } - if (rc < 0) - goto err; - if (i2c_debug >= 2) - printk("\n"); - } - - return num; -err: - dprintk2(2, " ERROR: %i\n", rc); - return rc; -} - -/* based on linux/sunrpc/svcauth.h and linux/hash.h - * The original hash function returns a different value, if arch is x86_64 - * or i386. - */ -static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits) -{ - unsigned long hash = 0; - unsigned long l = 0; - int len = 0; - unsigned char c; - do { - if (len == length) { - c = (char)len; - len = -1; - } else - c = *buf++; - l = (l << 8) | c; - len++; - if ((len & (32 / 8 - 1)) == 0) - hash = ((hash^l) * 0x9e370001UL); - } while (len); - - return (hash >> (32 - bits)) & 0xffffffffUL; -} - -static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) -{ - unsigned char buf, *p = eedata; - struct em28xx_eeprom *em_eeprom = (void *)eedata; - int i, err, size = len, block; - - if (dev->chip_id == CHIP_ID_EM2874 || - dev->chip_id == CHIP_ID_EM28174 || - dev->chip_id == CHIP_ID_EM2884) { - /* Empia switched to a 16-bit addressable eeprom in newer - devices. While we could certainly write a routine to read - the eeprom, there is nothing of use in there that cannot be - accessed through registers, and there is the risk that we - could corrupt the eeprom (since a 16-bit read call is - interpreted as a write call by 8-bit eeproms). - */ - return 0; - } - - dev->i2c_client.addr = 0xa0 >> 1; - - /* Check if board has eeprom */ - err = i2c_master_recv(&dev->i2c_client, &buf, 0); - if (err < 0) { - em28xx_errdev("board has no eeprom\n"); - memset(eedata, 0, len); - return -ENODEV; - } - - buf = 0; - - err = i2c_master_send(&dev->i2c_client, &buf, 1); - if (err != 1) { - printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", - dev->name, err); - return err; - } - while (size > 0) { - if (size > 16) - block = 16; - else - block = size; - - if (block != - (err = i2c_master_recv(&dev->i2c_client, p, block))) { - printk(KERN_WARNING - "%s: i2c eeprom read error (err=%d)\n", - dev->name, err); - return err; - } - size -= block; - p += block; - } - for (i = 0; i < len; i++) { - if (0 == (i % 16)) - printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i); - printk(" %02x", eedata[i]); - if (15 == (i % 16)) - printk("\n"); - } - - if (em_eeprom->id == 0x9567eb1a) - dev->hash = em28xx_hash_mem(eedata, len, 32); - - printk(KERN_INFO "%s: EEPROM ID= 0x%08x, EEPROM hash = 0x%08lx\n", - dev->name, em_eeprom->id, dev->hash); - - printk(KERN_INFO "%s: EEPROM info:\n", dev->name); - - switch (em_eeprom->chip_conf >> 4 & 0x3) { - case 0: - printk(KERN_INFO "%s:\tNo audio on board.\n", dev->name); - break; - case 1: - printk(KERN_INFO "%s:\tAC97 audio (5 sample rates)\n", - dev->name); - break; - case 2: - printk(KERN_INFO "%s:\tI2S audio, sample rate=32k\n", - dev->name); - break; - case 3: - printk(KERN_INFO "%s:\tI2S audio, 3 sample rates\n", - dev->name); - break; - } - - if (em_eeprom->chip_conf & 1 << 3) - printk(KERN_INFO "%s:\tUSB Remote wakeup capable\n", dev->name); - - if (em_eeprom->chip_conf & 1 << 2) - printk(KERN_INFO "%s:\tUSB Self power capable\n", dev->name); - - switch (em_eeprom->chip_conf & 0x3) { - case 0: - printk(KERN_INFO "%s:\t500mA max power\n", dev->name); - break; - case 1: - printk(KERN_INFO "%s:\t400mA max power\n", dev->name); - break; - case 2: - printk(KERN_INFO "%s:\t300mA max power\n", dev->name); - break; - case 3: - printk(KERN_INFO "%s:\t200mA max power\n", dev->name); - break; - } - printk(KERN_INFO "%s:\tTable at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n", - dev->name, - em_eeprom->string_idx_table, - em_eeprom->string1, - em_eeprom->string2, - em_eeprom->string3); - - return 0; -} - -/* ----------------------------------------------------------- */ - -/* - * functionality() - */ -static u32 functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_SMBUS_EMUL; -} - -static struct i2c_algorithm em28xx_algo = { - .master_xfer = em28xx_i2c_xfer, - .functionality = functionality, -}; - -static struct i2c_adapter em28xx_adap_template = { - .owner = THIS_MODULE, - .name = "em28xx", - .algo = &em28xx_algo, -}; - -static struct i2c_client em28xx_client_template = { - .name = "em28xx internal", -}; - -/* ----------------------------------------------------------- */ - -/* - * i2c_devs - * incomplete list of known devices - */ -static char *i2c_devs[128] = { - [0x4a >> 1] = "saa7113h", - [0x52 >> 1] = "drxk", - [0x60 >> 1] = "remote IR sensor", - [0x8e >> 1] = "remote IR sensor", - [0x86 >> 1] = "tda9887", - [0x80 >> 1] = "msp34xx", - [0x88 >> 1] = "msp34xx", - [0xa0 >> 1] = "eeprom", - [0xb0 >> 1] = "tda9874", - [0xb8 >> 1] = "tvp5150a", - [0xba >> 1] = "webcam sensor or tvp5150a", - [0xc0 >> 1] = "tuner (analog)", - [0xc2 >> 1] = "tuner (analog)", - [0xc4 >> 1] = "tuner (analog)", - [0xc6 >> 1] = "tuner (analog)", -}; - -/* - * do_i2c_scan() - * check i2c address range for devices - */ -void em28xx_do_i2c_scan(struct em28xx *dev) -{ - u8 i2c_devicelist[128]; - unsigned char buf; - int i, rc; - - memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist)); - - for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) { - dev->i2c_client.addr = i; - rc = i2c_master_recv(&dev->i2c_client, &buf, 0); - if (rc < 0) - continue; - i2c_devicelist[i] = i; - printk(KERN_INFO "%s: found i2c device @ 0x%x [%s]\n", - dev->name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); - } - - dev->i2c_hash = em28xx_hash_mem(i2c_devicelist, - ARRAY_SIZE(i2c_devicelist), 32); -} - -/* - * em28xx_i2c_register() - * register i2c bus - */ -int em28xx_i2c_register(struct em28xx *dev) -{ - int retval; - - BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg); - BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req); - dev->i2c_adap = em28xx_adap_template; - dev->i2c_adap.dev.parent = &dev->udev->dev; - strcpy(dev->i2c_adap.name, dev->name); - dev->i2c_adap.algo_data = dev; - i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); - - retval = i2c_add_adapter(&dev->i2c_adap); - if (retval < 0) { - em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n", - __func__, retval); - return retval; - } - - dev->i2c_client = em28xx_client_template; - dev->i2c_client.adapter = &dev->i2c_adap; - - retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); - if ((retval < 0) && (retval != -ENODEV)) { - em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n", - __func__, retval); - - return retval; - } - - if (i2c_scan) - em28xx_do_i2c_scan(dev); - - return 0; -} - -/* - * em28xx_i2c_unregister() - * unregister i2c_bus - */ -int em28xx_i2c_unregister(struct em28xx *dev) -{ - i2c_del_adapter(&dev->i2c_adap); - return 0; -} diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c deleted file mode 100644 index 97d36b4..0000000 --- a/drivers/media/video/em28xx/em28xx-input.c +++ /dev/null @@ -1,645 +0,0 @@ -/* - handle em28xx IR remotes via linux kernel input layer. - - Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> - Markus Rechberger <mrechberger@gmail.com> - Mauro Carvalho Chehab <mchehab@infradead.org> - Sascha Sommer <saschasommer@freenet.de> - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/usb.h> -#include <linux/slab.h> - -#include "em28xx.h" - -#define EM28XX_SNAPSHOT_KEY KEY_CAMERA -#define EM28XX_SBUTTON_QUERY_INTERVAL 500 -#define EM28XX_R0C_USBSUSP_SNAPSHOT 0x20 - -static unsigned int ir_debug; -module_param(ir_debug, int, 0644); -MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); - -#define MODULE_NAME "em28xx" - -#define i2cdprintk(fmt, arg...) \ - if (ir_debug) { \ - printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ - } - -#define dprintk(fmt, arg...) \ - if (ir_debug) { \ - printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ - } - -/********************************************************** - Polling structure used by em28xx IR's - **********************************************************/ - -struct em28xx_ir_poll_result { - unsigned int toggle_bit:1; - unsigned int read_count:7; - u8 rc_address; - u8 rc_data[4]; /* 1 byte on em2860/2880, 4 on em2874 */ -}; - -struct em28xx_IR { - struct em28xx *dev; - struct rc_dev *rc; - char name[32]; - char phys[32]; - - /* poll external decoder */ - int polling; - struct delayed_work work; - unsigned int full_code:1; - unsigned int last_readcount; - - int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); -}; - -/********************************************************** - I2C IR based get keycodes - should be used with ir-kbd-i2c - **********************************************************/ - -static int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) -{ - unsigned char b; - - /* poll IR chip */ - if (1 != i2c_master_recv(ir->c, &b, 1)) { - i2cdprintk("read error\n"); - return -EIO; - } - - /* it seems that 0xFE indicates that a button is still hold - down, while 0xff indicates that no button is hold - down. 0xfe sequences are sometimes interrupted by 0xFF */ - - i2cdprintk("key %02x\n", b); - - if (b == 0xff) - return 0; - - if (b == 0xfe) - /* keep old data */ - return 1; - - *ir_key = b; - *ir_raw = b; - return 1; -} - -static int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) -{ - unsigned char buf[2]; - u16 code; - int size; - - /* poll IR chip */ - size = i2c_master_recv(ir->c, buf, sizeof(buf)); - - if (size != 2) - return -EIO; - - /* Does eliminate repeated parity code */ - if (buf[1] == 0xff) - return 0; - - ir->old = buf[1]; - - /* - * Rearranges bits to the right order. - * The bit order were determined experimentally by using - * The original Hauppauge Grey IR and another RC5 that uses addr=0x08 - * The RC5 code has 14 bits, but we've experimentally determined - * the meaning for only 11 bits. - * So, the code translation is not complete. Yet, it is enough to - * work with the provided RC5 IR. - */ - code = - ((buf[0] & 0x01) ? 0x0020 : 0) | /* 0010 0000 */ - ((buf[0] & 0x02) ? 0x0010 : 0) | /* 0001 0000 */ - ((buf[0] & 0x04) ? 0x0008 : 0) | /* 0000 1000 */ - ((buf[0] & 0x08) ? 0x0004 : 0) | /* 0000 0100 */ - ((buf[0] & 0x10) ? 0x0002 : 0) | /* 0000 0010 */ - ((buf[0] & 0x20) ? 0x0001 : 0) | /* 0000 0001 */ - ((buf[1] & 0x08) ? 0x1000 : 0) | /* 0001 0000 */ - ((buf[1] & 0x10) ? 0x0800 : 0) | /* 0000 1000 */ - ((buf[1] & 0x20) ? 0x0400 : 0) | /* 0000 0100 */ - ((buf[1] & 0x40) ? 0x0200 : 0) | /* 0000 0010 */ - ((buf[1] & 0x80) ? 0x0100 : 0); /* 0000 0001 */ - - i2cdprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x%02x)\n", - code, buf[1], buf[0]); - - /* return key */ - *ir_key = code; - *ir_raw = code; - return 1; -} - -static int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, - u32 *ir_raw) -{ - unsigned char buf[3]; - - /* poll IR chip */ - - if (3 != i2c_master_recv(ir->c, buf, 3)) { - i2cdprintk("read error\n"); - return -EIO; - } - - i2cdprintk("key %02x\n", buf[2]&0x3f); - if (buf[0] != 0x00) - return 0; - - *ir_key = buf[2]&0x3f; - *ir_raw = buf[2]&0x3f; - - return 1; -} - -static int em28xx_get_key_winfast_usbii_deluxe(struct IR_i2c *ir, u32 *ir_key, - u32 *ir_raw) -{ - unsigned char subaddr, keydetect, key; - - struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0, .buf = &subaddr, .len = 1}, - - { .addr = ir->c->addr, .flags = I2C_M_RD, .buf = &keydetect, .len = 1} }; - - subaddr = 0x10; - if (2 != i2c_transfer(ir->c->adapter, msg, 2)) { - i2cdprintk("read error\n"); - return -EIO; - } - if (keydetect == 0x00) - return 0; - - subaddr = 0x00; - msg[1].buf = &key; - if (2 != i2c_transfer(ir->c->adapter, msg, 2)) { - i2cdprintk("read error\n"); - return -EIO; - } - if (key == 0x00) - return 0; - - *ir_key = key; - *ir_raw = key; - return 1; -} - -/********************************************************** - Poll based get keycode functions - **********************************************************/ - -/* This is for the em2860/em2880 */ -static int default_polling_getkey(struct em28xx_IR *ir, - struct em28xx_ir_poll_result *poll_result) -{ - struct em28xx *dev = ir->dev; - int rc; - u8 msg[3] = { 0, 0, 0 }; - - /* Read key toggle, brand, and key code - on registers 0x45, 0x46 and 0x47 - */ - rc = dev->em28xx_read_reg_req_len(dev, 0, EM28XX_R45_IR, - msg, sizeof(msg)); - if (rc < 0) - return rc; - - /* Infrared toggle (Reg 0x45[7]) */ - poll_result->toggle_bit = (msg[0] >> 7); - - /* Infrared read count (Reg 0x45[6:0] */ - poll_result->read_count = (msg[0] & 0x7f); - - /* Remote Control Address (Reg 0x46) */ - poll_result->rc_address = msg[1]; - - /* Remote Control Data (Reg 0x47) */ - poll_result->rc_data[0] = msg[2]; - - return 0; -} - -static int em2874_polling_getkey(struct em28xx_IR *ir, - struct em28xx_ir_poll_result *poll_result) -{ - struct em28xx *dev = ir->dev; - int rc; - u8 msg[5] = { 0, 0, 0, 0, 0 }; - - /* Read key toggle, brand, and key code - on registers 0x51-55 - */ - rc = dev->em28xx_read_reg_req_len(dev, 0, EM2874_R51_IR, - msg, sizeof(msg)); - if (rc < 0) - return rc; - - /* Infrared toggle (Reg 0x51[7]) */ - poll_result->toggle_bit = (msg[0] >> 7); - - /* Infrared read count (Reg 0x51[6:0] */ - poll_result->read_count = (msg[0] & 0x7f); - - /* Remote Control Address (Reg 0x52) */ - poll_result->rc_address = msg[1]; - - /* Remote Control Data (Reg 0x53-55) */ - poll_result->rc_data[0] = msg[2]; - poll_result->rc_data[1] = msg[3]; - poll_result->rc_data[2] = msg[4]; - - return 0; -} - -/********************************************************** - Polling code for em28xx - **********************************************************/ - -static void em28xx_ir_handle_key(struct em28xx_IR *ir) -{ - int result; - struct em28xx_ir_poll_result poll_result; - - /* read the registers containing the IR status */ - result = ir->get_key(ir, &poll_result); - if (unlikely(result < 0)) { - dprintk("ir->get_key() failed %d\n", result); - return; - } - - if (unlikely(poll_result.read_count != ir->last_readcount)) { - dprintk("%s: toggle: %d, count: %d, key 0x%02x%02x\n", __func__, - poll_result.toggle_bit, poll_result.read_count, - poll_result.rc_address, poll_result.rc_data[0]); - if (ir->full_code) - rc_keydown(ir->rc, - poll_result.rc_address << 8 | - poll_result.rc_data[0], - poll_result.toggle_bit); - else - rc_keydown(ir->rc, - poll_result.rc_data[0], - poll_result.toggle_bit); - - if (ir->dev->chip_id == CHIP_ID_EM2874 || - ir->dev->chip_id == CHIP_ID_EM2884) - /* The em2874 clears the readcount field every time the - register is read. The em2860/2880 datasheet says that it - is supposed to clear the readcount, but it doesn't. So with - the em2874, we are looking for a non-zero read count as - opposed to a readcount that is incrementing */ - ir->last_readcount = 0; - else - ir->last_readcount = poll_result.read_count; - } -} - -static void em28xx_ir_work(struct work_struct *work) -{ - struct em28xx_IR *ir = container_of(work, struct em28xx_IR, work.work); - - em28xx_ir_handle_key(ir); - schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); -} - -static int em28xx_ir_start(struct rc_dev *rc) -{ - struct em28xx_IR *ir = rc->priv; - - INIT_DELAYED_WORK(&ir->work, em28xx_ir_work); - schedule_delayed_work(&ir->work, 0); - - return 0; -} - -static void em28xx_ir_stop(struct rc_dev *rc) -{ - struct em28xx_IR *ir = rc->priv; - - cancel_delayed_work_sync(&ir->work); -} - -static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type) -{ - int rc = 0; - struct em28xx_IR *ir = rc_dev->priv; - struct em28xx *dev = ir->dev; - u8 ir_config = EM2874_IR_RC5; - - /* Adjust xclk based o IR table for RC5/NEC tables */ - - if (rc_type == RC_TYPE_RC5) { - dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE; - ir->full_code = 1; - } else if (rc_type == RC_TYPE_NEC) { - dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; - ir_config = EM2874_IR_NEC; - ir->full_code = 1; - } else if (rc_type != RC_TYPE_UNKNOWN) - rc = -EINVAL; - - em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, - EM28XX_XCLK_IR_RC5_MODE); - - /* Setup the proper handler based on the chip */ - switch (dev->chip_id) { - case CHIP_ID_EM2860: - case CHIP_ID_EM2883: - ir->get_key = default_polling_getkey; - break; - case CHIP_ID_EM2884: - case CHIP_ID_EM2874: - case CHIP_ID_EM28174: - ir->get_key = em2874_polling_getkey; - em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1); - break; - default: - printk("Unrecognized em28xx chip id 0x%02x: IR not supported\n", - dev->chip_id); - rc = -EINVAL; - } - - return rc; -} - -static void em28xx_register_i2c_ir(struct em28xx *dev) -{ - /* Leadtek winfast tv USBII deluxe can find a non working IR-device */ - /* at address 0x18, so if that address is needed for another board in */ - /* the future, please put it after 0x1f. */ - struct i2c_board_info info; - const unsigned short addr_list[] = { - 0x1f, 0x30, 0x47, I2C_CLIENT_END - }; - - memset(&info, 0, sizeof(struct i2c_board_info)); - memset(&dev->init_data, 0, sizeof(dev->init_data)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); - - /* detect & configure */ - switch (dev->model) { - case EM2800_BOARD_TERRATEC_CINERGY_200: - case EM2820_BOARD_TERRATEC_CINERGY_250: - dev->init_data.ir_codes = RC_MAP_EM_TERRATEC; - dev->init_data.get_key = em28xx_get_key_terratec; - dev->init_data.name = "i2c IR (EM28XX Terratec)"; - break; - case EM2820_BOARD_PINNACLE_USB_2: - dev->init_data.ir_codes = RC_MAP_PINNACLE_GREY; - dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey; - dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; - break; - case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: - dev->init_data.ir_codes = RC_MAP_HAUPPAUGE; - dev->init_data.get_key = em28xx_get_key_em_haup; - dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; - break; - case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE: - dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE; - dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe; - dev->init_data.name = "i2c IR (EM2820 Winfast TV USBII Deluxe)"; - break; - } - - if (dev->init_data.name) - info.platform_data = &dev->init_data; - i2c_new_probed_device(&dev->i2c_adap, &info, addr_list, NULL); -} - -/********************************************************** - Handle Webcam snapshot button - **********************************************************/ - -static void em28xx_query_sbutton(struct work_struct *work) -{ - /* Poll the register and see if the button is depressed */ - struct em28xx *dev = - container_of(work, struct em28xx, sbutton_query_work.work); - int ret; - - ret = em28xx_read_reg(dev, EM28XX_R0C_USBSUSP); - - if (ret & EM28XX_R0C_USBSUSP_SNAPSHOT) { - u8 cleared; - /* Button is depressed, clear the register */ - cleared = ((u8) ret) & ~EM28XX_R0C_USBSUSP_SNAPSHOT; - em28xx_write_regs(dev, EM28XX_R0C_USBSUSP, &cleared, 1); - - /* Not emulate the keypress */ - input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY, - 1); - /* Now unpress the key */ - input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY, - 0); - } - - /* Schedule next poll */ - schedule_delayed_work(&dev->sbutton_query_work, - msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL)); -} - -static void em28xx_register_snapshot_button(struct em28xx *dev) -{ - struct input_dev *input_dev; - int err; - - em28xx_info("Registering snapshot button...\n"); - input_dev = input_allocate_device(); - if (!input_dev) { - em28xx_errdev("input_allocate_device failed\n"); - return; - } - - usb_make_path(dev->udev, dev->snapshot_button_path, - sizeof(dev->snapshot_button_path)); - strlcat(dev->snapshot_button_path, "/sbutton", - sizeof(dev->snapshot_button_path)); - INIT_DELAYED_WORK(&dev->sbutton_query_work, em28xx_query_sbutton); - - input_dev->name = "em28xx snapshot button"; - input_dev->phys = dev->snapshot_button_path; - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); - set_bit(EM28XX_SNAPSHOT_KEY, input_dev->keybit); - input_dev->keycodesize = 0; - input_dev->keycodemax = 0; - input_dev->id.bustype = BUS_USB; - input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); - input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); - input_dev->id.version = 1; - input_dev->dev.parent = &dev->udev->dev; - - err = input_register_device(input_dev); - if (err) { - em28xx_errdev("input_register_device failed\n"); - input_free_device(input_dev); - return; - } - - dev->sbutton_input_dev = input_dev; - schedule_delayed_work(&dev->sbutton_query_work, - msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL)); - return; - -} - -static void em28xx_deregister_snapshot_button(struct em28xx *dev) -{ - if (dev->sbutton_input_dev != NULL) { - em28xx_info("Deregistering snapshot button\n"); - cancel_delayed_work_sync(&dev->sbutton_query_work); - input_unregister_device(dev->sbutton_input_dev); - dev->sbutton_input_dev = NULL; - } - return; -} - -static int em28xx_ir_init(struct em28xx *dev) -{ - struct em28xx_IR *ir; - struct rc_dev *rc; - int err = -ENOMEM; - - if (dev->board.ir_codes == NULL) { - /* No remote control support */ - em28xx_warn("Remote control support is not available for " - "this card.\n"); - return 0; - } - - ir = kzalloc(sizeof(*ir), GFP_KERNEL); - rc = rc_allocate_device(); - if (!ir || !rc) - goto err_out_free; - - /* record handles to ourself */ - ir->dev = dev; - dev->ir = ir; - ir->rc = rc; - - /* - * em2874 supports more protocols. For now, let's just announce - * the two protocols that were already tested - */ - rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC; - rc->priv = ir; - rc->change_protocol = em28xx_ir_change_protocol; - rc->open = em28xx_ir_start; - rc->close = em28xx_ir_stop; - - /* By default, keep protocol field untouched */ - err = em28xx_ir_change_protocol(rc, RC_TYPE_UNKNOWN); - if (err) - goto err_out_free; - - /* This is how often we ask the chip for IR information */ - ir->polling = 100; /* ms */ - - /* init input device */ - snprintf(ir->name, sizeof(ir->name), "em28xx IR (%s)", - dev->name); - - usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); - strlcat(ir->phys, "/input0", sizeof(ir->phys)); - - rc->input_name = ir->name; - rc->input_phys = ir->phys; - rc->input_id.bustype = BUS_USB; - rc->input_id.version = 1; - rc->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); - rc->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct); - rc->dev.parent = &dev->udev->dev; - rc->map_name = dev->board.ir_codes; - rc->driver_name = MODULE_NAME; - - /* all done */ - err = rc_register_device(rc); - if (err) - goto err_out_stop; - - em28xx_register_i2c_ir(dev); - -#if defined(CONFIG_MODULES) && defined(MODULE) - if (dev->board.has_ir_i2c) - request_module("ir-kbd-i2c"); -#endif - if (dev->board.has_snapshot_button) - em28xx_register_snapshot_button(dev); - - return 0; - - err_out_stop: - dev->ir = NULL; - err_out_free: - rc_free_device(rc); - kfree(ir); - return err; -} - -static int em28xx_ir_fini(struct em28xx *dev) -{ - struct em28xx_IR *ir = dev->ir; - - em28xx_deregister_snapshot_button(dev); - - /* skip detach on non attached boards */ - if (!ir) - return 0; - - if (ir->rc) - rc_unregister_device(ir->rc); - - /* done */ - kfree(ir); - dev->ir = NULL; - return 0; -} - -static struct em28xx_ops rc_ops = { - .id = EM28XX_RC, - .name = "Em28xx Input Extension", - .init = em28xx_ir_init, - .fini = em28xx_ir_fini, -}; - -static int __init em28xx_rc_register(void) -{ - return em28xx_register_extension(&rc_ops); -} - -static void __exit em28xx_rc_unregister(void) -{ - em28xx_unregister_extension(&rc_ops); -} - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); -MODULE_DESCRIPTION("Em28xx Input driver"); - -module_init(em28xx_rc_register); -module_exit(em28xx_rc_unregister); diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h deleted file mode 100644 index 6ff3682..0000000 --- a/drivers/media/video/em28xx/em28xx-reg.h +++ /dev/null @@ -1,226 +0,0 @@ -#define EM_GPIO_0 (1 << 0) -#define EM_GPIO_1 (1 << 1) -#define EM_GPIO_2 (1 << 2) -#define EM_GPIO_3 (1 << 3) -#define EM_GPIO_4 (1 << 4) -#define EM_GPIO_5 (1 << 5) -#define EM_GPIO_6 (1 << 6) -#define EM_GPIO_7 (1 << 7) - -#define EM_GPO_0 (1 << 0) -#define EM_GPO_1 (1 << 1) -#define EM_GPO_2 (1 << 2) -#define EM_GPO_3 (1 << 3) - -/* em28xx endpoints */ -#define EM28XX_EP_ANALOG 0x82 -#define EM28XX_EP_AUDIO 0x83 -#define EM28XX_EP_DIGITAL 0x84 - -/* em2800 registers */ -#define EM2800_R08_AUDIOSRC 0x08 - -/* em28xx registers */ - -#define EM28XX_R00_CHIPCFG 0x00 - -/* em28xx Chip Configuration 0x00 */ -#define EM28XX_CHIPCFG_VENDOR_AUDIO 0x80 -#define EM28XX_CHIPCFG_I2S_VOLUME_CAPABLE 0x40 -#define EM28XX_CHIPCFG_I2S_5_SAMPRATES 0x30 -#define EM28XX_CHIPCFG_I2S_3_SAMPRATES 0x20 -#define EM28XX_CHIPCFG_AC97 0x10 -#define EM28XX_CHIPCFG_AUDIOMASK 0x30 - -#define EM28XX_R01_CHIPCFG2 0x01 - -/* em28xx Chip Configuration 2 0x01 */ -#define EM28XX_CHIPCFG2_TS_PRESENT 0x10 -#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_MASK 0x0c /* bits 3-2 */ -#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_1MF 0x00 -#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_2MF 0x04 -#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_4MF 0x08 -#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_8MF 0x0c -#define EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK 0x03 /* bits 0-1 */ -#define EM28XX_CHIPCFG2_TS_PACKETSIZE_188 0x00 -#define EM28XX_CHIPCFG2_TS_PACKETSIZE_376 0x01 -#define EM28XX_CHIPCFG2_TS_PACKETSIZE_564 0x02 -#define EM28XX_CHIPCFG2_TS_PACKETSIZE_752 0x03 - - - /* GPIO/GPO registers */ -#define EM2880_R04_GPO 0x04 /* em2880-em2883 only */ -#define EM28XX_R08_GPIO 0x08 /* em2820 or upper */ - -#define EM28XX_R06_I2C_CLK 0x06 - -/* em28xx I2C Clock Register (0x06) */ -#define EM28XX_I2C_CLK_ACK_LAST_READ 0x80 -#define EM28XX_I2C_CLK_WAIT_ENABLE 0x40 -#define EM28XX_I2C_EEPROM_ON_BOARD 0x08 -#define EM28XX_I2C_EEPROM_KEY_VALID 0x04 -#define EM2874_I2C_SECONDARY_BUS_SELECT 0x04 /* em2874 has two i2c busses */ -#define EM28XX_I2C_FREQ_1_5_MHZ 0x03 /* bus frequency (bits [1-0]) */ -#define EM28XX_I2C_FREQ_25_KHZ 0x02 -#define EM28XX_I2C_FREQ_400_KHZ 0x01 -#define EM28XX_I2C_FREQ_100_KHZ 0x00 - - -#define EM28XX_R0A_CHIPID 0x0a -#define EM28XX_R0C_USBSUSP 0x0c /* */ - -#define EM28XX_R0E_AUDIOSRC 0x0e -#define EM28XX_R0F_XCLK 0x0f - -/* em28xx XCLK Register (0x0f) */ -#define EM28XX_XCLK_AUDIO_UNMUTE 0x80 /* otherwise audio muted */ -#define EM28XX_XCLK_I2S_MSB_TIMING 0x40 /* otherwise standard timing */ -#define EM28XX_XCLK_IR_RC5_MODE 0x20 /* otherwise NEC mode */ -#define EM28XX_XCLK_IR_NEC_CHK_PARITY 0x10 -#define EM28XX_XCLK_FREQUENCY_30MHZ 0x00 /* Freq. select (bits [3-0]) */ -#define EM28XX_XCLK_FREQUENCY_15MHZ 0x01 -#define EM28XX_XCLK_FREQUENCY_10MHZ 0x02 -#define EM28XX_XCLK_FREQUENCY_7_5MHZ 0x03 -#define EM28XX_XCLK_FREQUENCY_6MHZ 0x04 -#define EM28XX_XCLK_FREQUENCY_5MHZ 0x05 -#define EM28XX_XCLK_FREQUENCY_4_3MHZ 0x06 -#define EM28XX_XCLK_FREQUENCY_12MHZ 0x07 -#define EM28XX_XCLK_FREQUENCY_20MHZ 0x08 -#define EM28XX_XCLK_FREQUENCY_20MHZ_2 0x09 -#define EM28XX_XCLK_FREQUENCY_48MHZ 0x0a -#define EM28XX_XCLK_FREQUENCY_24MHZ 0x0b - -#define EM28XX_R10_VINMODE 0x10 - -#define EM28XX_R11_VINCTRL 0x11 - -/* em28xx Video Input Control Register 0x11 */ -#define EM28XX_VINCTRL_VBI_SLICED 0x80 -#define EM28XX_VINCTRL_VBI_RAW 0x40 -#define EM28XX_VINCTRL_VOUT_MODE_IN 0x20 /* HREF,VREF,VACT in output */ -#define EM28XX_VINCTRL_CCIR656_ENABLE 0x10 -#define EM28XX_VINCTRL_VBI_16BIT_RAW 0x08 /* otherwise 8-bit raw */ -#define EM28XX_VINCTRL_FID_ON_HREF 0x04 -#define EM28XX_VINCTRL_DUAL_EDGE_STROBE 0x02 -#define EM28XX_VINCTRL_INTERLACED 0x01 - -#define EM28XX_R12_VINENABLE 0x12 /* */ - -#define EM28XX_R14_GAMMA 0x14 -#define EM28XX_R15_RGAIN 0x15 -#define EM28XX_R16_GGAIN 0x16 -#define EM28XX_R17_BGAIN 0x17 -#define EM28XX_R18_ROFFSET 0x18 -#define EM28XX_R19_GOFFSET 0x19 -#define EM28XX_R1A_BOFFSET 0x1a - -#define EM28XX_R1B_OFLOW 0x1b -#define EM28XX_R1C_HSTART 0x1c -#define EM28XX_R1D_VSTART 0x1d -#define EM28XX_R1E_CWIDTH 0x1e -#define EM28XX_R1F_CHEIGHT 0x1f - -#define EM28XX_R20_YGAIN 0x20 -#define EM28XX_R21_YOFFSET 0x21 -#define EM28XX_R22_UVGAIN 0x22 -#define EM28XX_R23_UOFFSET 0x23 -#define EM28XX_R24_VOFFSET 0x24 -#define EM28XX_R25_SHARPNESS 0x25 - -#define EM28XX_R26_COMPR 0x26 -#define EM28XX_R27_OUTFMT 0x27 - -/* em28xx Output Format Register (0x27) */ -#define EM28XX_OUTFMT_RGB_8_RGRG 0x00 -#define EM28XX_OUTFMT_RGB_8_GRGR 0x01 -#define EM28XX_OUTFMT_RGB_8_GBGB 0x02 -#define EM28XX_OUTFMT_RGB_8_BGBG 0x03 -#define EM28XX_OUTFMT_RGB_16_656 0x04 -#define EM28XX_OUTFMT_RGB_8_BAYER 0x08 /* Pattern in Reg 0x10[1-0] */ -#define EM28XX_OUTFMT_YUV211 0x10 -#define EM28XX_OUTFMT_YUV422_Y0UY1V 0x14 -#define EM28XX_OUTFMT_YUV422_Y1UY0V 0x15 -#define EM28XX_OUTFMT_YUV411 0x18 - - -#define EM28XX_R28_XMIN 0x28 -#define EM28XX_R29_XMAX 0x29 -#define EM28XX_R2A_YMIN 0x2a -#define EM28XX_R2B_YMAX 0x2b - -#define EM28XX_R30_HSCALELOW 0x30 -#define EM28XX_R31_HSCALEHIGH 0x31 -#define EM28XX_R32_VSCALELOW 0x32 -#define EM28XX_R33_VSCALEHIGH 0x33 -#define EM28XX_R34_VBI_START_H 0x34 -#define EM28XX_R35_VBI_START_V 0x35 -#define EM28XX_R36_VBI_WIDTH 0x36 -#define EM28XX_R37_VBI_HEIGHT 0x37 - -#define EM28XX_R40_AC97LSB 0x40 -#define EM28XX_R41_AC97MSB 0x41 -#define EM28XX_R42_AC97ADDR 0x42 -#define EM28XX_R43_AC97BUSY 0x43 - -#define EM28XX_R45_IR 0x45 - /* 0x45 bit 7 - parity bit - bits 6-0 - count - 0x46 IR brand - 0x47 IR data - */ - -/* em2874 registers */ -#define EM2874_R50_IR_CONFIG 0x50 -#define EM2874_R51_IR 0x51 -#define EM2874_R5F_TS_ENABLE 0x5f -#define EM2874_R80_GPIO 0x80 - -/* em2874 IR config register (0x50) */ -#define EM2874_IR_NEC 0x00 -#define EM2874_IR_RC5 0x04 -#define EM2874_IR_RC6_MODE_0 0x08 -#define EM2874_IR_RC6_MODE_6A 0x0b - -/* em2874 Transport Stream Enable Register (0x5f) */ -#define EM2874_TS1_CAPTURE_ENABLE (1 << 0) -#define EM2874_TS1_FILTER_ENABLE (1 << 1) -#define EM2874_TS1_NULL_DISCARD (1 << 2) -#define EM2874_TS2_CAPTURE_ENABLE (1 << 4) -#define EM2874_TS2_FILTER_ENABLE (1 << 5) -#define EM2874_TS2_NULL_DISCARD (1 << 6) - -/* register settings */ -#define EM2800_AUDIO_SRC_TUNER 0x0d -#define EM2800_AUDIO_SRC_LINE 0x0c -#define EM28XX_AUDIO_SRC_TUNER 0xc0 -#define EM28XX_AUDIO_SRC_LINE 0x80 - -/* FIXME: Need to be populated with the other chip ID's */ -enum em28xx_chip_id { - CHIP_ID_EM2800 = 7, - CHIP_ID_EM2710 = 17, - CHIP_ID_EM2820 = 18, /* Also used by some em2710 */ - CHIP_ID_EM2840 = 20, - CHIP_ID_EM2750 = 33, - CHIP_ID_EM2860 = 34, - CHIP_ID_EM2870 = 35, - CHIP_ID_EM2883 = 36, - CHIP_ID_EM2874 = 65, - CHIP_ID_EM2884 = 68, - CHIP_ID_EM28174 = 113, -}; - -/* - * Registers used by em202 - */ - -/* EMP202 vendor registers */ -#define EM202_EXT_MODEM_CTRL 0x3e -#define EM202_GPIO_CONF 0x4c -#define EM202_GPIO_POLARITY 0x4e -#define EM202_GPIO_STICKY 0x50 -#define EM202_GPIO_MASK 0x52 -#define EM202_GPIO_STATUS 0x54 -#define EM202_SPDIF_OUT_SEL 0x6a -#define EM202_ANTIPOP 0x72 -#define EM202_EAPD_GPIO_ACCESS 0x74 diff --git a/drivers/media/video/em28xx/em28xx-vbi.c b/drivers/media/video/em28xx/em28xx-vbi.c deleted file mode 100644 index 2b4c9cb..0000000 --- a/drivers/media/video/em28xx/em28xx-vbi.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - em28xx-vbi.c - VBI driver for em28xx - - Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com> - - This work was sponsored by EyeMagnet Limited. - - 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., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/hardirq.h> -#include <linux/init.h> - -#include "em28xx.h" - -static unsigned int vbibufs = 5; -module_param(vbibufs, int, 0644); -MODULE_PARM_DESC(vbibufs, "number of vbi buffers, range 2-32"); - -static unsigned int vbi_debug; -module_param(vbi_debug, int, 0644); -MODULE_PARM_DESC(vbi_debug, "enable debug messages [vbi]"); - -#define dprintk(level, fmt, arg...) if (vbi_debug >= level) \ - printk(KERN_DEBUG "%s: " fmt, dev->core->name , ## arg) - -/* ------------------------------------------------------------------ */ - -static void -free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf) -{ - struct em28xx_fh *fh = vq->priv_data; - struct em28xx *dev = fh->dev; - unsigned long flags = 0; - if (in_interrupt()) - BUG(); - - /* We used to wait for the buffer to finish here, but this didn't work - because, as we were keeping the state as VIDEOBUF_QUEUED, - videobuf_queue_cancel marked it as finished for us. - (Also, it could wedge forever if the hardware was misconfigured.) - - This should be safe; by the time we get here, the buffer isn't - queued anymore. If we ever start marking the buffers as - VIDEOBUF_ACTIVE, it won't be, though. - */ - spin_lock_irqsave(&dev->slock, flags); - if (dev->isoc_ctl.vbi_buf == buf) - dev->isoc_ctl.vbi_buf = NULL; - spin_unlock_irqrestore(&dev->slock, flags); - - videobuf_vmalloc_free(&buf->vb); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -static int -vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) -{ - struct em28xx_fh *fh = q->priv_data; - struct em28xx *dev = fh->dev; - - *size = dev->vbi_width * dev->vbi_height * 2; - - if (0 == *count) - *count = vbibufs; - if (*count < 2) - *count = 2; - if (*count > 32) - *count = 32; - return 0; -} - -static int -vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct em28xx_fh *fh = q->priv_data; - struct em28xx *dev = fh->dev; - struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); - int rc = 0; - - buf->vb.size = dev->vbi_width * dev->vbi_height * 2; - - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - buf->vb.width = dev->vbi_width; - buf->vb.height = dev->vbi_height; - buf->vb.field = field; - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - rc = videobuf_iolock(q, &buf->vb, NULL); - if (rc < 0) - goto fail; - } - - buf->vb.state = VIDEOBUF_PREPARED; - return 0; - -fail: - free_buffer(q, buf); - return rc; -} - -static void -vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct em28xx_buffer *buf = container_of(vb, - struct em28xx_buffer, - vb); - struct em28xx_fh *fh = vq->priv_data; - struct em28xx *dev = fh->dev; - struct em28xx_dmaqueue *vbiq = &dev->vbiq; - - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vbiq->active); -} - -static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); - free_buffer(q, buf); -} - -struct videobuf_queue_ops em28xx_vbi_qops = { - .buf_setup = vbi_setup, - .buf_prepare = vbi_prepare, - .buf_queue = vbi_queue, - .buf_release = vbi_release, -}; diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c deleted file mode 100644 index ecb23df..0000000 --- a/drivers/media/video/em28xx/em28xx-video.c +++ /dev/null @@ -1,2624 +0,0 @@ -/* - em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB - video capture devices - - Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> - Markus Rechberger <mrechberger@gmail.com> - Mauro Carvalho Chehab <mchehab@infradead.org> - Sascha Sommer <saschasommer@freenet.de> - - Some parts based on SN9C10x PC Camera Controllers GPL driver made - by Luca Risolia <luca.risolia@studio.unibo.it> - - 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 <linux/init.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/bitmap.h> -#include <linux/usb.h> -#include <linux/i2c.h> -#include <linux/mm.h> -#include <linux/mutex.h> -#include <linux/slab.h> - -#include "em28xx.h" -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-chip-ident.h> -#include <media/msp3400.h> -#include <media/tuner.h> - -#define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \ - "Markus Rechberger <mrechberger@gmail.com>, " \ - "Mauro Carvalho Chehab <mchehab@infradead.org>, " \ - "Sascha Sommer <saschasommer@freenet.de>" - -#define DRIVER_DESC "Empia em28xx based USB video device driver" - -#define EM28XX_VERSION "0.1.3" - -#define em28xx_videodbg(fmt, arg...) do {\ - if (video_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __func__ , ##arg); } while (0) - -static unsigned int isoc_debug; -module_param(isoc_debug, int, 0644); -MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]"); - -#define em28xx_isocdbg(fmt, arg...) \ -do {\ - if (isoc_debug) { \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __func__ , ##arg); \ - } \ - } while (0) - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EM28XX_VERSION); - -static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; -static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; -static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; - -module_param_array(video_nr, int, NULL, 0444); -module_param_array(vbi_nr, int, NULL, 0444); -module_param_array(radio_nr, int, NULL, 0444); -MODULE_PARM_DESC(video_nr, "video device numbers"); -MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); -MODULE_PARM_DESC(radio_nr, "radio device numbers"); - -static unsigned int video_debug; -module_param(video_debug, int, 0644); -MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); - -/* supported video standards */ -static struct em28xx_fmt format[] = { - { - .name = "16 bpp YUY2, 4:2:2, packed", - .fourcc = V4L2_PIX_FMT_YUYV, - .depth = 16, - .reg = EM28XX_OUTFMT_YUV422_Y0UY1V, - }, { - .name = "16 bpp RGB 565, LE", - .fourcc = V4L2_PIX_FMT_RGB565, - .depth = 16, - .reg = EM28XX_OUTFMT_RGB_16_656, - }, { - .name = "8 bpp Bayer BGBG..GRGR", - .fourcc = V4L2_PIX_FMT_SBGGR8, - .depth = 8, - .reg = EM28XX_OUTFMT_RGB_8_BGBG, - }, { - .name = "8 bpp Bayer GRGR..BGBG", - .fourcc = V4L2_PIX_FMT_SGRBG8, - .depth = 8, - .reg = EM28XX_OUTFMT_RGB_8_GRGR, - }, { - .name = "8 bpp Bayer GBGB..RGRG", - .fourcc = V4L2_PIX_FMT_SGBRG8, - .depth = 8, - .reg = EM28XX_OUTFMT_RGB_8_GBGB, - }, { - .name = "12 bpp YUV411", - .fourcc = V4L2_PIX_FMT_YUV411P, - .depth = 12, - .reg = EM28XX_OUTFMT_YUV411, - }, -}; - -/* supported controls */ -/* Common to all boards */ -static struct v4l2_queryctrl ac97_qctrl[] = { - { - .id = V4L2_CID_AUDIO_VOLUME, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Volume", - .minimum = 0x0, - .maximum = 0x1f, - .step = 0x1, - .default_value = 0x1f, - .flags = V4L2_CTRL_FLAG_SLIDER, - }, { - .id = V4L2_CID_AUDIO_MUTE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1, - .flags = 0, - } -}; - -/* ------------------------------------------------------------------ - DMA and thread functions - ------------------------------------------------------------------*/ - -/* - * Announces that a buffer were filled and request the next - */ -static inline void buffer_filled(struct em28xx *dev, - struct em28xx_dmaqueue *dma_q, - struct em28xx_buffer *buf) -{ - /* Advice that buffer was filled */ - em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - do_gettimeofday(&buf->vb.ts); - - dev->isoc_ctl.vid_buf = NULL; - - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); -} - -static inline void vbi_buffer_filled(struct em28xx *dev, - struct em28xx_dmaqueue *dma_q, - struct em28xx_buffer *buf) -{ - /* Advice that buffer was filled */ - em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); - - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - do_gettimeofday(&buf->vb.ts); - - dev->isoc_ctl.vbi_buf = NULL; - - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); -} - -/* - * Identify the buffer header type and properly handles - */ -static void em28xx_copy_video(struct em28xx *dev, - struct em28xx_dmaqueue *dma_q, - struct em28xx_buffer *buf, - unsigned char *p, - unsigned char *outp, unsigned long len) -{ - void *fieldstart, *startwrite, *startread; - int linesdone, currlinedone, offset, lencopy, remain; - int bytesperline = dev->width << 1; - - if (dma_q->pos + len > buf->vb.size) - len = buf->vb.size - dma_q->pos; - - startread = p; - remain = len; - - if (dev->progressive) - fieldstart = outp; - else { - /* Interlaces two half frames */ - if (buf->top_field) - fieldstart = outp; - else - fieldstart = outp + bytesperline; - } - - linesdone = dma_q->pos / bytesperline; - currlinedone = dma_q->pos % bytesperline; - - if (dev->progressive) - offset = linesdone * bytesperline + currlinedone; - else - offset = linesdone * bytesperline * 2 + currlinedone; - - startwrite = fieldstart + offset; - lencopy = bytesperline - currlinedone; - lencopy = lencopy > remain ? remain : lencopy; - - if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) { - em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n", - ((char *)startwrite + lencopy) - - ((char *)outp + buf->vb.size)); - remain = (char *)outp + buf->vb.size - (char *)startwrite; - lencopy = remain; - } - if (lencopy <= 0) - return; - memcpy(startwrite, startread, lencopy); - - remain -= lencopy; - - while (remain > 0) { - startwrite += lencopy + bytesperline; - startread += lencopy; - if (bytesperline > remain) - lencopy = remain; - else - lencopy = bytesperline; - - if ((char *)startwrite + lencopy > (char *)outp + - buf->vb.size) { - em28xx_isocdbg("Overflow of %zi bytes past buffer end" - "(2)\n", - ((char *)startwrite + lencopy) - - ((char *)outp + buf->vb.size)); - lencopy = remain = (char *)outp + buf->vb.size - - (char *)startwrite; - } - if (lencopy <= 0) - break; - - memcpy(startwrite, startread, lencopy); - - remain -= lencopy; - } - - dma_q->pos += len; -} - -static void em28xx_copy_vbi(struct em28xx *dev, - struct em28xx_dmaqueue *dma_q, - struct em28xx_buffer *buf, - unsigned char *p, - unsigned char *outp, unsigned long len) -{ - void *startwrite, *startread; - int offset; - int bytesperline; - - if (dev == NULL) { - em28xx_isocdbg("dev is null\n"); - return; - } - bytesperline = dev->vbi_width; - - if (dma_q == NULL) { - em28xx_isocdbg("dma_q is null\n"); - return; - } - if (buf == NULL) { - return; - } - if (p == NULL) { - em28xx_isocdbg("p is null\n"); - return; - } - if (outp == NULL) { - em28xx_isocdbg("outp is null\n"); - return; - } - - if (dma_q->pos + len > buf->vb.size) - len = buf->vb.size - dma_q->pos; - - startread = p; - - startwrite = outp + dma_q->pos; - offset = dma_q->pos; - - /* Make sure the bottom field populates the second half of the frame */ - if (buf->top_field == 0) { - startwrite += bytesperline * dev->vbi_height; - offset += bytesperline * dev->vbi_height; - } - - memcpy(startwrite, startread, len); - dma_q->pos += len; -} - -static inline void print_err_status(struct em28xx *dev, - int packet, int status) -{ - char *errmsg = "Unknown"; - - switch (status) { - case -ENOENT: - errmsg = "unlinked synchronuously"; - break; - case -ECONNRESET: - errmsg = "unlinked asynchronuously"; - break; - case -ENOSR: - errmsg = "Buffer error (overrun)"; - break; - case -EPIPE: - errmsg = "Stalled (device not responding)"; - break; - case -EOVERFLOW: - errmsg = "Babble (bad cable?)"; - break; - case -EPROTO: - errmsg = "Bit-stuff error (bad cable?)"; - break; - case -EILSEQ: - errmsg = "CRC/Timeout (could be anything)"; - break; - case -ETIME: - errmsg = "Device does not respond"; - break; - } - if (packet < 0) { - em28xx_isocdbg("URB status %d [%s].\n", status, errmsg); - } else { - em28xx_isocdbg("URB packet %d, status %d [%s].\n", - packet, status, errmsg); - } -} - -/* - * video-buf generic routine to get the next available buffer - */ -static inline void get_next_buf(struct em28xx_dmaqueue *dma_q, - struct em28xx_buffer **buf) -{ - struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); - char *outp; - - if (list_empty(&dma_q->active)) { - em28xx_isocdbg("No active queue to serve\n"); - dev->isoc_ctl.vid_buf = NULL; - *buf = NULL; - return; - } - - /* Get the next buffer */ - *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue); - - /* Cleans up buffer - Useful for testing for frame/URB loss */ - outp = videobuf_to_vmalloc(&(*buf)->vb); - memset(outp, 0, (*buf)->vb.size); - - dev->isoc_ctl.vid_buf = *buf; - - return; -} - -/* - * video-buf generic routine to get the next available VBI buffer - */ -static inline void vbi_get_next_buf(struct em28xx_dmaqueue *dma_q, - struct em28xx_buffer **buf) -{ - struct em28xx *dev = container_of(dma_q, struct em28xx, vbiq); - char *outp; - - if (list_empty(&dma_q->active)) { - em28xx_isocdbg("No active queue to serve\n"); - dev->isoc_ctl.vbi_buf = NULL; - *buf = NULL; - return; - } - - /* Get the next buffer */ - *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue); - /* Cleans up buffer - Useful for testing for frame/URB loss */ - outp = videobuf_to_vmalloc(&(*buf)->vb); - memset(outp, 0x00, (*buf)->vb.size); - - dev->isoc_ctl.vbi_buf = *buf; - - return; -} - -/* - * Controls the isoc copy of each urb packet - */ -static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb) -{ - struct em28xx_buffer *buf; - struct em28xx_dmaqueue *dma_q = &dev->vidq; - unsigned char *outp = NULL; - int i, len = 0, rc = 1; - unsigned char *p; - - if (!dev) - return 0; - - if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) - return 0; - - if (urb->status < 0) { - print_err_status(dev, -1, urb->status); - if (urb->status == -ENOENT) - return 0; - } - - buf = dev->isoc_ctl.vid_buf; - if (buf != NULL) - outp = videobuf_to_vmalloc(&buf->vb); - - for (i = 0; i < urb->number_of_packets; i++) { - int status = urb->iso_frame_desc[i].status; - - if (status < 0) { - print_err_status(dev, i, status); - if (urb->iso_frame_desc[i].status != -EPROTO) - continue; - } - - len = urb->iso_frame_desc[i].actual_length - 4; - - if (urb->iso_frame_desc[i].actual_length <= 0) { - /* em28xx_isocdbg("packet %d is empty",i); - spammy */ - continue; - } - if (urb->iso_frame_desc[i].actual_length > - dev->max_pkt_size) { - em28xx_isocdbg("packet bigger than packet size"); - continue; - } - - p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - - /* FIXME: incomplete buffer checks where removed to make - logic simpler. Impacts of those changes should be evaluated - */ - if (p[0] == 0x33 && p[1] == 0x95 && p[2] == 0x00) { - em28xx_isocdbg("VBI HEADER!!!\n"); - /* FIXME: Should add vbi copy */ - continue; - } - if (p[0] == 0x22 && p[1] == 0x5a) { - em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2], - len, (p[2] & 1) ? "odd" : "even"); - - if (dev->progressive || !(p[2] & 1)) { - if (buf != NULL) - buffer_filled(dev, dma_q, buf); - get_next_buf(dma_q, &buf); - if (buf == NULL) - outp = NULL; - else - outp = videobuf_to_vmalloc(&buf->vb); - } - - if (buf != NULL) { - if (p[2] & 1) - buf->top_field = 0; - else - buf->top_field = 1; - } - - dma_q->pos = 0; - } - if (buf != NULL) { - if (p[0] != 0x88 && p[0] != 0x22) { - em28xx_isocdbg("frame is not complete\n"); - len += 4; - } else { - p += 4; - } - em28xx_copy_video(dev, dma_q, buf, p, outp, len); - } - } - return rc; -} - -/* Version of isoc handler that takes into account a mixture of video and - VBI data */ -static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) -{ - struct em28xx_buffer *buf, *vbi_buf; - struct em28xx_dmaqueue *dma_q = &dev->vidq; - struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq; - unsigned char *outp = NULL; - unsigned char *vbioutp = NULL; - int i, len = 0, rc = 1; - unsigned char *p; - int vbi_size; - - if (!dev) - return 0; - - if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) - return 0; - - if (urb->status < 0) { - print_err_status(dev, -1, urb->status); - if (urb->status == -ENOENT) - return 0; - } - - buf = dev->isoc_ctl.vid_buf; - if (buf != NULL) - outp = videobuf_to_vmalloc(&buf->vb); - - vbi_buf = dev->isoc_ctl.vbi_buf; - if (vbi_buf != NULL) - vbioutp = videobuf_to_vmalloc(&vbi_buf->vb); - - for (i = 0; i < urb->number_of_packets; i++) { - int status = urb->iso_frame_desc[i].status; - - if (status < 0) { - print_err_status(dev, i, status); - if (urb->iso_frame_desc[i].status != -EPROTO) - continue; - } - - len = urb->iso_frame_desc[i].actual_length; - if (urb->iso_frame_desc[i].actual_length <= 0) { - /* em28xx_isocdbg("packet %d is empty",i); - spammy */ - continue; - } - if (urb->iso_frame_desc[i].actual_length > - dev->max_pkt_size) { - em28xx_isocdbg("packet bigger than packet size"); - continue; - } - - p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - - /* capture type 0 = vbi start - capture type 1 = video start - capture type 2 = video in progress */ - if (p[0] == 0x33 && p[1] == 0x95) { - dev->capture_type = 0; - dev->vbi_read = 0; - em28xx_isocdbg("VBI START HEADER!!!\n"); - dev->cur_field = p[2]; - p += 4; - len -= 4; - } else if (p[0] == 0x88 && p[1] == 0x88 && - p[2] == 0x88 && p[3] == 0x88) { - /* continuation */ - p += 4; - len -= 4; - } else if (p[0] == 0x22 && p[1] == 0x5a) { - /* start video */ - p += 4; - len -= 4; - } - - vbi_size = dev->vbi_width * dev->vbi_height; - - if (dev->capture_type == 0) { - if (dev->vbi_read >= vbi_size) { - /* We've already read all the VBI data, so - treat the rest as video */ - em28xx_isocdbg("dev->vbi_read > vbi_size\n"); - } else if ((dev->vbi_read + len) < vbi_size) { - /* This entire frame is VBI data */ - if (dev->vbi_read == 0 && - (!(dev->cur_field & 1))) { - /* Brand new frame */ - if (vbi_buf != NULL) - vbi_buffer_filled(dev, - vbi_dma_q, - vbi_buf); - vbi_get_next_buf(vbi_dma_q, &vbi_buf); - if (vbi_buf == NULL) - vbioutp = NULL; - else - vbioutp = videobuf_to_vmalloc( - &vbi_buf->vb); - } - - if (dev->vbi_read == 0) { - vbi_dma_q->pos = 0; - if (vbi_buf != NULL) { - if (dev->cur_field & 1) - vbi_buf->top_field = 0; - else - vbi_buf->top_field = 1; - } - } - - dev->vbi_read += len; - em28xx_copy_vbi(dev, vbi_dma_q, vbi_buf, p, - vbioutp, len); - } else { - /* Some of this frame is VBI data and some is - video data */ - int vbi_data_len = vbi_size - dev->vbi_read; - dev->vbi_read += vbi_data_len; - em28xx_copy_vbi(dev, vbi_dma_q, vbi_buf, p, - vbioutp, vbi_data_len); - dev->capture_type = 1; - p += vbi_data_len; - len -= vbi_data_len; - } - } - - if (dev->capture_type == 1) { - dev->capture_type = 2; - if (dev->progressive || !(dev->cur_field & 1)) { - if (buf != NULL) - buffer_filled(dev, dma_q, buf); - get_next_buf(dma_q, &buf); - if (buf == NULL) - outp = NULL; - else - outp = videobuf_to_vmalloc(&buf->vb); - } - if (buf != NULL) { - if (dev->cur_field & 1) - buf->top_field = 0; - else - buf->top_field = 1; - } - - dma_q->pos = 0; - } - - if (buf != NULL && dev->capture_type == 2) { - if (len >= 4 && p[0] == 0x88 && p[1] == 0x88 && - p[2] == 0x88 && p[3] == 0x88) { - p += 4; - len -= 4; - } - if (len >= 4 && p[0] == 0x22 && p[1] == 0x5a) { - em28xx_isocdbg("Video frame %d, len=%i, %s\n", - p[2], len, (p[2] & 1) ? - "odd" : "even"); - p += 4; - len -= 4; - } - - if (len > 0) - em28xx_copy_video(dev, dma_q, buf, p, outp, - len); - } - } - return rc; -} - - -/* ------------------------------------------------------------------ - Videobuf operations - ------------------------------------------------------------------*/ - -static int -buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) -{ - struct em28xx_fh *fh = vq->priv_data; - struct em28xx *dev = fh->dev; - struct v4l2_frequency f; - - *size = (fh->dev->width * fh->dev->height * dev->format->depth + 7) - >> 3; - - if (0 == *count) - *count = EM28XX_DEF_BUF; - - if (*count < EM28XX_MIN_BUF) - *count = EM28XX_MIN_BUF; - - /* Ask tuner to go to analog or radio mode */ - memset(&f, 0, sizeof(f)); - f.frequency = dev->ctl_freq; - f.type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f); - - return 0; -} - -/* This is called *without* dev->slock held; please keep it that way */ -static void free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf) -{ - struct em28xx_fh *fh = vq->priv_data; - struct em28xx *dev = fh->dev; - unsigned long flags = 0; - if (in_interrupt()) - BUG(); - - /* We used to wait for the buffer to finish here, but this didn't work - because, as we were keeping the state as VIDEOBUF_QUEUED, - videobuf_queue_cancel marked it as finished for us. - (Also, it could wedge forever if the hardware was misconfigured.) - - This should be safe; by the time we get here, the buffer isn't - queued anymore. If we ever start marking the buffers as - VIDEOBUF_ACTIVE, it won't be, though. - */ - spin_lock_irqsave(&dev->slock, flags); - if (dev->isoc_ctl.vid_buf == buf) - dev->isoc_ctl.vid_buf = NULL; - spin_unlock_irqrestore(&dev->slock, flags); - - videobuf_vmalloc_free(&buf->vb); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -static int -buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct em28xx_fh *fh = vq->priv_data; - struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); - struct em28xx *dev = fh->dev; - int rc = 0, urb_init = 0; - - buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth - + 7) >> 3; - - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - buf->vb.width = dev->width; - buf->vb.height = dev->height; - buf->vb.field = field; - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - rc = videobuf_iolock(vq, &buf->vb, NULL); - if (rc < 0) - goto fail; - } - - if (!dev->isoc_ctl.analog_bufs.num_bufs) - urb_init = 1; - - if (urb_init) { - if (em28xx_vbi_supported(dev) == 1) - rc = em28xx_init_isoc(dev, EM28XX_ANALOG_MODE, - EM28XX_NUM_PACKETS, - EM28XX_NUM_BUFS, - dev->max_pkt_size, - em28xx_isoc_copy_vbi); - else - rc = em28xx_init_isoc(dev, EM28XX_ANALOG_MODE, - EM28XX_NUM_PACKETS, - EM28XX_NUM_BUFS, - dev->max_pkt_size, - em28xx_isoc_copy); - if (rc < 0) - goto fail; - } - - buf->vb.state = VIDEOBUF_PREPARED; - return 0; - -fail: - free_buffer(vq, buf); - return rc; -} - -static void -buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct em28xx_buffer *buf = container_of(vb, - struct em28xx_buffer, - vb); - struct em28xx_fh *fh = vq->priv_data; - struct em28xx *dev = fh->dev; - struct em28xx_dmaqueue *vidq = &dev->vidq; - - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vidq->active); - -} - -static void buffer_release(struct videobuf_queue *vq, - struct videobuf_buffer *vb) -{ - struct em28xx_buffer *buf = container_of(vb, - struct em28xx_buffer, - vb); - struct em28xx_fh *fh = vq->priv_data; - struct em28xx *dev = (struct em28xx *)fh->dev; - - em28xx_isocdbg("em28xx: called buffer_release\n"); - - free_buffer(vq, buf); -} - -static struct videobuf_queue_ops em28xx_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, -}; - -/********************* v4l2 interface **************************************/ - -static void video_mux(struct em28xx *dev, int index) -{ - dev->ctl_input = index; - dev->ctl_ainput = INPUT(index)->amux; - dev->ctl_aoutput = INPUT(index)->aout; - - if (!dev->ctl_aoutput) - dev->ctl_aoutput = EM28XX_AOUT_MASTER; - - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, - INPUT(index)->vmux, 0, 0); - - if (dev->board.has_msp34xx) { - if (dev->i2s_speed) { - v4l2_device_call_all(&dev->v4l2_dev, 0, audio, - s_i2s_clock_freq, dev->i2s_speed); - } - /* Note: this is msp3400 specific */ - v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, - dev->ctl_ainput, MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0); - } - - if (dev->board.adecoder != EM28XX_NOADECODER) { - v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, - dev->ctl_ainput, dev->ctl_aoutput, 0); - } - - em28xx_audio_analog_set(dev); -} - -/* Usage lock check functions */ -static int res_get(struct em28xx_fh *fh, unsigned int bit) -{ - struct em28xx *dev = fh->dev; - - if (fh->resources & bit) - /* have it already allocated */ - return 1; - - /* is it free? */ - if (dev->resources & bit) { - /* no, someone else uses it */ - return 0; - } - /* it's free, grab it */ - fh->resources |= bit; - dev->resources |= bit; - em28xx_videodbg("res: get %d\n", bit); - return 1; -} - -static int res_check(struct em28xx_fh *fh, unsigned int bit) -{ - return fh->resources & bit; -} - -static int res_locked(struct em28xx *dev, unsigned int bit) -{ - return dev->resources & bit; -} - -static void res_free(struct em28xx_fh *fh, unsigned int bits) -{ - struct em28xx *dev = fh->dev; - - BUG_ON((fh->resources & bits) != bits); - - fh->resources &= ~bits; - dev->resources &= ~bits; - em28xx_videodbg("res: put %d\n", bits); -} - -static int get_ressource(struct em28xx_fh *fh) -{ - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - return EM28XX_RESOURCE_VIDEO; - case V4L2_BUF_TYPE_VBI_CAPTURE: - return EM28XX_RESOURCE_VBI; - default: - BUG(); - return 0; - } -} - -/* - * ac97_queryctrl() - * return the ac97 supported controls - */ -static int ac97_queryctrl(struct v4l2_queryctrl *qc) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) { - if (qc->id && qc->id == ac97_qctrl[i].id) { - memcpy(qc, &(ac97_qctrl[i]), sizeof(*qc)); - return 0; - } - } - - /* Control is not ac97 related */ - return 1; -} - -/* - * ac97_get_ctrl() - * return the current values for ac97 mute and volume - */ -static int ac97_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - ctrl->value = dev->mute; - return 0; - case V4L2_CID_AUDIO_VOLUME: - ctrl->value = dev->volume; - return 0; - default: - /* Control is not ac97 related */ - return 1; - } -} - -/* - * ac97_set_ctrl() - * set values for ac97 mute and volume - */ -static int ac97_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) - if (ctrl->id == ac97_qctrl[i].id) - goto handle; - - /* Announce that hasn't handle it */ - return 1; - -handle: - if (ctrl->value < ac97_qctrl[i].minimum || - ctrl->value > ac97_qctrl[i].maximum) - return -ERANGE; - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - dev->mute = ctrl->value; - break; - case V4L2_CID_AUDIO_VOLUME: - dev->volume = ctrl->value; - break; - } - - return em28xx_audio_analog_set(dev); -} - -static int check_dev(struct em28xx *dev) -{ - if (dev->state & DEV_DISCONNECTED) { - em28xx_errdev("v4l2 ioctl: device not present\n"); - return -ENODEV; - } - - if (dev->state & DEV_MISCONFIGURED) { - em28xx_errdev("v4l2 ioctl: device is misconfigured; " - "close and open it again\n"); - return -EIO; - } - return 0; -} - -static void get_scale(struct em28xx *dev, - unsigned int width, unsigned int height, - unsigned int *hscale, unsigned int *vscale) -{ - unsigned int maxw = norm_maxw(dev); - unsigned int maxh = norm_maxh(dev); - - *hscale = (((unsigned long)maxw) << 12) / width - 4096L; - if (*hscale >= 0x4000) - *hscale = 0x3fff; - - *vscale = (((unsigned long)maxh) << 12) / height - 4096L; - if (*vscale >= 0x4000) - *vscale = 0x3fff; -} - -/* ------------------------------------------------------------------ - IOCTL vidioc handling - ------------------------------------------------------------------*/ - -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - f->fmt.pix.width = dev->width; - f->fmt.pix.height = dev->height; - f->fmt.pix.pixelformat = dev->format->fourcc; - f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3; - f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height; - f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - - /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */ - if (dev->progressive) - f->fmt.pix.field = V4L2_FIELD_NONE; - else - f->fmt.pix.field = dev->interlaced ? - V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; - return 0; -} - -static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(format); i++) - if (format[i].fourcc == fourcc) - return &format[i]; - - return NULL; -} - -static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - unsigned int width = f->fmt.pix.width; - unsigned int height = f->fmt.pix.height; - unsigned int maxw = norm_maxw(dev); - unsigned int maxh = norm_maxh(dev); - unsigned int hscale, vscale; - struct em28xx_fmt *fmt; - - fmt = format_by_fourcc(f->fmt.pix.pixelformat); - if (!fmt) { - em28xx_videodbg("Fourcc format (%08x) invalid.\n", - f->fmt.pix.pixelformat); - return -EINVAL; - } - - if (dev->board.is_em2800) { - /* the em2800 can only scale down to 50% */ - height = height > (3 * maxh / 4) ? maxh : maxh / 2; - width = width > (3 * maxw / 4) ? maxw : maxw / 2; - /* MaxPacketSize for em2800 is too small to capture at full resolution - * use half of maxw as the scaler can only scale to 50% */ - if (width == maxw && height == maxh) - width /= 2; - } else { - /* width must even because of the YUYV format - height must be even because of interlacing */ - v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, - 1, 0); - } - - get_scale(dev, width, height, &hscale, &vscale); - - width = (((unsigned long)maxw) << 12) / (hscale + 4096L); - height = (((unsigned long)maxh) << 12) / (vscale + 4096L); - - f->fmt.pix.width = width; - f->fmt.pix.height = height; - f->fmt.pix.pixelformat = fmt->fourcc; - f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3; - f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height; - f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - if (dev->progressive) - f->fmt.pix.field = V4L2_FIELD_NONE; - else - f->fmt.pix.field = dev->interlaced ? - V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; - - return 0; -} - -static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc, - unsigned width, unsigned height) -{ - struct em28xx_fmt *fmt; - - fmt = format_by_fourcc(fourcc); - if (!fmt) - return -EINVAL; - - dev->format = fmt; - dev->width = width; - dev->height = height; - - /* set new image size */ - get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); - - em28xx_set_alternate(dev); - em28xx_resolution_set(dev); - - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - vidioc_try_fmt_vid_cap(file, priv, f); - - if (videobuf_queue_is_busy(&fh->vb_vidq)) { - em28xx_errdev("%s queue busy\n", __func__); - return -EBUSY; - } - - return em28xx_set_video_format(dev, f->fmt.pix.pixelformat, - f->fmt.pix.width, f->fmt.pix.height); -} - -static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - *norm = dev->norm; - - return 0; -} - -static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - v4l2_device_call_all(&dev->v4l2_dev, 0, video, querystd, norm); - - return 0; -} - -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - struct v4l2_format f; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - dev->norm = *norm; - - /* Adjusts width/height, if needed */ - f.fmt.pix.width = dev->width; - f.fmt.pix.height = dev->height; - vidioc_try_fmt_vid_cap(file, priv, &f); - - /* set new image size */ - dev->width = f.fmt.pix.width; - dev->height = f.fmt.pix.height; - get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); - - em28xx_resolution_set(dev); - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm); - - return 0; -} - -static int vidioc_g_parm(struct file *file, void *priv, - struct v4l2_streamparm *p) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc = 0; - - if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (dev->board.is_webcam) - rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0, - video, g_parm, p); - else - v4l2_video_std_frame_period(dev->norm, - &p->parm.capture.timeperframe); - - return rc; -} - -static int vidioc_s_parm(struct file *file, void *priv, - struct v4l2_streamparm *p) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - if (!dev->board.is_webcam) - return -EINVAL; - - if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - return v4l2_device_call_until_err(&dev->v4l2_dev, 0, video, s_parm, p); -} - -static const char *iname[] = { - [EM28XX_VMUX_COMPOSITE1] = "Composite1", - [EM28XX_VMUX_COMPOSITE2] = "Composite2", - [EM28XX_VMUX_COMPOSITE3] = "Composite3", - [EM28XX_VMUX_COMPOSITE4] = "Composite4", - [EM28XX_VMUX_SVIDEO] = "S-Video", - [EM28XX_VMUX_TELEVISION] = "Television", - [EM28XX_VMUX_CABLE] = "Cable TV", - [EM28XX_VMUX_DVB] = "DVB", - [EM28XX_VMUX_DEBUG] = "for debug only", -}; - -static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *i) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - unsigned int n; - - n = i->index; - if (n >= MAX_EM28XX_INPUT) - return -EINVAL; - if (0 == INPUT(n)->type) - return -EINVAL; - - i->index = n; - i->type = V4L2_INPUT_TYPE_CAMERA; - - strcpy(i->name, iname[INPUT(n)->type]); - - if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) || - (EM28XX_VMUX_CABLE == INPUT(n)->type)) - i->type = V4L2_INPUT_TYPE_TUNER; - - i->std = dev->vdev->tvnorms; - - return 0; -} - -static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - *i = dev->ctl_input; - - return 0; -} - -static int vidioc_s_input(struct file *file, void *priv, unsigned int i) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (i >= MAX_EM28XX_INPUT) - return -EINVAL; - if (0 == INPUT(i)->type) - return -EINVAL; - - video_mux(dev, i); - return 0; -} - -static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - if (!dev->audio_mode.has_audio) - return -EINVAL; - - switch (a->index) { - case EM28XX_AMUX_VIDEO: - strcpy(a->name, "Television"); - break; - case EM28XX_AMUX_LINE_IN: - strcpy(a->name, "Line In"); - break; - case EM28XX_AMUX_VIDEO2: - strcpy(a->name, "Television alt"); - break; - case EM28XX_AMUX_PHONE: - strcpy(a->name, "Phone"); - break; - case EM28XX_AMUX_MIC: - strcpy(a->name, "Mic"); - break; - case EM28XX_AMUX_CD: - strcpy(a->name, "CD"); - break; - case EM28XX_AMUX_AUX: - strcpy(a->name, "Aux"); - break; - case EM28XX_AMUX_PCM_OUT: - strcpy(a->name, "PCM"); - break; - default: - return -EINVAL; - } - - a->index = dev->ctl_ainput; - a->capability = V4L2_AUDCAP_STEREO; - - return 0; -} - -static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - - if (!dev->audio_mode.has_audio) - return -EINVAL; - - if (a->index >= MAX_EM28XX_INPUT) - return -EINVAL; - if (0 == INPUT(a->index)->type) - return -EINVAL; - - dev->ctl_ainput = INPUT(a->index)->amux; - dev->ctl_aoutput = INPUT(a->index)->aout; - - if (!dev->ctl_aoutput) - dev->ctl_aoutput = EM28XX_AOUT_MASTER; - - return 0; -} - -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int id = qc->id; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - memset(qc, 0, sizeof(*qc)); - - qc->id = id; - - /* enumerate AC97 controls */ - if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { - rc = ac97_queryctrl(qc); - if (!rc) - return 0; - } - - /* enumerate V4L2 device controls */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc); - - if (qc->type) - return 0; - else - return -EINVAL; -} - -/* - * FIXME: This is an indirect way to check if a control exists at a - * subdev. Instead of that hack, maybe the better would be to change all - * subdevs to return -ENOIOCTLCMD, if an ioctl is not supported. - */ -static int check_subdev_ctrl(struct em28xx *dev, int id) -{ - struct v4l2_queryctrl qc; - - memset(&qc, 0, sizeof(qc)); - qc.id = id; - - /* enumerate V4L2 device controls */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, &qc); - - if (qc.type) - return 0; - else - return -EINVAL; -} - -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - rc = 0; - - /* Set an AC97 control */ - if (dev->audio_mode.ac97 != EM28XX_NO_AC97) - rc = ac97_get_ctrl(dev, ctrl); - else - rc = 1; - - /* It were not an AC97 control. Sends it to the v4l2 dev interface */ - if (rc == 1) { - if (check_subdev_ctrl(dev, ctrl->id)) - return -EINVAL; - - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl); - rc = 0; - } - - return rc; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - /* Set an AC97 control */ - if (dev->audio_mode.ac97 != EM28XX_NO_AC97) - rc = ac97_set_ctrl(dev, ctrl); - else - rc = 1; - - /* It isn't an AC97 control. Sends it to the v4l2 dev interface */ - if (rc == 1) { - rc = check_subdev_ctrl(dev, ctrl->id); - if (!rc) - v4l2_device_call_all(&dev->v4l2_dev, 0, - core, s_ctrl, ctrl); - /* - * In the case of non-AC97 volume controls, we still need - * to do some setups at em28xx, in order to mute/unmute - * and to adjust audio volume. However, the value ranges - * should be checked by the corresponding V4L subdriver. - */ - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - dev->mute = ctrl->value; - rc = em28xx_audio_analog_set(dev); - break; - case V4L2_CID_AUDIO_VOLUME: - dev->volume = ctrl->value; - rc = em28xx_audio_analog_set(dev); - } - } - return (rc < 0) ? rc : 0; -} - -static int vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (0 != t->index) - return -EINVAL; - - strcpy(t->name, "Tuner"); - t->type = V4L2_TUNER_ANALOG_TV; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); - return 0; -} - -static int vidioc_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (0 != t->index) - return -EINVAL; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); - return 0; -} - -static int vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - f->frequency = dev->ctl_freq; - return 0; -} - -static int vidioc_s_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (0 != f->tuner) - return -EINVAL; - - if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV)) - return -EINVAL; - if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO)) - return -EINVAL; - - dev->ctl_freq = f->frequency; - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f); - - return 0; -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int em28xx_reg_len(int reg) -{ - switch (reg) { - case EM28XX_R40_AC97LSB: - case EM28XX_R30_HSCALELOW: - case EM28XX_R32_VSCALELOW: - return 2; - default: - return 1; - } -} - -static int vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip); - - return 0; -} - - -static int vidioc_g_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int ret; - - switch (reg->match.type) { - case V4L2_CHIP_MATCH_AC97: - ret = em28xx_read_ac97(dev, reg->reg); - if (ret < 0) - return ret; - - reg->val = ret; - reg->size = 1; - return 0; - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - /* TODO: is this correct? */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); - return 0; - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } - - /* Match host */ - reg->size = em28xx_reg_len(reg->reg); - if (reg->size == 1) { - ret = em28xx_read_reg(dev, reg->reg); - - if (ret < 0) - return ret; - - reg->val = ret; - } else { - __le16 val = 0; - ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS, - reg->reg, (char *)&val, 2); - if (ret < 0) - return ret; - - reg->val = le16_to_cpu(val); - } - - return 0; -} - -static int vidioc_s_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - __le16 buf; - - switch (reg->match.type) { - case V4L2_CHIP_MATCH_AC97: - return em28xx_write_ac97(dev, reg->reg, reg->val); - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - /* TODO: is this correct? */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); - return 0; - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } - - /* Match host */ - buf = cpu_to_le16(reg->val); - - return em28xx_write_regs(dev, reg->reg, (char *)&buf, - em28xx_reg_len(reg->reg)); -} -#endif - - -static int vidioc_cropcap(struct file *file, void *priv, - struct v4l2_cropcap *cc) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - cc->bounds.left = 0; - cc->bounds.top = 0; - cc->bounds.width = dev->width; - cc->bounds.height = dev->height; - cc->defrect = cc->bounds; - cc->pixelaspect.numerator = 54; /* 4:3 FIXME: remove magic numbers */ - cc->pixelaspect.denominator = 59; - - return 0; -} - -static int vidioc_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc = -EINVAL; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (unlikely(type != fh->type)) - return -EINVAL; - - em28xx_videodbg("vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n", - fh, type, fh->resources, dev->resources); - - if (unlikely(!res_get(fh, get_ressource(fh)))) - return -EBUSY; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_streamon(&fh->vb_vidq); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_streamon(&fh->vb_vbiq); - - return rc; -} - -static int vidioc_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) - return -EINVAL; - if (type != fh->type) - return -EINVAL; - - em28xx_videodbg("vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n", - fh, type, fh->resources, dev->resources); - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (res_check(fh, EM28XX_RESOURCE_VIDEO)) { - videobuf_streamoff(&fh->vb_vidq); - res_free(fh, EM28XX_RESOURCE_VIDEO); - } - } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - if (res_check(fh, EM28XX_RESOURCE_VBI)) { - videobuf_streamoff(&fh->vb_vbiq); - res_free(fh, EM28XX_RESOURCE_VBI); - } - } - - return 0; -} - -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - strlcpy(cap->driver, "em28xx", sizeof(cap->driver)); - strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card)); - usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); - - cap->capabilities = - V4L2_CAP_SLICED_VBI_CAPTURE | - V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; - - if (dev->vbi_dev) - cap->capabilities |= V4L2_CAP_VBI_CAPTURE; - - if (dev->audio_mode.has_audio) - cap->capabilities |= V4L2_CAP_AUDIO; - - if (dev->tuner_type != TUNER_ABSENT) - cap->capabilities |= V4L2_CAP_TUNER; - - return 0; -} - -static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - if (unlikely(f->index >= ARRAY_SIZE(format))) - return -EINVAL; - - strlcpy(f->description, format[f->index].name, sizeof(f->description)); - f->pixelformat = format[f->index].fourcc; - - return 0; -} - -static int vidioc_enum_framesizes(struct file *file, void *priv, - struct v4l2_frmsizeenum *fsize) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - struct em28xx_fmt *fmt; - unsigned int maxw = norm_maxw(dev); - unsigned int maxh = norm_maxh(dev); - - fmt = format_by_fourcc(fsize->pixel_format); - if (!fmt) { - em28xx_videodbg("Fourcc format (%08x) invalid.\n", - fsize->pixel_format); - return -EINVAL; - } - - if (dev->board.is_em2800) { - if (fsize->index > 1) - return -EINVAL; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - fsize->discrete.width = maxw / (1 + fsize->index); - fsize->discrete.height = maxh / (1 + fsize->index); - return 0; - } - - if (fsize->index != 0) - return -EINVAL; - - /* Report a continuous range */ - fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; - fsize->stepwise.min_width = 48; - fsize->stepwise.min_height = 32; - fsize->stepwise.max_width = maxw; - fsize->stepwise.max_height = maxh; - fsize->stepwise.step_width = 1; - fsize->stepwise.step_height = 1; - return 0; -} - -/* Sliced VBI ioctls */ -static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - f->fmt.sliced.service_set = 0; - v4l2_device_call_all(&dev->v4l2_dev, 0, vbi, g_sliced_fmt, &f->fmt.sliced); - - if (f->fmt.sliced.service_set == 0) - rc = -EINVAL; - - return rc; -} - -static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - v4l2_device_call_all(&dev->v4l2_dev, 0, vbi, g_sliced_fmt, &f->fmt.sliced); - - if (f->fmt.sliced.service_set == 0) - return -EINVAL; - - return 0; -} - -/* RAW VBI ioctls */ - -static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, - struct v4l2_format *format) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - format->fmt.vbi.samples_per_line = dev->vbi_width; - format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; - format->fmt.vbi.offset = 0; - format->fmt.vbi.flags = 0; - format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; - format->fmt.vbi.count[0] = dev->vbi_height; - format->fmt.vbi.count[1] = dev->vbi_height; - - /* Varies by video standard (NTSC, PAL, etc.) */ - if (dev->norm & V4L2_STD_525_60) { - /* NTSC */ - format->fmt.vbi.start[0] = 10; - format->fmt.vbi.start[1] = 273; - } else if (dev->norm & V4L2_STD_625_50) { - /* PAL */ - format->fmt.vbi.start[0] = 6; - format->fmt.vbi.start[1] = 318; - } - - return 0; -} - -static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv, - struct v4l2_format *format) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - format->fmt.vbi.samples_per_line = dev->vbi_width; - format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; - format->fmt.vbi.offset = 0; - format->fmt.vbi.flags = 0; - format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; - format->fmt.vbi.count[0] = dev->vbi_height; - format->fmt.vbi.count[1] = dev->vbi_height; - - /* Varies by video standard (NTSC, PAL, etc.) */ - if (dev->norm & V4L2_STD_525_60) { - /* NTSC */ - format->fmt.vbi.start[0] = 10; - format->fmt.vbi.start[1] = 273; - } else if (dev->norm & V4L2_STD_625_50) { - /* PAL */ - format->fmt.vbi.start[0] = 6; - format->fmt.vbi.start[1] = 318; - } - - return 0; -} - -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *rb) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - return videobuf_reqbufs(&fh->vb_vidq, rb); - else - return videobuf_reqbufs(&fh->vb_vbiq, rb); -} - -static int vidioc_querybuf(struct file *file, void *priv, - struct v4l2_buffer *b) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - return videobuf_querybuf(&fh->vb_vidq, b); - else { - /* FIXME: I'm not sure yet whether this is a bug in zvbi or - the videobuf framework, but we probably shouldn't be - returning a buffer larger than that which was asked for. - At a minimum, it causes a crash in zvbi since it does - a memcpy based on the source buffer length */ - int result = videobuf_querybuf(&fh->vb_vbiq, b); - b->length = dev->vbi_width * dev->vbi_height * 2; - - return result; - } -} - -static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - return videobuf_qbuf(&fh->vb_vidq, b); - else - return videobuf_qbuf(&fh->vb_vbiq, b); -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & - O_NONBLOCK); - else - return videobuf_dqbuf(&fh->vb_vbiq, b, file->f_flags & - O_NONBLOCK); -} - -/* ----------------------------------------------------------- */ -/* RADIO ESPECIFIC IOCTLS */ -/* ----------------------------------------------------------- */ - -static int radio_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct em28xx *dev = ((struct em28xx_fh *)priv)->dev; - - strlcpy(cap->driver, "em28xx", sizeof(cap->driver)); - strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card)); - usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); - - cap->capabilities = V4L2_CAP_TUNER; - return 0; -} - -static int radio_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct em28xx *dev = ((struct em28xx_fh *)priv)->dev; - - if (unlikely(t->index > 0)) - return -EINVAL; - - strcpy(t->name, "Radio"); - t->type = V4L2_TUNER_RADIO; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); - - return 0; -} - -static int radio_enum_input(struct file *file, void *priv, - struct v4l2_input *i) -{ - if (i->index != 0) - return -EINVAL; - strcpy(i->name, "Radio"); - i->type = V4L2_INPUT_TYPE_TUNER; - - return 0; -} - -static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a) -{ - if (unlikely(a->index)) - return -EINVAL; - - strcpy(a->name, "Radio"); - return 0; -} - -static int radio_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct em28xx *dev = ((struct em28xx_fh *)priv)->dev; - - if (0 != t->index) - return -EINVAL; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); - - return 0; -} - -static int radio_s_audio(struct file *file, void *fh, - struct v4l2_audio *a) -{ - return 0; -} - -static int radio_s_input(struct file *file, void *fh, unsigned int i) -{ - return 0; -} - -static int radio_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) -{ - int i; - - if (qc->id < V4L2_CID_BASE || - qc->id >= V4L2_CID_LASTP1) - return -EINVAL; - - for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) { - if (qc->id && qc->id == ac97_qctrl[i].id) { - memcpy(qc, &(ac97_qctrl[i]), sizeof(*qc)); - return 0; - } - } - - return -EINVAL; -} - -/* - * em28xx_v4l2_open() - * inits the device and starts isoc transfer - */ -static int em28xx_v4l2_open(struct file *filp) -{ - int errCode = 0, radio = 0; - struct video_device *vdev = video_devdata(filp); - struct em28xx *dev = video_drvdata(filp); - enum v4l2_buf_type fh_type = 0; - struct em28xx_fh *fh; - enum v4l2_field field; - - switch (vdev->vfl_type) { - case VFL_TYPE_GRABBER: - fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - break; - case VFL_TYPE_VBI: - fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; - break; - case VFL_TYPE_RADIO: - radio = 1; - break; - } - - em28xx_videodbg("open dev=%s type=%s users=%d\n", - video_device_node_name(vdev), v4l2_type_names[fh_type], - dev->users); - - - if (mutex_lock_interruptible(&dev->lock)) - return -ERESTARTSYS; - fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); - if (!fh) { - em28xx_errdev("em28xx-video.c: Out of memory?!\n"); - mutex_unlock(&dev->lock); - return -ENOMEM; - } - fh->dev = dev; - fh->radio = radio; - fh->type = fh_type; - filp->private_data = fh; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { - em28xx_set_mode(dev, EM28XX_ANALOG_MODE); - em28xx_set_alternate(dev); - em28xx_resolution_set(dev); - - /* Needed, since GPIO might have disabled power of - some i2c device - */ - em28xx_wake_i2c(dev); - - } - if (fh->radio) { - em28xx_videodbg("video_open: setting radio device\n"); - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio); - } - - dev->users++; - - if (dev->progressive) - field = V4L2_FIELD_NONE; - else - field = V4L2_FIELD_INTERLACED; - - videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops, - NULL, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, field, - sizeof(struct em28xx_buffer), fh, &dev->lock); - - videobuf_queue_vmalloc_init(&fh->vb_vbiq, &em28xx_vbi_qops, - NULL, &dev->slock, - V4L2_BUF_TYPE_VBI_CAPTURE, - V4L2_FIELD_SEQ_TB, - sizeof(struct em28xx_buffer), fh, &dev->lock); - mutex_unlock(&dev->lock); - - return errCode; -} - -/* - * em28xx_realease_resources() - * unregisters the v4l2,i2c and usb devices - * called when the device gets disconected or at module unload -*/ -void em28xx_release_analog_resources(struct em28xx *dev) -{ - - /*FIXME: I2C IR should be disconnected */ - - if (dev->radio_dev) { - if (video_is_registered(dev->radio_dev)) - video_unregister_device(dev->radio_dev); - else - video_device_release(dev->radio_dev); - dev->radio_dev = NULL; - } - if (dev->vbi_dev) { - em28xx_info("V4L2 device %s deregistered\n", - video_device_node_name(dev->vbi_dev)); - if (video_is_registered(dev->vbi_dev)) - video_unregister_device(dev->vbi_dev); - else - video_device_release(dev->vbi_dev); - dev->vbi_dev = NULL; - } - if (dev->vdev) { - em28xx_info("V4L2 device %s deregistered\n", - video_device_node_name(dev->vdev)); - if (video_is_registered(dev->vdev)) - video_unregister_device(dev->vdev); - else - video_device_release(dev->vdev); - dev->vdev = NULL; - } -} - -/* - * em28xx_v4l2_close() - * stops streaming and deallocates all resources allocated by the v4l2 - * calls and ioctls - */ -static int em28xx_v4l2_close(struct file *filp) -{ - struct em28xx_fh *fh = filp->private_data; - struct em28xx *dev = fh->dev; - int errCode; - - em28xx_videodbg("users=%d\n", dev->users); - - mutex_lock(&dev->lock); - if (res_check(fh, EM28XX_RESOURCE_VIDEO)) { - videobuf_stop(&fh->vb_vidq); - res_free(fh, EM28XX_RESOURCE_VIDEO); - } - - if (res_check(fh, EM28XX_RESOURCE_VBI)) { - videobuf_stop(&fh->vb_vbiq); - res_free(fh, EM28XX_RESOURCE_VBI); - } - - if (dev->users == 1) { - /* the device is already disconnect, - free the remaining resources */ - if (dev->state & DEV_DISCONNECTED) { - em28xx_release_resources(dev); - kfree(dev->alt_max_pkt_size); - kfree(dev); - kfree(fh); - mutex_unlock(&dev->lock); - return 0; - } - - /* Save some power by putting tuner to sleep */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); - - /* do this before setting alternate! */ - em28xx_uninit_isoc(dev, EM28XX_ANALOG_MODE); - em28xx_set_mode(dev, EM28XX_SUSPEND); - - /* set alternate 0 */ - dev->alt = 0; - em28xx_videodbg("setting alternate 0\n"); - errCode = usb_set_interface(dev->udev, 0, 0); - if (errCode < 0) { - em28xx_errdev("cannot change alternate number to " - "0 (error=%i)\n", errCode); - } - } - - videobuf_mmap_free(&fh->vb_vidq); - videobuf_mmap_free(&fh->vb_vbiq); - kfree(fh); - dev->users--; - mutex_unlock(&dev->lock); - return 0; -} - -/* - * em28xx_v4l2_read() - * will allocate buffers when called for the first time - */ -static ssize_t -em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count, - loff_t *pos) -{ - struct em28xx_fh *fh = filp->private_data; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (mutex_lock_interruptible(&dev->lock)) - return -ERESTARTSYS; - /* FIXME: read() is not prepared to allow changing the video - resolution while streaming. Seems a bug at em28xx_set_fmt - */ - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (res_locked(dev, EM28XX_RESOURCE_VIDEO)) - rc = -EBUSY; - else - rc = videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, - filp->f_flags & O_NONBLOCK); - } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - if (!res_get(fh, EM28XX_RESOURCE_VBI)) - rc = -EBUSY; - else - rc = videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0, - filp->f_flags & O_NONBLOCK); - } - mutex_unlock(&dev->lock); - - return rc; -} - -/* - * em28xx_poll() - * will allocate buffers when called for the first time - */ -static unsigned int em28xx_poll(struct file *filp, poll_table *wait) -{ - struct em28xx_fh *fh = filp->private_data; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (!res_get(fh, EM28XX_RESOURCE_VIDEO)) - return POLLERR; - return videobuf_poll_stream(filp, &fh->vb_vidq, wait); - } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - if (!res_get(fh, EM28XX_RESOURCE_VBI)) - return POLLERR; - return videobuf_poll_stream(filp, &fh->vb_vbiq, wait); - } else { - return POLLERR; - } -} - -static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table *wait) -{ - struct em28xx_fh *fh = filp->private_data; - struct em28xx *dev = fh->dev; - unsigned int res; - - mutex_lock(&dev->lock); - res = em28xx_poll(filp, wait); - mutex_unlock(&dev->lock); - return res; -} - -/* - * em28xx_v4l2_mmap() - */ -static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct em28xx_fh *fh = filp->private_data; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (mutex_lock_interruptible(&dev->lock)) - return -ERESTARTSYS; - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma); - mutex_unlock(&dev->lock); - - em28xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n", - (unsigned long)vma->vm_start, - (unsigned long)vma->vm_end-(unsigned long)vma->vm_start, - rc); - - return rc; -} - -static const struct v4l2_file_operations em28xx_v4l_fops = { - .owner = THIS_MODULE, - .open = em28xx_v4l2_open, - .release = em28xx_v4l2_close, - .read = em28xx_v4l2_read, - .poll = em28xx_v4l2_poll, - .mmap = em28xx_v4l2_mmap, - .unlocked_ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, - .vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, - .vidioc_enum_framesizes = vidioc_enum_framesizes, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_cropcap = vidioc_cropcap, - .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap, - .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, - .vidioc_s_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, - - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, - .vidioc_g_std = vidioc_g_std, - .vidioc_querystd = vidioc_querystd, - .vidioc_s_std = vidioc_s_std, - .vidioc_g_parm = vidioc_g_parm, - .vidioc_s_parm = vidioc_s_parm, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, - .vidioc_g_chip_ident = vidioc_g_chip_ident, -#endif -}; - -static const struct video_device em28xx_video_template = { - .fops = &em28xx_v4l_fops, - .release = video_device_release, - .ioctl_ops = &video_ioctl_ops, - - .tvnorms = V4L2_STD_ALL, - .current_norm = V4L2_STD_PAL, -}; - -static const struct v4l2_file_operations radio_fops = { - .owner = THIS_MODULE, - .open = em28xx_v4l2_open, - .release = em28xx_v4l2_close, - .unlocked_ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops radio_ioctl_ops = { - .vidioc_querycap = radio_querycap, - .vidioc_g_tuner = radio_g_tuner, - .vidioc_enum_input = radio_enum_input, - .vidioc_g_audio = radio_g_audio, - .vidioc_s_tuner = radio_s_tuner, - .vidioc_s_audio = radio_s_audio, - .vidioc_s_input = radio_s_input, - .vidioc_queryctrl = radio_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, -#endif -}; - -static struct video_device em28xx_radio_template = { - .name = "em28xx-radio", - .fops = &radio_fops, - .ioctl_ops = &radio_ioctl_ops, -}; - -/******************************** usb interface ******************************/ - - - -static struct video_device *em28xx_vdev_init(struct em28xx *dev, - const struct video_device *template, - const char *type_name) -{ - struct video_device *vfd; - - vfd = video_device_alloc(); - if (NULL == vfd) - return NULL; - - *vfd = *template; - vfd->v4l2_dev = &dev->v4l2_dev; - vfd->release = video_device_release; - vfd->debug = video_debug; - vfd->lock = &dev->lock; - - snprintf(vfd->name, sizeof(vfd->name), "%s %s", - dev->name, type_name); - - video_set_drvdata(vfd, dev); - return vfd; -} - -int em28xx_register_analog_devices(struct em28xx *dev) -{ - u8 val; - int ret; - unsigned int maxw; - - printk(KERN_INFO "%s: v4l2 driver version %s\n", - dev->name, EM28XX_VERSION); - - /* set default norm */ - dev->norm = em28xx_video_template.current_norm; - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm); - dev->interlaced = EM28XX_INTERLACED_DEFAULT; - - /* Analog specific initialization */ - dev->format = &format[0]; - - maxw = norm_maxw(dev); - /* MaxPacketSize for em2800 is too small to capture at full resolution - * use half of maxw as the scaler can only scale to 50% */ - if (dev->board.is_em2800) - maxw /= 2; - - em28xx_set_video_format(dev, format[0].fourcc, - maxw, norm_maxh(dev)); - - video_mux(dev, 0); - - /* Audio defaults */ - dev->mute = 1; - dev->volume = 0x1f; - -/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */ - val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK); - em28xx_write_reg(dev, EM28XX_R0F_XCLK, - (EM28XX_XCLK_AUDIO_UNMUTE | val)); - - em28xx_set_outfmt(dev); - em28xx_colorlevels_set_default(dev); - em28xx_compression_disable(dev); - - /* allocate and fill video video_device struct */ - dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video"); - if (!dev->vdev) { - em28xx_errdev("cannot allocate video_device.\n"); - return -ENODEV; - } - - /* register v4l2 video video_device */ - ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER, - video_nr[dev->devno]); - if (ret) { - em28xx_errdev("unable to register video device (error=%i).\n", - ret); - return ret; - } - - /* Allocate and fill vbi video_device struct */ - if (em28xx_vbi_supported(dev) == 1) { - dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, - "vbi"); - - /* register v4l2 vbi video_device */ - ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, - vbi_nr[dev->devno]); - if (ret < 0) { - em28xx_errdev("unable to register vbi device\n"); - return ret; - } - } - - if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) { - dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, - "radio"); - if (!dev->radio_dev) { - em28xx_errdev("cannot allocate video_device.\n"); - return -ENODEV; - } - ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, - radio_nr[dev->devno]); - if (ret < 0) { - em28xx_errdev("can't register radio device\n"); - return ret; - } - em28xx_info("Registered radio device as %s\n", - video_device_node_name(dev->radio_dev)); - } - - em28xx_info("V4L2 video device registered as %s\n", - video_device_node_name(dev->vdev)); - - if (dev->vbi_dev) - em28xx_info("V4L2 VBI device registered as %s\n", - video_device_node_name(dev->vbi_dev)); - - return 0; -} diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h deleted file mode 100644 index 8757523..0000000 --- a/drivers/media/video/em28xx/em28xx.h +++ /dev/null @@ -1,809 +0,0 @@ -/* - em28xx.h - driver for Empia EM2800/EM2820/2840 USB video capture devices - - Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> - Ludovico Cavedon <cavedon@sssup.it> - Mauro Carvalho Chehab <mchehab@infradead.org> - - Based on the em2800 driver from Sascha Sommer <saschasommer@freenet.de> - - 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 _EM28XX_H -#define _EM28XX_H - -#include <linux/workqueue.h> -#include <linux/i2c.h> -#include <linux/mutex.h> -#include <linux/videodev2.h> - -#include <media/videobuf-vmalloc.h> -#include <media/v4l2-device.h> -#include <media/ir-kbd-i2c.h> -#include <media/rc-core.h> -#if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE) -#include <media/videobuf-dvb.h> -#endif -#include "tuner-xc2028.h" -#include "xc5000.h" -#include "em28xx-reg.h" - -/* Boards supported by driver */ -#define EM2800_BOARD_UNKNOWN 0 -#define EM2820_BOARD_UNKNOWN 1 -#define EM2820_BOARD_TERRATEC_CINERGY_250 2 -#define EM2820_BOARD_PINNACLE_USB_2 3 -#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 4 -#define EM2820_BOARD_MSI_VOX_USB_2 5 -#define EM2800_BOARD_TERRATEC_CINERGY_200 6 -#define EM2800_BOARD_LEADTEK_WINFAST_USBII 7 -#define EM2800_BOARD_KWORLD_USB2800 8 -#define EM2820_BOARD_PINNACLE_DVC_90 9 -#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 10 -#define EM2880_BOARD_TERRATEC_HYBRID_XS 11 -#define EM2820_BOARD_KWORLD_PVRTV2800RF 12 -#define EM2880_BOARD_TERRATEC_PRODIGY_XS 13 -#define EM2820_BOARD_PROLINK_PLAYTV_USB2 14 -#define EM2800_BOARD_VGEAR_POCKETTV 15 -#define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 16 -#define EM2880_BOARD_PINNACLE_PCTV_HD_PRO 17 -#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2 18 -#define EM2860_BOARD_SAA711X_REFERENCE_DESIGN 19 -#define EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 20 -#define EM2800_BOARD_GRABBEEX_USB2800 21 -#define EM2750_BOARD_UNKNOWN 22 -#define EM2750_BOARD_DLCW_130 23 -#define EM2820_BOARD_DLINK_USB_TV 24 -#define EM2820_BOARD_GADMEI_UTV310 25 -#define EM2820_BOARD_HERCULES_SMART_TV_USB2 26 -#define EM2820_BOARD_PINNACLE_USB_2_FM1216ME 27 -#define EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE 28 -#define EM2860_BOARD_TVP5150_REFERENCE_DESIGN 29 -#define EM2820_BOARD_VIDEOLOGY_20K14XUSB 30 -#define EM2821_BOARD_USBGEAR_VD204 31 -#define EM2821_BOARD_SUPERCOMP_USB_2 32 -#define EM2860_BOARD_ELGATO_VIDEO_CAPTURE 33 -#define EM2860_BOARD_TERRATEC_HYBRID_XS 34 -#define EM2860_BOARD_TYPHOON_DVD_MAKER 35 -#define EM2860_BOARD_NETGMBH_CAM 36 -#define EM2860_BOARD_GADMEI_UTV330 37 -#define EM2861_BOARD_YAKUMO_MOVIE_MIXER 38 -#define EM2861_BOARD_KWORLD_PVRTV_300U 39 -#define EM2861_BOARD_PLEXTOR_PX_TV100U 40 -#define EM2870_BOARD_KWORLD_350U 41 -#define EM2870_BOARD_KWORLD_355U 42 -#define EM2870_BOARD_TERRATEC_XS 43 -#define EM2870_BOARD_TERRATEC_XS_MT2060 44 -#define EM2870_BOARD_PINNACLE_PCTV_DVB 45 -#define EM2870_BOARD_COMPRO_VIDEOMATE 46 -#define EM2880_BOARD_KWORLD_DVB_305U 47 -#define EM2880_BOARD_KWORLD_DVB_310U 48 -#define EM2880_BOARD_MSI_DIGIVOX_AD 49 -#define EM2880_BOARD_MSI_DIGIVOX_AD_II 50 -#define EM2880_BOARD_TERRATEC_HYBRID_XS_FR 51 -#define EM2881_BOARD_DNT_DA2_HYBRID 52 -#define EM2881_BOARD_PINNACLE_HYBRID_PRO 53 -#define EM2882_BOARD_KWORLD_VS_DVBT 54 -#define EM2882_BOARD_TERRATEC_HYBRID_XS 55 -#define EM2882_BOARD_PINNACLE_HYBRID_PRO_330E 56 -#define EM2883_BOARD_KWORLD_HYBRID_330U 57 -#define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU 58 -#define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60 -#define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2 61 -#define EM2820_BOARD_GADMEI_TVR200 62 -#define EM2860_BOARD_KAIOMY_TVNPC_U2 63 -#define EM2860_BOARD_EASYCAP 64 -#define EM2820_BOARD_IODATA_GVMVP_SZ 65 -#define EM2880_BOARD_EMPIRE_DUAL_TV 66 -#define EM2860_BOARD_TERRATEC_GRABBY 67 -#define EM2860_BOARD_TERRATEC_AV350 68 -#define EM2882_BOARD_KWORLD_ATSC_315U 69 -#define EM2882_BOARD_EVGA_INDTUBE 70 -#define EM2820_BOARD_SILVERCREST_WEBCAM 71 -#define EM2861_BOARD_GADMEI_UTV330PLUS 72 -#define EM2870_BOARD_REDDO_DVB_C_USB_BOX 73 -#define EM2800_BOARD_VC211A 74 -#define EM2882_BOARD_DIKOM_DK300 75 -#define EM2870_BOARD_KWORLD_A340 76 -#define EM2874_BOARD_LEADERSHIP_ISDBT 77 -#define EM28174_BOARD_PCTV_290E 78 -#define EM2884_BOARD_TERRATEC_H5 79 -#define EM28174_BOARD_PCTV_460E 80 -#define EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C 81 -#define EM2884_BOARD_CINERGY_HTC_STICK 82 -#define EM2860_BOARD_HT_VIDBOX_NW03 83 -#define EM2874_BOARD_MAXMEDIA_UB425_TC 84 -#define EM2884_BOARD_PCTV_510E 85 -#define EM2884_BOARD_PCTV_520E 86 - -/* Limits minimum and default number of buffers */ -#define EM28XX_MIN_BUF 4 -#define EM28XX_DEF_BUF 8 - -/*Limits the max URB message size */ -#define URB_MAX_CTRL_SIZE 80 - -/* Params for validated field */ -#define EM28XX_BOARD_NOT_VALIDATED 1 -#define EM28XX_BOARD_VALIDATED 0 - -/* Params for em28xx_cmd() audio */ -#define EM28XX_START_AUDIO 1 -#define EM28XX_STOP_AUDIO 0 - -/* maximum number of em28xx boards */ -#define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */ - -/* maximum number of frames that can be queued */ -#define EM28XX_NUM_FRAMES 5 -/* number of frames that get used for v4l2_read() */ -#define EM28XX_NUM_READ_FRAMES 2 - -/* number of buffers for isoc transfers */ -#define EM28XX_NUM_BUFS 5 -#define EM28XX_DVB_NUM_BUFS 5 - -/* number of packets for each buffer - windows requests only 64 packets .. so we better do the same - this is what I found out for all alternate numbers there! - */ -#define EM28XX_NUM_PACKETS 64 -#define EM28XX_DVB_MAX_PACKETS 64 - -#define EM28XX_INTERLACED_DEFAULT 1 - -/* -#define (use usbview if you want to get the other alternate number infos) -#define -#define alternate number 2 -#define Endpoint Address: 82 - Direction: in - Attribute: 1 - Type: Isoc - Max Packet Size: 1448 - Interval: 125us - - alternate number 7 - - Endpoint Address: 82 - Direction: in - Attribute: 1 - Type: Isoc - Max Packet Size: 3072 - Interval: 125us -*/ - -/* time to wait when stopping the isoc transfer */ -#define EM28XX_URB_TIMEOUT \ - msecs_to_jiffies(EM28XX_NUM_BUFS * EM28XX_NUM_PACKETS) - -/* time in msecs to wait for i2c writes to finish */ -#define EM2800_I2C_WRITE_TIMEOUT 20 - -enum em28xx_mode { - EM28XX_SUSPEND, - EM28XX_ANALOG_MODE, - EM28XX_DIGITAL_MODE, -}; - - -struct em28xx; - -struct em28xx_usb_isoc_bufs { - /* max packet size of isoc transaction */ - int max_pkt_size; - - /* number of packets in each buffer */ - int num_packets; - - /* number of allocated urbs */ - int num_bufs; - - /* urb for isoc transfers */ - struct urb **urb; - - /* transfer buffers for isoc transfer */ - char **transfer_buffer; -}; - -struct em28xx_usb_isoc_ctl { - /* isoc transfer buffers for analog mode */ - struct em28xx_usb_isoc_bufs analog_bufs; - - /* isoc transfer buffers for digital mode */ - struct em28xx_usb_isoc_bufs digital_bufs; - - /* Stores already requested buffers */ - struct em28xx_buffer *vid_buf; - struct em28xx_buffer *vbi_buf; - - /* isoc urb callback */ - int (*isoc_copy) (struct em28xx *dev, struct urb *urb); - -}; - -/* Struct to enumberate video formats */ -struct em28xx_fmt { - char *name; - u32 fourcc; /* v4l2 format id */ - int depth; - int reg; -}; - -/* buffer for one video frame */ -struct em28xx_buffer { - /* common v4l buffer stuff -- must be first */ - struct videobuf_buffer vb; - - struct list_head frame; - int top_field; -}; - -struct em28xx_dmaqueue { - struct list_head active; - - wait_queue_head_t wq; - - /* Counters to control buffer fill */ - int pos; -}; - -/* inputs */ - -#define MAX_EM28XX_INPUT 4 -enum enum28xx_itype { - EM28XX_VMUX_COMPOSITE1 = 1, - EM28XX_VMUX_COMPOSITE2, - EM28XX_VMUX_COMPOSITE3, - EM28XX_VMUX_COMPOSITE4, - EM28XX_VMUX_SVIDEO, - EM28XX_VMUX_TELEVISION, - EM28XX_VMUX_CABLE, - EM28XX_VMUX_DVB, - EM28XX_VMUX_DEBUG, - EM28XX_RADIO, -}; - -enum em28xx_ac97_mode { - EM28XX_NO_AC97 = 0, - EM28XX_AC97_EM202, - EM28XX_AC97_SIGMATEL, - EM28XX_AC97_OTHER, -}; - -struct em28xx_audio_mode { - enum em28xx_ac97_mode ac97; - - u16 ac97_feat; - u32 ac97_vendor_id; - - unsigned int has_audio:1; - - unsigned int i2s_3rates:1; - unsigned int i2s_5rates:1; -}; - -/* em28xx has two audio inputs: tuner and line in. - However, on most devices, an auxiliary AC97 codec device is used. - The AC97 device may have several different inputs and outputs, - depending on their model. So, it is possible to use AC97 mixer to - address more than two different entries. - */ -enum em28xx_amux { - /* This is the only entry for em28xx tuner input */ - EM28XX_AMUX_VIDEO, /* em28xx tuner, AC97 mixer Video */ - - EM28XX_AMUX_LINE_IN, /* AC97 mixer Line In */ - - /* Some less-common mixer setups */ - EM28XX_AMUX_VIDEO2, /* em28xx Line in, AC97 mixer Video */ - EM28XX_AMUX_PHONE, - EM28XX_AMUX_MIC, - EM28XX_AMUX_CD, - EM28XX_AMUX_AUX, - EM28XX_AMUX_PCM_OUT, -}; - -enum em28xx_aout { - /* AC97 outputs */ - EM28XX_AOUT_MASTER = 1 << 0, - EM28XX_AOUT_LINE = 1 << 1, - EM28XX_AOUT_MONO = 1 << 2, - EM28XX_AOUT_LFE = 1 << 3, - EM28XX_AOUT_SURR = 1 << 4, - - /* PCM IN Mixer - used by AC97_RECORD_SELECT register */ - EM28XX_AOUT_PCM_IN = 1 << 7, - - /* Bits 10-8 are used to indicate the PCM IN record select */ - EM28XX_AOUT_PCM_MIC_PCM = 0 << 8, - EM28XX_AOUT_PCM_CD = 1 << 8, - EM28XX_AOUT_PCM_VIDEO = 2 << 8, - EM28XX_AOUT_PCM_AUX = 3 << 8, - EM28XX_AOUT_PCM_LINE = 4 << 8, - EM28XX_AOUT_PCM_STEREO = 5 << 8, - EM28XX_AOUT_PCM_MONO = 6 << 8, - EM28XX_AOUT_PCM_PHONE = 7 << 8, -}; - -static inline int ac97_return_record_select(int a_out) -{ - return (a_out & 0x700) >> 8; -} - -struct em28xx_reg_seq { - int reg; - unsigned char val, mask; - int sleep; -}; - -struct em28xx_input { - enum enum28xx_itype type; - unsigned int vmux; - enum em28xx_amux amux; - enum em28xx_aout aout; - struct em28xx_reg_seq *gpio; -}; - -#define INPUT(nr) (&em28xx_boards[dev->model].input[nr]) - -enum em28xx_decoder { - EM28XX_NODECODER = 0, - EM28XX_TVP5150, - EM28XX_SAA711X, -}; - -enum em28xx_sensor { - EM28XX_NOSENSOR = 0, - EM28XX_MT9V011, - EM28XX_MT9M001, - EM28XX_MT9M111, -}; - -enum em28xx_adecoder { - EM28XX_NOADECODER = 0, - EM28XX_TVAUDIO, -}; - -struct em28xx_board { - char *name; - int vchannels; - int tuner_type; - int tuner_addr; - - /* i2c flags */ - unsigned int tda9887_conf; - - /* GPIO sequences */ - struct em28xx_reg_seq *dvb_gpio; - struct em28xx_reg_seq *suspend_gpio; - struct em28xx_reg_seq *tuner_gpio; - struct em28xx_reg_seq *mute_gpio; - - unsigned int is_em2800:1; - unsigned int has_msp34xx:1; - unsigned int mts_firmware:1; - unsigned int max_range_640_480:1; - unsigned int has_dvb:1; - unsigned int has_snapshot_button:1; - unsigned int is_webcam:1; - unsigned int valid:1; - unsigned int has_ir_i2c:1; - - unsigned char xclk, i2c_speed; - unsigned char radio_addr; - unsigned short tvaudio_addr; - - enum em28xx_decoder decoder; - enum em28xx_adecoder adecoder; - - struct em28xx_input input[MAX_EM28XX_INPUT]; - struct em28xx_input radio; - char *ir_codes; -}; - -struct em28xx_eeprom { - u32 id; /* 0x9567eb1a */ - u16 vendor_ID; - u16 product_ID; - - u16 chip_conf; - - u16 board_conf; - - u16 string1, string2, string3; - - u8 string_idx_table; -}; - -/* device states */ -enum em28xx_dev_state { - DEV_INITIALIZED = 0x01, - DEV_DISCONNECTED = 0x02, - DEV_MISCONFIGURED = 0x04, -}; - -#define EM28XX_AUDIO_BUFS 5 -#define EM28XX_NUM_AUDIO_PACKETS 64 -#define EM28XX_AUDIO_MAX_PACKET_SIZE 196 /* static value */ -#define EM28XX_CAPTURE_STREAM_EN 1 - -/* em28xx extensions */ -#define EM28XX_AUDIO 0x10 -#define EM28XX_DVB 0x20 -#define EM28XX_RC 0x30 - -/* em28xx resource types (used for res_get/res_lock etc */ -#define EM28XX_RESOURCE_VIDEO 0x01 -#define EM28XX_RESOURCE_VBI 0x02 - -struct em28xx_audio { - char name[50]; - char *transfer_buffer[EM28XX_AUDIO_BUFS]; - struct urb *urb[EM28XX_AUDIO_BUFS]; - struct usb_device *udev; - unsigned int capture_transfer_done; - struct snd_pcm_substream *capture_pcm_substream; - - unsigned int hwptr_done_capture; - struct snd_card *sndcard; - - int users; - spinlock_t slock; -}; - -struct em28xx; - -struct em28xx_fh { - struct em28xx *dev; - int radio; - unsigned int resources; - - struct videobuf_queue vb_vidq; - struct videobuf_queue vb_vbiq; - - enum v4l2_buf_type type; -}; - -/* main device struct */ -struct em28xx { - /* generic device properties */ - char name[30]; /* name (including minor) of the device */ - int model; /* index in the device_data struct */ - int devno; /* marks the number of this device */ - enum em28xx_chip_id chip_id; - - int audio_ifnum; - - struct v4l2_device v4l2_dev; - struct em28xx_board board; - - /* Webcam specific fields */ - enum em28xx_sensor em28xx_sensor; - int sensor_xres, sensor_yres; - int sensor_xtal; - - /* Allows progressive (e. g. non-interlaced) mode */ - int progressive; - - /* Vinmode/Vinctl used at the driver */ - int vinmode, vinctl; - - unsigned int has_audio_class:1; - unsigned int has_alsa_audio:1; - unsigned int is_audio_only:1; - - /* Controls audio streaming */ - struct work_struct wq_trigger; /* Trigger to start/stop audio for alsa module */ - atomic_t stream_started; /* stream should be running if true */ - - struct em28xx_fmt *format; - - struct em28xx_IR *ir; - - /* Some older em28xx chips needs a waiting time after writing */ - unsigned int wait_after_write; - - struct list_head devlist; - - u32 i2s_speed; /* I2S speed for audio digital stream */ - - struct em28xx_audio_mode audio_mode; - - int tuner_type; /* type of the tuner */ - int tuner_addr; /* tuner address */ - int tda9887_conf; - /* i2c i/o */ - struct i2c_adapter i2c_adap; - struct i2c_client i2c_client; - /* video for linux */ - int users; /* user count for exclusive use */ - struct video_device *vdev; /* video for linux device struct */ - v4l2_std_id norm; /* selected tv norm */ - int ctl_freq; /* selected frequency */ - unsigned int ctl_input; /* selected input */ - unsigned int ctl_ainput;/* selected audio input */ - unsigned int ctl_aoutput;/* selected audio output */ - int mute; - int volume; - /* frame properties */ - int width; /* current frame width */ - int height; /* current frame height */ - unsigned hscale; /* horizontal scale factor (see datasheet) */ - unsigned vscale; /* vertical scale factor (see datasheet) */ - int interlaced; /* 1=interlace fileds, 0=just top fileds */ - unsigned int video_bytesread; /* Number of bytes read */ - - unsigned long hash; /* eeprom hash - for boards with generic ID */ - unsigned long i2c_hash; /* i2c devicelist hash - - for boards with generic ID */ - - struct em28xx_audio adev; - - /* states */ - enum em28xx_dev_state state; - - /* vbi related state tracking */ - int capture_type; - int vbi_read; - unsigned char cur_field; - unsigned int vbi_width; - unsigned int vbi_height; /* lines per field */ - - struct work_struct request_module_wk; - - /* locks */ - struct mutex lock; - struct mutex ctrl_urb_lock; /* protects urb_buf */ - /* spinlock_t queue_lock; */ - struct list_head inqueue, outqueue; - struct video_device *vbi_dev; - struct video_device *radio_dev; - - /* resources in use */ - unsigned int resources; - - unsigned char eedata[256]; - - /* Isoc control struct */ - struct em28xx_dmaqueue vidq; - struct em28xx_dmaqueue vbiq; - struct em28xx_usb_isoc_ctl isoc_ctl; - spinlock_t slock; - - /* usb transfer */ - struct usb_device *udev; /* the usb device */ - int alt; /* alternate */ - int max_pkt_size; /* max packet size of isoc transaction */ - int num_alt; /* Number of alternative settings */ - unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ - int dvb_alt; /* alternate for DVB */ - unsigned int dvb_max_pkt_size; /* wMaxPacketSize for DVB */ - char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */ - - /* helper funcs that call usb_control_msg */ - int (*em28xx_write_regs) (struct em28xx *dev, u16 reg, - char *buf, int len); - int (*em28xx_read_reg) (struct em28xx *dev, u16 reg); - int (*em28xx_read_reg_req_len) (struct em28xx *dev, u8 req, u16 reg, - char *buf, int len); - int (*em28xx_write_regs_req) (struct em28xx *dev, u8 req, u16 reg, - char *buf, int len); - int (*em28xx_read_reg_req) (struct em28xx *dev, u8 req, u16 reg); - - enum em28xx_mode mode; - - /* register numbers for GPO/GPIO registers */ - u16 reg_gpo_num, reg_gpio_num; - - /* Caches GPO and GPIO registers */ - unsigned char reg_gpo, reg_gpio; - - /* Snapshot button */ - char snapshot_button_path[30]; /* path of the input dev */ - struct input_dev *sbutton_input_dev; - struct delayed_work sbutton_query_work; - - struct em28xx_dvb *dvb; - - /* I2C keyboard data */ - struct IR_i2c_init_data init_data; -}; - -struct em28xx_ops { - struct list_head next; - char *name; - int id; - int (*init)(struct em28xx *); - int (*fini)(struct em28xx *); -}; - -/* Provided by em28xx-i2c.c */ -void em28xx_do_i2c_scan(struct em28xx *dev); -int em28xx_i2c_register(struct em28xx *dev); -int em28xx_i2c_unregister(struct em28xx *dev); - -/* Provided by em28xx-core.c */ - -u32 em28xx_request_buffers(struct em28xx *dev, u32 count); -void em28xx_queue_unusedframes(struct em28xx *dev); -void em28xx_release_buffers(struct em28xx *dev); - -int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, - char *buf, int len); -int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg); -int em28xx_read_reg(struct em28xx *dev, u16 reg); -int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, - int len); -int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len); -int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val); -int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, - u8 bitmask); - -int em28xx_read_ac97(struct em28xx *dev, u8 reg); -int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val); - -int em28xx_audio_analog_set(struct em28xx *dev); -int em28xx_audio_setup(struct em28xx *dev); - -int em28xx_colorlevels_set_default(struct em28xx *dev); -int em28xx_capture_start(struct em28xx *dev, int start); -int em28xx_vbi_supported(struct em28xx *dev); -int em28xx_set_outfmt(struct em28xx *dev); -int em28xx_resolution_set(struct em28xx *dev); -int em28xx_set_alternate(struct em28xx *dev); -int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode, - int max_packets, int num_bufs, int max_pkt_size); -int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode, - int max_packets, int num_bufs, int max_pkt_size, - int (*isoc_copy) (struct em28xx *dev, struct urb *urb)); -void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode); -void em28xx_stop_urbs(struct em28xx *dev); -int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev); -int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode); -int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio); -void em28xx_wake_i2c(struct em28xx *dev); -int em28xx_register_extension(struct em28xx_ops *dev); -void em28xx_unregister_extension(struct em28xx_ops *dev); -void em28xx_init_extension(struct em28xx *dev); -void em28xx_close_extension(struct em28xx *dev); - -/* Provided by em28xx-video.c */ -int em28xx_register_analog_devices(struct em28xx *dev); -void em28xx_release_analog_resources(struct em28xx *dev); - -/* Provided by em28xx-cards.c */ -extern int em2800_variant_detect(struct usb_device *udev, int model); -extern struct em28xx_board em28xx_boards[]; -extern struct usb_device_id em28xx_id_table[]; -extern const unsigned int em28xx_bcount; -int em28xx_tuner_callback(void *ptr, int component, int command, int arg); -void em28xx_release_resources(struct em28xx *dev); - -/* Provided by em28xx-vbi.c */ -extern struct videobuf_queue_ops em28xx_vbi_qops; - -/* printk macros */ - -#define em28xx_err(fmt, arg...) do {\ - printk(KERN_ERR fmt , ##arg); } while (0) - -#define em28xx_errdev(fmt, arg...) do {\ - printk(KERN_ERR "%s: "fmt,\ - dev->name , ##arg); } while (0) - -#define em28xx_info(fmt, arg...) do {\ - printk(KERN_INFO "%s: "fmt,\ - dev->name , ##arg); } while (0) -#define em28xx_warn(fmt, arg...) do {\ - printk(KERN_WARNING "%s: "fmt,\ - dev->name , ##arg); } while (0) - -static inline int em28xx_compression_disable(struct em28xx *dev) -{ - /* side effect of disabling scaler and mixer */ - return em28xx_write_reg(dev, EM28XX_R26_COMPR, 0x00); -} - -static inline int em28xx_contrast_get(struct em28xx *dev) -{ - return em28xx_read_reg(dev, EM28XX_R20_YGAIN) & 0x1f; -} - -static inline int em28xx_brightness_get(struct em28xx *dev) -{ - return em28xx_read_reg(dev, EM28XX_R21_YOFFSET); -} - -static inline int em28xx_saturation_get(struct em28xx *dev) -{ - return em28xx_read_reg(dev, EM28XX_R22_UVGAIN) & 0x1f; -} - -static inline int em28xx_u_balance_get(struct em28xx *dev) -{ - return em28xx_read_reg(dev, EM28XX_R23_UOFFSET); -} - -static inline int em28xx_v_balance_get(struct em28xx *dev) -{ - return em28xx_read_reg(dev, EM28XX_R24_VOFFSET); -} - -static inline int em28xx_gamma_get(struct em28xx *dev) -{ - return em28xx_read_reg(dev, EM28XX_R14_GAMMA) & 0x3f; -} - -static inline int em28xx_contrast_set(struct em28xx *dev, s32 val) -{ - u8 tmp = (u8) val; - return em28xx_write_regs(dev, EM28XX_R20_YGAIN, &tmp, 1); -} - -static inline int em28xx_brightness_set(struct em28xx *dev, s32 val) -{ - u8 tmp = (u8) val; - return em28xx_write_regs(dev, EM28XX_R21_YOFFSET, &tmp, 1); -} - -static inline int em28xx_saturation_set(struct em28xx *dev, s32 val) -{ - u8 tmp = (u8) val; - return em28xx_write_regs(dev, EM28XX_R22_UVGAIN, &tmp, 1); -} - -static inline int em28xx_u_balance_set(struct em28xx *dev, s32 val) -{ - u8 tmp = (u8) val; - return em28xx_write_regs(dev, EM28XX_R23_UOFFSET, &tmp, 1); -} - -static inline int em28xx_v_balance_set(struct em28xx *dev, s32 val) -{ - u8 tmp = (u8) val; - return em28xx_write_regs(dev, EM28XX_R24_VOFFSET, &tmp, 1); -} - -static inline int em28xx_gamma_set(struct em28xx *dev, s32 val) -{ - u8 tmp = (u8) val; - return em28xx_write_regs(dev, EM28XX_R14_GAMMA, &tmp, 1); -} - -/*FIXME: maxw should be dependent of alt mode */ -static inline unsigned int norm_maxw(struct em28xx *dev) -{ - if (dev->board.is_webcam) - return dev->sensor_xres; - - if (dev->board.max_range_640_480) - return 640; - - return 720; -} - -static inline unsigned int norm_maxh(struct em28xx *dev) -{ - if (dev->board.is_webcam) - return dev->sensor_yres; - - if (dev->board.max_range_640_480) - return 480; - - return (dev->norm & V4L2_STD_625_50) ? 576 : 480; -} -#endif |