summaryrefslogtreecommitdiffstats
path: root/drivers/media/video/em28xx
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2012-08-14 00:13:22 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-08-15 16:25:07 -0300
commit0c0d06cac63ee327ceaab4b5ffe2206574ab86bd (patch)
treee759f0dc3185d97f2a0c6b5cd5e32ea6faa74d40 /drivers/media/video/em28xx
parent84cfe9e79bd5ac11c963f4841158454fefa872f6 (diff)
[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/Kconfig58
-rw-r--r--drivers/media/video/em28xx/Makefile15
-rw-r--r--drivers/media/video/em28xx/em28xx-audio.c751
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c3417
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c1260
-rw-r--r--drivers/media/video/em28xx/em28xx-dvb.c1197
-rw-r--r--drivers/media/video/em28xx/em28xx-i2c.c568
-rw-r--r--drivers/media/video/em28xx/em28xx-input.c645
-rw-r--r--drivers/media/video/em28xx/em28xx-reg.h226
-rw-r--r--drivers/media/video/em28xx/em28xx-vbi.c145
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c2624
-rw-r--r--drivers/media/video/em28xx/em28xx.h809
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 928ef0d0429..00000000000
--- 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 65c7c29e416..00000000000
--- 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 2fdb66ee44a..00000000000
--- 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 ca62b998138..00000000000
--- 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, &regs[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, &regs[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 bed07a6c33f..00000000000
--- 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 a16531fa937..00000000000
--- 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 1683bd9d51e..00000000000
--- 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 97d36b4f19d..00000000000
--- 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 6ff368297f6..00000000000
--- 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 2b4c9cba2d6..00000000000
--- 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 ecb23df7f16..00000000000
--- 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(&reg->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(&reg->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 8757523e686..00000000000
--- 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