diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-09-23 14:30:01 +0200 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-09-23 14:32:35 +0200 |
commit | be304970850806abea880da95fbfb743a4d9f87d (patch) | |
tree | bd926b64bac6198dc05f07611025f56b1246e3ce /drivers/staging | |
parent | [media] tm6000: Fix some CodingStyle issues (diff) | |
download | linux-be304970850806abea880da95fbfb743a4d9f87d.tar.xz linux-be304970850806abea880da95fbfb743a4d9f87d.zip |
[media] move tm6000 to drivers/media/video
The serious bugs got fixed already.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/Kconfig | 2 | ||||
-rw-r--r-- | drivers/staging/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/tm6000/CARDLIST | 16 | ||||
-rw-r--r-- | drivers/staging/tm6000/Kconfig | 33 | ||||
-rw-r--r-- | drivers/staging/tm6000/Makefile | 15 | ||||
-rw-r--r-- | drivers/staging/tm6000/README | 22 | ||||
-rw-r--r-- | drivers/staging/tm6000/TODO | 8 | ||||
-rw-r--r-- | drivers/staging/tm6000/tm6000-alsa.c | 513 | ||||
-rw-r--r-- | drivers/staging/tm6000/tm6000-cards.c | 1402 | ||||
-rw-r--r-- | drivers/staging/tm6000/tm6000-core.c | 965 | ||||
-rw-r--r-- | drivers/staging/tm6000/tm6000-dvb.c | 452 | ||||
-rw-r--r-- | drivers/staging/tm6000/tm6000-i2c.c | 340 | ||||
-rw-r--r-- | drivers/staging/tm6000/tm6000-input.c | 459 | ||||
-rw-r--r-- | drivers/staging/tm6000/tm6000-regs.h | 600 | ||||
-rw-r--r-- | drivers/staging/tm6000/tm6000-stds.c | 659 | ||||
-rw-r--r-- | drivers/staging/tm6000/tm6000-usb-isoc.h | 50 | ||||
-rw-r--r-- | drivers/staging/tm6000/tm6000-video.c | 1813 | ||||
-rw-r--r-- | drivers/staging/tm6000/tm6000.h | 398 |
18 files changed, 0 insertions, 7748 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 06c9081d596d..720927742eb7 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -32,8 +32,6 @@ source "drivers/staging/go7007/Kconfig" source "drivers/staging/cx25821/Kconfig" -source "drivers/staging/tm6000/Kconfig" - source "drivers/staging/cxd2099/Kconfig" source "drivers/staging/usbip/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index f3c5e33bb263..d44d25ed6cf1 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_ET131X) += et131x/ obj-$(CONFIG_SLICOSS) += slicoss/ obj-$(CONFIG_VIDEO_GO7007) += go7007/ obj-$(CONFIG_VIDEO_CX25821) += cx25821/ -obj-$(CONFIG_VIDEO_TM6000) += tm6000/ obj-$(CONFIG_DVB_CXD2099) += cxd2099/ obj-$(CONFIG_LIRC_STAGING) += lirc/ obj-$(CONFIG_USBIP_CORE) += usbip/ diff --git a/drivers/staging/tm6000/CARDLIST b/drivers/staging/tm6000/CARDLIST deleted file mode 100644 index b5edce487997..000000000000 --- a/drivers/staging/tm6000/CARDLIST +++ /dev/null @@ -1,16 +0,0 @@ - 1 -> Generic tm5600 board (tm5600) [6000:0001] - 2 -> Generic tm6000 board (tm6000) [6000:0001] - 3 -> Generic tm6010 board (tm6010) [6000:0002] - 4 -> 10Moons UT821 (tm5600) [6000:0001] - 5 -> 10Moons UT330 (tm5600) - 6 -> ADSTech Dual TV (tm6000) [06e1:f332] - 7 -> FreeCom and similar (tm6000) [14aa:0620] - 8 -> ADSTech Mini Dual TV (tm6000) [06e1:b339] - 9 -> Hauppauge WinTV HVR-900H/USB2 Stick (tm6010) [2040:6600,2040:6601,2040:6610,2040:6611] - 10 -> Beholder Wander (tm6010) [6000:dec0] - 11 -> Beholder Voyager (tm6010) [6000:dec1] - 12 -> TerraTec Cinergy Hybrid XE/Cinergy Hybrid Stick (tm6010) [0ccd:0086,0ccd:00a5] - 13 -> TwinHan TU501 (tm6010) [13d3:3240,13d3:3241,13d3:3243,13d3:3264] - 14 -> Beholder Wander Lite (tm6010) [6000:dec2] - 15 -> Beholder Voyager Lite (tm6010) [6000:dec3] - diff --git a/drivers/staging/tm6000/Kconfig b/drivers/staging/tm6000/Kconfig deleted file mode 100644 index 114eec8a630a..000000000000 --- a/drivers/staging/tm6000/Kconfig +++ /dev/null @@ -1,33 +0,0 @@ -config VIDEO_TM6000 - tristate "TV Master TM5600/6000/6010 driver" - depends on VIDEO_DEV && I2C && INPUT && RC_CORE && USB && EXPERIMENTAL - select VIDEO_TUNER - select MEDIA_TUNER_XC2028 - select MEDIA_TUNER_XC5000 - select VIDEOBUF_VMALLOC - help - Support for TM5600/TM6000/TM6010 USB Device - - Since these cards have no MPEG decoder onboard, they transmit - only compressed MPEG data over the usb bus, so you need - an external software decoder to watch TV on your computer. - - Say Y if you own such a device and want to use it. - -config VIDEO_TM6000_ALSA - tristate "TV Master TM5600/6000/6010 audio support" - depends on VIDEO_TM6000 && SND && EXPERIMENTAL - select SND_PCM - ---help--- - This is a video4linux driver for direct (DMA) audio for - TM5600/TM6000/TM6010 USB Devices. - - To compile this driver as a module, choose M here: the - module will be called tm6000-alsa. - -config VIDEO_TM6000_DVB - tristate "DVB Support for tm6000 based TV cards" - depends on VIDEO_TM6000 && DVB_CORE && USB && EXPERIMENTAL - select DVB_ZL10353 - ---help--- - This adds support for DVB cards based on the tm5600/tm6000 chip. diff --git a/drivers/staging/tm6000/Makefile b/drivers/staging/tm6000/Makefile deleted file mode 100644 index 395515b4a888..000000000000 --- a/drivers/staging/tm6000/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -tm6000-y := tm6000-cards.o \ - tm6000-core.o \ - tm6000-i2c.o \ - tm6000-video.o \ - tm6000-stds.o \ - tm6000-input.o - -obj-$(CONFIG_VIDEO_TM6000) += tm6000.o -obj-$(CONFIG_VIDEO_TM6000_ALSA) += tm6000-alsa.o -obj-$(CONFIG_VIDEO_TM6000_DVB) += tm6000-dvb.o - -ccflags-y := -Idrivers/media/video -ccflags-y += -Idrivers/media/common/tuners -ccflags-y += -Idrivers/media/dvb/dvb-core -ccflags-y += -Idrivers/media/dvb/frontends diff --git a/drivers/staging/tm6000/README b/drivers/staging/tm6000/README deleted file mode 100644 index c340ebc2ee9f..000000000000 --- a/drivers/staging/tm6000/README +++ /dev/null @@ -1,22 +0,0 @@ -Todo: - - Fix the loss of some blocks when receiving the video URB's - - Add a lock at tm6000_read_write_usb() to prevent two simultaneous access to the - URB control transfers - - Properly add the locks at tm6000-video - - Add audio support - - Add vbi support - - Add IR support - - Do several cleanups - - I think that frame1/frame0 are inverted. This causes a funny effect at the image. - the fix is trivial, but require some tests - - My tm6010 devices sometimes insist on stop working. I need to turn them off, removing - from my machine and wait for a while for it to work again. I'm starting to think that - it is an overheat issue - is there a workaround that we could do? - - Sometimes, tm6010 doesn't read eeprom at the proper time (hardware bug). So, the device - got miss-detected as a "generic" tm6000. This can be really bad if the tuner is the - Low Power one, as it may result on loading the high power firmware, that could damage - the device. Maybe we may read eeprom to double check, when the device is marked as "generic" - - Coding Style fixes - - sparse cleanups - -Please send patches to linux-media@vger.kernel.org diff --git a/drivers/staging/tm6000/TODO b/drivers/staging/tm6000/TODO deleted file mode 100644 index 135d0ea3ad70..000000000000 --- a/drivers/staging/tm6000/TODO +++ /dev/null @@ -1,8 +0,0 @@ -There a few things to do before putting this driver in production: - - IR NEC with tm5600/6000 TV cards - - IR RC5 with tm5600/6000/6010 TV cards - - CodingStyle; - - Fix audio; - - Fix some panic/OOPS conditions. - -Please send patches to linux-media@vger.kernel.org diff --git a/drivers/staging/tm6000/tm6000-alsa.c b/drivers/staging/tm6000/tm6000-alsa.c deleted file mode 100644 index 7d675c72fd47..000000000000 --- a/drivers/staging/tm6000/tm6000-alsa.c +++ /dev/null @@ -1,513 +0,0 @@ -/* - * - * Support for audio capture for tm5600/6000/6010 - * (c) 2007-2008 Mauro Carvalho Chehab <mchehab@redhat.com> - * - * Based on cx88-alsa.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/interrupt.h> -#include <linux/usb.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> - -#include <linux/delay.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/control.h> -#include <sound/initval.h> - - -#include "tm6000.h" -#include "tm6000-regs.h" - -#undef dprintk - -#define dprintk(level, fmt, arg...) do { \ - if (debug >= level) \ - printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg); \ - } while (0) - -/**************************************************************************** - Module global static vars - ****************************************************************************/ - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ - -static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; - -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable tm6000x soundcard. default enabled."); - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for tm6000x capture interface(s)."); - - -/**************************************************************************** - Module macros - ****************************************************************************/ - -MODULE_DESCRIPTION("ALSA driver module for tm5600/tm6000/tm6010 based TV cards"); -MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Trident,tm5600}," - "{{Trident,tm6000}," - "{{Trident,tm6010}"); -static unsigned int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "enable debug messages"); - -/**************************************************************************** - Module specific funtions - ****************************************************************************/ - -/* - * BOARD Specific: Sets audio DMA - */ - -static int _tm6000_start_audio_dma(struct snd_tm6000_card *chip) -{ - struct tm6000_core *core = chip->core; - - dprintk(1, "Starting audio DMA\n"); - - /* Enables audio */ - tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_IF, 0x40, 0x40); - - tm6000_set_audio_bitrate(core, 48000); - - return 0; -} - -/* - * BOARD Specific: Resets audio DMA - */ -static int _tm6000_stop_audio_dma(struct snd_tm6000_card *chip) -{ - struct tm6000_core *core = chip->core; - - dprintk(1, "Stopping audio DMA\n"); - - /* Disables audio */ - tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_IF, 0x00, 0x40); - - return 0; -} - -static void dsp_buffer_free(struct snd_pcm_substream *substream) -{ - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - - dprintk(2, "Freeing buffer\n"); - - vfree(substream->runtime->dma_area); - substream->runtime->dma_area = NULL; - substream->runtime->dma_bytes = 0; -} - -static int dsp_buffer_alloc(struct snd_pcm_substream *substream, int size) -{ - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - - dprintk(2, "Allocating buffer\n"); - - if (substream->runtime->dma_area) { - if (substream->runtime->dma_bytes > size) - return 0; - - dsp_buffer_free(substream); - } - - substream->runtime->dma_area = vmalloc(size); - if (!substream->runtime->dma_area) - return -ENOMEM; - - substream->runtime->dma_bytes = size; - - return 0; -} - - -/**************************************************************************** - ALSA PCM Interface - ****************************************************************************/ - -/* - * Digital hardware definition - */ -#define DEFAULT_FIFO_SIZE 4096 - -static struct snd_pcm_hardware snd_tm6000_digital_hw = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - - .rates = SNDRV_PCM_RATE_CONTINUOUS, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .period_bytes_min = 64, - .period_bytes_max = 12544, - .periods_min = 1, - .periods_max = 98, - .buffer_bytes_max = 62720 * 8, -}; - -/* - * audio pcm capture open callback - */ -static int snd_tm6000_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - err = snd_pcm_hw_constraint_pow2(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIODS); - if (err < 0) - goto _error; - - chip->substream = substream; - - runtime->hw = snd_tm6000_digital_hw; - - return 0; -_error: - dprintk(1, "Error opening PCM!\n"); - return err; -} - -/* - * audio close callback - */ -static int snd_tm6000_close(struct snd_pcm_substream *substream) -{ - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - struct tm6000_core *core = chip->core; - - if (atomic_read(&core->stream_started) > 0) { - atomic_set(&core->stream_started, 0); - schedule_work(&core->wq_trigger); - } - - return 0; -} - -static int tm6000_fillbuf(struct tm6000_core *core, char *buf, int size) -{ - struct snd_tm6000_card *chip = core->adev; - struct snd_pcm_substream *substream = chip->substream; - struct snd_pcm_runtime *runtime; - int period_elapsed = 0; - unsigned int stride, buf_pos; - int length; - - if (atomic_read(&core->stream_started) == 0) - return 0; - - if (!size || !substream) { - dprintk(1, "substream was NULL\n"); - return -EINVAL; - } - - runtime = substream->runtime; - if (!runtime || !runtime->dma_area) { - dprintk(1, "runtime was NULL\n"); - return -EINVAL; - } - - buf_pos = chip->buf_pos; - stride = runtime->frame_bits >> 3; - - if (stride == 0) { - dprintk(1, "stride is zero\n"); - return -EINVAL; - } - - length = size / stride; - if (length == 0) { - dprintk(1, "%s: length was zero\n", __func__); - return -EINVAL; - } - - dprintk(1, "Copying %d bytes at %p[%d] - buf size=%d x %d\n", size, - runtime->dma_area, buf_pos, - (unsigned int)runtime->buffer_size, stride); - - if (buf_pos + length >= runtime->buffer_size) { - unsigned int cnt = runtime->buffer_size - buf_pos; - memcpy(runtime->dma_area + buf_pos * stride, buf, cnt * stride); - memcpy(runtime->dma_area, buf + cnt * stride, - length * stride - cnt * stride); - } else - memcpy(runtime->dma_area + buf_pos * stride, buf, - length * stride); - - snd_pcm_stream_lock(substream); - - chip->buf_pos += length; - if (chip->buf_pos >= runtime->buffer_size) - chip->buf_pos -= runtime->buffer_size; - - chip->period_pos += length; - if (chip->period_pos >= runtime->period_size) { - chip->period_pos -= runtime->period_size; - period_elapsed = 1; - } - - snd_pcm_stream_unlock(substream); - - if (period_elapsed) - snd_pcm_period_elapsed(substream); - - return 0; -} - -/* - * hw_params callback - */ -static int snd_tm6000_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - int size, rc; - - size = params_period_bytes(hw_params) * params_periods(hw_params); - - rc = dsp_buffer_alloc(substream, size); - if (rc < 0) - return rc; - - return 0; -} - -/* - * hw free callback - */ -static int snd_tm6000_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - struct tm6000_core *core = chip->core; - - if (atomic_read(&core->stream_started) > 0) { - atomic_set(&core->stream_started, 0); - schedule_work(&core->wq_trigger); - } - - dsp_buffer_free(substream); - return 0; -} - -/* - * prepare callback - */ -static int snd_tm6000_prepare(struct snd_pcm_substream *substream) -{ - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - - chip->buf_pos = 0; - chip->period_pos = 0; - - return 0; -} - - -/* - * trigger callback - */ -static void audio_trigger(struct work_struct *work) -{ - struct tm6000_core *core = container_of(work, struct tm6000_core, - wq_trigger); - struct snd_tm6000_card *chip = core->adev; - - if (atomic_read(&core->stream_started)) { - dprintk(1, "starting capture"); - _tm6000_start_audio_dma(chip); - } else { - dprintk(1, "stopping capture"); - _tm6000_stop_audio_dma(chip); - } -} - -static int snd_tm6000_card_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - struct tm6000_core *core = chip->core; - int err = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - atomic_set(&core->stream_started, 1); - break; - case SNDRV_PCM_TRIGGER_STOP: - atomic_set(&core->stream_started, 0); - break; - default: - err = -EINVAL; - break; - } - schedule_work(&core->wq_trigger); - - return err; -} -/* - * pointer callback - */ -static snd_pcm_uframes_t snd_tm6000_pointer(struct snd_pcm_substream *substream) -{ - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - - return chip->buf_pos; -} - -/* - * operators - */ -static struct snd_pcm_ops snd_tm6000_pcm_ops = { - .open = snd_tm6000_pcm_open, - .close = snd_tm6000_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_tm6000_hw_params, - .hw_free = snd_tm6000_hw_free, - .prepare = snd_tm6000_prepare, - .trigger = snd_tm6000_card_trigger, - .pointer = snd_tm6000_pointer, -}; - -/* - * create a PCM device - */ - -/* FIXME: Control interface - How to control volume/mute? */ - -/**************************************************************************** - Basic Flow for Sound Devices - ****************************************************************************/ - -/* - * Alsa Constructor - Component probe - */ -static int tm6000_audio_init(struct tm6000_core *dev) -{ - struct snd_card *card; - struct snd_tm6000_card *chip; - int rc; - static int devnr; - char component[14]; - struct snd_pcm *pcm; - - if (!dev) - return 0; - - if (devnr >= SNDRV_CARDS) - return -ENODEV; - - if (!enable[devnr]) - return -ENOENT; - - rc = snd_card_create(index[devnr], "tm6000", THIS_MODULE, 0, &card); - if (rc < 0) { - snd_printk(KERN_ERR "cannot create card instance %d\n", devnr); - return rc; - } - strcpy(card->driver, "tm6000-alsa"); - strcpy(card->shortname, "TM5600/60x0"); - sprintf(card->longname, "TM5600/60x0 Audio at bus %d device %d", - dev->udev->bus->busnum, dev->udev->devnum); - - sprintf(component, "USB%04x:%04x", - le16_to_cpu(dev->udev->descriptor.idVendor), - le16_to_cpu(dev->udev->descriptor.idProduct)); - snd_component_add(card, component); - snd_card_set_dev(card, &dev->udev->dev); - - chip = kzalloc(sizeof(struct snd_tm6000_card), GFP_KERNEL); - if (!chip) { - rc = -ENOMEM; - goto error; - } - - chip->core = dev; - chip->card = card; - dev->adev = chip; - spin_lock_init(&chip->reg_lock); - - rc = snd_pcm_new(card, "TM6000 Audio", 0, 0, 1, &pcm); - if (rc < 0) - goto error_chip; - - pcm->info_flags = 0; - pcm->private_data = chip; - strcpy(pcm->name, "Trident TM5600/60x0"); - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_tm6000_pcm_ops); - - INIT_WORK(&dev->wq_trigger, audio_trigger); - rc = snd_card_register(card); - if (rc < 0) - goto error_chip; - - dprintk(1, "Registered audio driver for %s\n", card->longname); - - return 0; - -error_chip: - kfree(chip); - dev->adev = NULL; -error: - snd_card_free(card); - return rc; -} - -static int tm6000_audio_fini(struct tm6000_core *dev) -{ - struct snd_tm6000_card *chip = dev->adev; - - if (!dev) - return 0; - - if (!chip) - return 0; - - if (!chip->card) - return 0; - - snd_card_free(chip->card); - chip->card = NULL; - kfree(chip); - dev->adev = NULL; - - return 0; -} - -static struct tm6000_ops audio_ops = { - .type = TM6000_AUDIO, - .name = "TM6000 Audio Extension", - .init = tm6000_audio_init, - .fini = tm6000_audio_fini, - .fillbuf = tm6000_fillbuf, -}; - -static int __init tm6000_alsa_register(void) -{ - return tm6000_register_extension(&audio_ops); -} - -static void __exit tm6000_alsa_unregister(void) -{ - tm6000_unregister_extension(&audio_ops); -} - -module_init(tm6000_alsa_register); -module_exit(tm6000_alsa_unregister); diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/staging/tm6000/tm6000-cards.c deleted file mode 100644 index ec2578a0fdf7..000000000000 --- a/drivers/staging/tm6000/tm6000-cards.c +++ /dev/null @@ -1,1402 +0,0 @@ -/* - * tm6000-cards.c - driver for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 - * - * 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/pci.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/usb.h> -#include <linux/slab.h> -#include <media/v4l2-common.h> -#include <media/tuner.h> -#include <media/tvaudio.h> -#include <media/i2c-addr.h> -#include <media/rc-map.h> - -#include "tm6000.h" -#include "tm6000-regs.h" -#include "tuner-xc2028.h" -#include "xc5000.h" - -#define TM6000_BOARD_UNKNOWN 0 -#define TM5600_BOARD_GENERIC 1 -#define TM6000_BOARD_GENERIC 2 -#define TM6010_BOARD_GENERIC 3 -#define TM5600_BOARD_10MOONS_UT821 4 -#define TM5600_BOARD_10MOONS_UT330 5 -#define TM6000_BOARD_ADSTECH_DUAL_TV 6 -#define TM6000_BOARD_FREECOM_AND_SIMILAR 7 -#define TM6000_BOARD_ADSTECH_MINI_DUAL_TV 8 -#define TM6010_BOARD_HAUPPAUGE_900H 9 -#define TM6010_BOARD_BEHOLD_WANDER 10 -#define TM6010_BOARD_BEHOLD_VOYAGER 11 -#define TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE 12 -#define TM6010_BOARD_TWINHAN_TU501 13 -#define TM6010_BOARD_BEHOLD_WANDER_LITE 14 -#define TM6010_BOARD_BEHOLD_VOYAGER_LITE 15 -#define TM5600_BOARD_TERRATEC_GRABSTER 16 - -#define is_generic(model) ((model == TM6000_BOARD_UNKNOWN) || \ - (model == TM5600_BOARD_GENERIC) || \ - (model == TM6000_BOARD_GENERIC) || \ - (model == TM6010_BOARD_GENERIC)) - -#define TM6000_MAXBOARDS 16 -static unsigned int card[] = {[0 ... (TM6000_MAXBOARDS - 1)] = UNSET }; - -module_param_array(card, int, NULL, 0444); - -static unsigned long tm6000_devused; - - -struct tm6000_board { - char *name; - char eename[16]; /* EEPROM name */ - unsigned eename_size; /* size of EEPROM name */ - unsigned eename_pos; /* Position where it appears at ROM */ - - struct tm6000_capabilities caps; - - enum tm6000_devtype type; /* variant of the chipset */ - int tuner_type; /* type of the tuner */ - int tuner_addr; /* tuner address */ - int demod_addr; /* demodulator address */ - - struct tm6000_gpio gpio; - - struct tm6000_input vinput[3]; - struct tm6000_input rinput; - - char *ir_codes; -}; - -static struct tm6000_board tm6000_boards[] = { - [TM6000_BOARD_UNKNOWN] = { - .name = "Unknown tm6000 video grabber", - .caps = { - .has_tuner = 1, - .has_eeprom = 1, - }, - .gpio = { - .tuner_reset = TM6000_GPIO_1, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_ADC1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM5600_BOARD_GENERIC] = { - .name = "Generic tm5600 board", - .type = TM5600, - .tuner_type = TUNER_XC2028, - .tuner_addr = 0xc2 >> 1, - .caps = { - .has_tuner = 1, - .has_eeprom = 1, - }, - .gpio = { - .tuner_reset = TM6000_GPIO_1, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_ADC1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM6000_BOARD_GENERIC] = { - .name = "Generic tm6000 board", - .tuner_type = TUNER_XC2028, - .tuner_addr = 0xc2 >> 1, - .caps = { - .has_tuner = 1, - .has_eeprom = 1, - }, - .gpio = { - .tuner_reset = TM6000_GPIO_1, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_ADC1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM6010_BOARD_GENERIC] = { - .name = "Generic tm6010 board", - .type = TM6010, - .tuner_type = TUNER_XC2028, - .tuner_addr = 0xc2 >> 1, - .demod_addr = 0x1e >> 1, - .caps = { - .has_tuner = 1, - .has_dvb = 1, - .has_zl10353 = 1, - .has_eeprom = 1, - .has_remote = 1, - }, - .gpio = { - .tuner_reset = TM6010_GPIO_2, - .tuner_on = TM6010_GPIO_3, - .demod_reset = TM6010_GPIO_1, - .demod_on = TM6010_GPIO_4, - .power_led = TM6010_GPIO_7, - .dvb_led = TM6010_GPIO_5, - .ir = TM6010_GPIO_0, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_SIF1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM5600_BOARD_10MOONS_UT821] = { - .name = "10Moons UT 821", - .tuner_type = TUNER_XC2028, - .eename = { '1', '0', 'M', 'O', 'O', 'N', 'S', '5', '6', '0', '0', 0xff, 0x45, 0x5b}, - .eename_size = 14, - .eename_pos = 0x14, - .type = TM5600, - .tuner_addr = 0xc2 >> 1, - .caps = { - .has_tuner = 1, - .has_eeprom = 1, - }, - .gpio = { - .tuner_reset = TM6000_GPIO_1, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_ADC1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM5600_BOARD_10MOONS_UT330] = { - .name = "10Moons UT 330", - .tuner_type = TUNER_PHILIPS_FQ1216AME_MK4, - .tuner_addr = 0xc8 >> 1, - .caps = { - .has_tuner = 1, - .has_dvb = 0, - .has_zl10353 = 0, - .has_eeprom = 1, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_ADC1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM6000_BOARD_ADSTECH_DUAL_TV] = { - .name = "ADSTECH Dual TV USB", - .tuner_type = TUNER_XC2028, - .tuner_addr = 0xc8 >> 1, - .caps = { - .has_tuner = 1, - .has_tda9874 = 1, - .has_dvb = 1, - .has_zl10353 = 1, - .has_eeprom = 1, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_ADC1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM6000_BOARD_FREECOM_AND_SIMILAR] = { - .name = "Freecom Hybrid Stick / Moka DVB-T Receiver Dual", - .tuner_type = TUNER_XC2028, /* has a XC3028 */ - .tuner_addr = 0xc2 >> 1, - .demod_addr = 0x1e >> 1, - .caps = { - .has_tuner = 1, - .has_dvb = 1, - .has_zl10353 = 1, - .has_eeprom = 0, - .has_remote = 1, - }, - .gpio = { - .tuner_reset = TM6000_GPIO_4, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_ADC1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM6000_BOARD_ADSTECH_MINI_DUAL_TV] = { - .name = "ADSTECH Mini Dual TV USB", - .tuner_type = TUNER_XC2028, /* has a XC3028 */ - .tuner_addr = 0xc8 >> 1, - .demod_addr = 0x1e >> 1, - .caps = { - .has_tuner = 1, - .has_dvb = 1, - .has_zl10353 = 1, - .has_eeprom = 0, - }, - .gpio = { - .tuner_reset = TM6000_GPIO_4, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_ADC1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM6010_BOARD_HAUPPAUGE_900H] = { - .name = "Hauppauge WinTV HVR-900H / WinTV USB2-Stick", - .eename = { 'H', 0, 'V', 0, 'R', 0, '9', 0, '0', 0, '0', 0, 'H', 0 }, - .eename_size = 14, - .eename_pos = 0x42, - .tuner_type = TUNER_XC2028, /* has a XC3028 */ - .tuner_addr = 0xc2 >> 1, - .demod_addr = 0x1e >> 1, - .type = TM6010, - .caps = { - .has_tuner = 1, - .has_dvb = 1, - .has_zl10353 = 1, - .has_eeprom = 1, - .has_remote = 1, - }, - .gpio = { - .tuner_reset = TM6010_GPIO_2, - .tuner_on = TM6010_GPIO_3, - .demod_reset = TM6010_GPIO_1, - .demod_on = TM6010_GPIO_4, - .power_led = TM6010_GPIO_7, - .dvb_led = TM6010_GPIO_5, - .ir = TM6010_GPIO_0, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_SIF1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM6010_BOARD_BEHOLD_WANDER] = { - .name = "Beholder Wander DVB-T/TV/FM USB2.0", - .tuner_type = TUNER_XC5000, - .tuner_addr = 0xc2 >> 1, - .demod_addr = 0x1e >> 1, - .type = TM6010, - .caps = { - .has_tuner = 1, - .has_dvb = 1, - .has_zl10353 = 1, - .has_eeprom = 1, - .has_remote = 1, - .has_radio = 1, - }, - .gpio = { - .tuner_reset = TM6010_GPIO_0, - .demod_reset = TM6010_GPIO_1, - .power_led = TM6010_GPIO_6, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_SIF1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - .rinput = { - .type = TM6000_INPUT_RADIO, - .amux = TM6000_AMUX_ADC1, - }, - }, - [TM6010_BOARD_BEHOLD_VOYAGER] = { - .name = "Beholder Voyager TV/FM USB2.0", - .tuner_type = TUNER_XC5000, - .tuner_addr = 0xc2 >> 1, - .type = TM6010, - .caps = { - .has_tuner = 1, - .has_dvb = 0, - .has_zl10353 = 0, - .has_eeprom = 1, - .has_remote = 1, - .has_radio = 1, - }, - .gpio = { - .tuner_reset = TM6010_GPIO_0, - .power_led = TM6010_GPIO_6, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_SIF1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - .rinput = { - .type = TM6000_INPUT_RADIO, - .amux = TM6000_AMUX_ADC1, - }, - }, - [TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE] = { - .name = "Terratec Cinergy Hybrid XE / Cinergy Hybrid-Stick", - .tuner_type = TUNER_XC2028, /* has a XC3028 */ - .tuner_addr = 0xc2 >> 1, - .demod_addr = 0x1e >> 1, - .type = TM6010, - .caps = { - .has_tuner = 1, - .has_dvb = 1, - .has_zl10353 = 1, - .has_eeprom = 1, - .has_remote = 1, - .has_radio = 1, - }, - .gpio = { - .tuner_reset = TM6010_GPIO_2, - .tuner_on = TM6010_GPIO_3, - .demod_reset = TM6010_GPIO_1, - .demod_on = TM6010_GPIO_4, - .power_led = TM6010_GPIO_7, - .dvb_led = TM6010_GPIO_5, - .ir = TM6010_GPIO_0, - }, - .ir_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_SIF1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - .rinput = { - .type = TM6000_INPUT_RADIO, - .amux = TM6000_AMUX_SIF1, - }, - }, - [TM5600_BOARD_TERRATEC_GRABSTER] = { - .name = "Terratec Grabster AV 150/250 MX", - .type = TM5600, - .tuner_type = TUNER_ABSENT, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_ADC1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM6010_BOARD_TWINHAN_TU501] = { - .name = "Twinhan TU501(704D1)", - .tuner_type = TUNER_XC2028, /* has a XC3028 */ - .tuner_addr = 0xc2 >> 1, - .demod_addr = 0x1e >> 1, - .type = TM6010, - .caps = { - .has_tuner = 1, - .has_dvb = 1, - .has_zl10353 = 1, - .has_eeprom = 1, - .has_remote = 1, - }, - .gpio = { - .tuner_reset = TM6010_GPIO_2, - .tuner_on = TM6010_GPIO_3, - .demod_reset = TM6010_GPIO_1, - .demod_on = TM6010_GPIO_4, - .power_led = TM6010_GPIO_7, - .dvb_led = TM6010_GPIO_5, - .ir = TM6010_GPIO_0, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_SIF1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM6010_BOARD_BEHOLD_WANDER_LITE] = { - .name = "Beholder Wander Lite DVB-T/TV/FM USB2.0", - .tuner_type = TUNER_XC5000, - .tuner_addr = 0xc2 >> 1, - .demod_addr = 0x1e >> 1, - .type = TM6010, - .caps = { - .has_tuner = 1, - .has_dvb = 1, - .has_zl10353 = 1, - .has_eeprom = 1, - .has_remote = 0, - .has_radio = 1, - }, - .gpio = { - .tuner_reset = TM6010_GPIO_0, - .demod_reset = TM6010_GPIO_1, - .power_led = TM6010_GPIO_6, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_SIF1, - }, - }, - .rinput = { - .type = TM6000_INPUT_RADIO, - .amux = TM6000_AMUX_ADC1, - }, - }, - [TM6010_BOARD_BEHOLD_VOYAGER_LITE] = { - .name = "Beholder Voyager Lite TV/FM USB2.0", - .tuner_type = TUNER_XC5000, - .tuner_addr = 0xc2 >> 1, - .type = TM6010, - .caps = { - .has_tuner = 1, - .has_dvb = 0, - .has_zl10353 = 0, - .has_eeprom = 1, - .has_remote = 0, - .has_radio = 1, - }, - .gpio = { - .tuner_reset = TM6010_GPIO_0, - .power_led = TM6010_GPIO_6, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_SIF1, - }, - }, - .rinput = { - .type = TM6000_INPUT_RADIO, - .amux = TM6000_AMUX_ADC1, - }, - }, -}; - -/* table of devices that work with this driver */ -static struct usb_device_id tm6000_id_table[] = { - { USB_DEVICE(0x6000, 0x0001), .driver_info = TM5600_BOARD_GENERIC }, - { USB_DEVICE(0x6000, 0x0002), .driver_info = TM6010_BOARD_GENERIC }, - { USB_DEVICE(0x06e1, 0xf332), .driver_info = TM6000_BOARD_ADSTECH_DUAL_TV }, - { USB_DEVICE(0x14aa, 0x0620), .driver_info = TM6000_BOARD_FREECOM_AND_SIMILAR }, - { USB_DEVICE(0x06e1, 0xb339), .driver_info = TM6000_BOARD_ADSTECH_MINI_DUAL_TV }, - { USB_DEVICE(0x2040, 0x6600), .driver_info = TM6010_BOARD_HAUPPAUGE_900H }, - { USB_DEVICE(0x2040, 0x6601), .driver_info = TM6010_BOARD_HAUPPAUGE_900H }, - { USB_DEVICE(0x2040, 0x6610), .driver_info = TM6010_BOARD_HAUPPAUGE_900H }, - { USB_DEVICE(0x2040, 0x6611), .driver_info = TM6010_BOARD_HAUPPAUGE_900H }, - { USB_DEVICE(0x6000, 0xdec0), .driver_info = TM6010_BOARD_BEHOLD_WANDER }, - { USB_DEVICE(0x6000, 0xdec1), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER }, - { USB_DEVICE(0x0ccd, 0x0086), .driver_info = TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE }, - { USB_DEVICE(0x0ccd, 0x00A5), .driver_info = TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE }, - { USB_DEVICE(0x0ccd, 0x0079), .driver_info = TM5600_BOARD_TERRATEC_GRABSTER }, - { USB_DEVICE(0x13d3, 0x3240), .driver_info = TM6010_BOARD_TWINHAN_TU501 }, - { USB_DEVICE(0x13d3, 0x3241), .driver_info = TM6010_BOARD_TWINHAN_TU501 }, - { USB_DEVICE(0x13d3, 0x3243), .driver_info = TM6010_BOARD_TWINHAN_TU501 }, - { USB_DEVICE(0x13d3, 0x3264), .driver_info = TM6010_BOARD_TWINHAN_TU501 }, - { USB_DEVICE(0x6000, 0xdec2), .driver_info = TM6010_BOARD_BEHOLD_WANDER_LITE }, - { USB_DEVICE(0x6000, 0xdec3), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER_LITE }, - { } -}; - -/* Control power led for show some activity */ -void tm6000_flash_led(struct tm6000_core *dev, u8 state) -{ - /* Power LED unconfigured */ - if (!dev->gpio.power_led) - return; - - /* ON Power LED */ - if (state) { - switch (dev->model) { - case TM6010_BOARD_HAUPPAUGE_900H: - case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: - case TM6010_BOARD_TWINHAN_TU501: - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.power_led, 0x00); - break; - case TM6010_BOARD_BEHOLD_WANDER: - case TM6010_BOARD_BEHOLD_VOYAGER: - case TM6010_BOARD_BEHOLD_WANDER_LITE: - case TM6010_BOARD_BEHOLD_VOYAGER_LITE: - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.power_led, 0x01); - break; - } - } - /* OFF Power LED */ - else { - switch (dev->model) { - case TM6010_BOARD_HAUPPAUGE_900H: - case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: - case TM6010_BOARD_TWINHAN_TU501: - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.power_led, 0x01); - break; - case TM6010_BOARD_BEHOLD_WANDER: - case TM6010_BOARD_BEHOLD_VOYAGER: - case TM6010_BOARD_BEHOLD_WANDER_LITE: - case TM6010_BOARD_BEHOLD_VOYAGER_LITE: - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.power_led, 0x00); - break; - } - } -} - -/* Tuner callback to provide the proper gpio changes needed for xc5000 */ -int tm6000_xc5000_callback(void *ptr, int component, int command, int arg) -{ - int rc = 0; - struct tm6000_core *dev = ptr; - - if (dev->tuner_type != TUNER_XC5000) - return 0; - - switch (command) { - case XC5000_TUNER_RESET: - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x01); - msleep(15); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x00); - msleep(15); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x01); - break; - } - return rc; -} -EXPORT_SYMBOL_GPL(tm6000_xc5000_callback); - -/* Tuner callback to provide the proper gpio changes needed for xc2028 */ - -int tm6000_tuner_callback(void *ptr, int component, int command, int arg) -{ - int rc = 0; - struct tm6000_core *dev = ptr; - - if (dev->tuner_type != TUNER_XC2028) - return 0; - - switch (command) { - case XC2028_RESET_CLK: - tm6000_ir_wait(dev, 0); - - tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, - 0x02, arg); - msleep(10); - rc = tm6000_i2c_reset(dev, 10); - break; - case XC2028_TUNER_RESET: - /* Reset codes during load firmware */ - switch (arg) { - case 0: - /* newer tuner can faster reset */ - switch (dev->model) { - case TM5600_BOARD_10MOONS_UT821: - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x01); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - 0x300, 0x01); - msleep(10); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x00); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - 0x300, 0x00); - msleep(10); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x01); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - 0x300, 0x01); - break; - case TM6010_BOARD_HAUPPAUGE_900H: - case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: - case TM6010_BOARD_TWINHAN_TU501: - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x01); - msleep(60); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x00); - msleep(75); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x01); - msleep(60); - break; - default: - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x00); - msleep(130); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x01); - msleep(130); - break; - } - - tm6000_ir_wait(dev, 1); - break; - case 1: - tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, - 0x02, 0x01); - msleep(10); - break; - case 2: - rc = tm6000_i2c_reset(dev, 100); - break; - } - break; - case XC2028_I2C_FLUSH: - tm6000_set_reg(dev, REQ_50_SET_START, 0, 0); - tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0); - break; - } - return rc; -} -EXPORT_SYMBOL_GPL(tm6000_tuner_callback); - -int tm6000_cards_setup(struct tm6000_core *dev) -{ - /* - * Board-specific initialization sequence. Handles all GPIO - * initialization sequences that are board-specific. - * Up to now, all found devices use GPIO1 and GPIO4 at the same way. - * Probably, they're all based on some reference device. Due to that, - * there's a common routine at the end to handle those GPIO's. Devices - * that use different pinups or init sequences can just return at - * the board-specific session. - */ - switch (dev->model) { - case TM6010_BOARD_HAUPPAUGE_900H: - case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: - case TM6010_BOARD_TWINHAN_TU501: - case TM6010_BOARD_GENERIC: - /* Turn xceive 3028 on */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.tuner_on, 0x01); - msleep(15); - /* Turn zarlink zl10353 on */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x00); - msleep(15); - /* Reset zarlink zl10353 */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x00); - msleep(50); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x01); - msleep(15); - /* Turn zarlink zl10353 off */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x01); - msleep(15); - /* ir ? */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.ir, 0x01); - msleep(15); - /* Power led on (blue) */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x00); - msleep(15); - /* DVB led off (orange) */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.dvb_led, 0x01); - msleep(15); - /* Turn zarlink zl10353 on */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x00); - msleep(15); - break; - case TM6010_BOARD_BEHOLD_WANDER: - case TM6010_BOARD_BEHOLD_WANDER_LITE: - /* Power led on (blue) */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x01); - msleep(15); - /* Reset zarlink zl10353 */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x00); - msleep(50); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x01); - msleep(15); - break; - case TM6010_BOARD_BEHOLD_VOYAGER: - case TM6010_BOARD_BEHOLD_VOYAGER_LITE: - /* Power led on (blue) */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x01); - msleep(15); - break; - default: - break; - } - - /* - * Default initialization. Most of the devices seem to use GPIO1 - * and GPIO4.on the same way, so, this handles the common sequence - * used by most devices. - * If a device uses a different sequence or different GPIO pins for - * reset, just add the code at the board-specific part - */ - - if (dev->gpio.tuner_reset) { - int rc; - int i; - - for (i = 0; i < 2; i++) { - rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x00); - if (rc < 0) { - printk(KERN_ERR "Error %i doing tuner reset\n", rc); - return rc; - } - - msleep(10); /* Just to be conservative */ - rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x01); - if (rc < 0) { - printk(KERN_ERR "Error %i doing tuner reset\n", rc); - return rc; - } - } - } else { - printk(KERN_ERR "Tuner reset is not configured\n"); - return -1; - } - - msleep(50); - - return 0; -}; - -static void tm6000_config_tuner(struct tm6000_core *dev) -{ - struct tuner_setup tun_setup; - - /* Load tuner module */ - v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tuner", dev->tuner_addr, NULL); - - memset(&tun_setup, 0, sizeof(tun_setup)); - tun_setup.type = dev->tuner_type; - tun_setup.addr = dev->tuner_addr; - - tun_setup.mode_mask = 0; - if (dev->caps.has_tuner) - tun_setup.mode_mask |= (T_ANALOG_TV | T_RADIO); - - switch (dev->tuner_type) { - case TUNER_XC2028: - tun_setup.tuner_callback = tm6000_tuner_callback; - break; - case TUNER_XC5000: - tun_setup.tuner_callback = tm6000_xc5000_callback; - break; - } - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup); - - switch (dev->tuner_type) { - case 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)); - - ctl.demod = XC3028_FE_ZARLINK456; - - xc2028_cfg.tuner = TUNER_XC2028; - xc2028_cfg.priv = &ctl; - - switch (dev->model) { - case TM6010_BOARD_HAUPPAUGE_900H: - case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: - case TM6010_BOARD_TWINHAN_TU501: - ctl.fname = "xc3028L-v36.fw"; - break; - default: - if (dev->dev_type == TM6010) - ctl.fname = "xc3028-v27.fw"; - else - ctl.fname = "xc3028-v24.fw"; - } - - printk(KERN_INFO "Setting firmware parameters for xc2028\n"); - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, - &xc2028_cfg); - - } - break; - case TUNER_XC5000: - { - struct v4l2_priv_tun_config xc5000_cfg; - struct xc5000_config ctl = { - .i2c_address = dev->tuner_addr, - .if_khz = 4570, - .radio_input = XC5000_RADIO_FM1_MONO, - }; - - xc5000_cfg.tuner = TUNER_XC5000; - xc5000_cfg.priv = &ctl; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, - &xc5000_cfg); - } - break; - default: - printk(KERN_INFO "Unknown tuner type. Tuner is not configured.\n"); - break; - } -} - -static int fill_board_specific_data(struct tm6000_core *dev) -{ - int rc; - - dev->dev_type = tm6000_boards[dev->model].type; - dev->tuner_type = tm6000_boards[dev->model].tuner_type; - dev->tuner_addr = tm6000_boards[dev->model].tuner_addr; - - dev->gpio = tm6000_boards[dev->model].gpio; - - dev->ir_codes = tm6000_boards[dev->model].ir_codes; - - dev->demod_addr = tm6000_boards[dev->model].demod_addr; - - dev->caps = tm6000_boards[dev->model].caps; - - dev->vinput[0] = tm6000_boards[dev->model].vinput[0]; - dev->vinput[1] = tm6000_boards[dev->model].vinput[1]; - dev->vinput[2] = tm6000_boards[dev->model].vinput[2]; - dev->rinput = tm6000_boards[dev->model].rinput; - - /* setup per-model quirks */ - switch (dev->model) { - case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: - dev->quirks |= TM6000_QUIRK_NO_USB_DELAY; - break; - - default: - break; - } - - /* initialize hardware */ - rc = tm6000_init(dev); - if (rc < 0) - return rc; - - return v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev); -} - - -static void use_alternative_detection_method(struct tm6000_core *dev) -{ - int i, model = -1; - - if (!dev->eedata_size) - return; - - for (i = 0; i < ARRAY_SIZE(tm6000_boards); i++) { - if (!tm6000_boards[i].eename_size) - continue; - if (dev->eedata_size < tm6000_boards[i].eename_pos + - tm6000_boards[i].eename_size) - continue; - - if (!memcmp(&dev->eedata[tm6000_boards[i].eename_pos], - tm6000_boards[i].eename, - tm6000_boards[i].eename_size)) { - model = i; - break; - } - } - if (model < 0) { - printk(KERN_INFO "Device has eeprom but is currently unknown\n"); - return; - } - - dev->model = model; - - printk(KERN_INFO "Device identified via eeprom as %s (type = %d)\n", - tm6000_boards[model].name, model); -} - -static int tm6000_init_dev(struct tm6000_core *dev) -{ - struct v4l2_frequency f; - int rc = 0; - - mutex_init(&dev->lock); - mutex_lock(&dev->lock); - - if (!is_generic(dev->model)) { - rc = fill_board_specific_data(dev); - if (rc < 0) - goto err; - - /* register i2c bus */ - rc = tm6000_i2c_register(dev); - if (rc < 0) - goto err; - } else { - /* register i2c bus */ - rc = tm6000_i2c_register(dev); - if (rc < 0) - goto err; - - use_alternative_detection_method(dev); - - rc = fill_board_specific_data(dev); - if (rc < 0) - goto err; - } - - /* Default values for STD and resolutions */ - dev->width = 720; - dev->height = 480; - dev->norm = V4L2_STD_PAL_M; - - /* Configure tuner */ - tm6000_config_tuner(dev); - - /* Set video standard */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm); - - /* Set tuner frequency - also loads firmware on xc2028/xc3028 */ - f.tuner = 0; - f.type = V4L2_TUNER_ANALOG_TV; - f.frequency = 3092; /* 193.25 MHz */ - dev->freq = f.frequency; - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f); - - if (dev->caps.has_tda9874) - v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tvaudio", I2C_ADDR_TDA9874, NULL); - - /* register and initialize V4L2 */ - rc = tm6000_v4l2_register(dev); - if (rc < 0) - goto err; - - tm6000_add_into_devlist(dev); - tm6000_init_extension(dev); - - tm6000_ir_init(dev); - - mutex_unlock(&dev->lock); - return 0; - -err: - mutex_unlock(&dev->lock); - return rc; -} - -/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */ -#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) - -static void get_max_endpoint(struct usb_device *udev, - struct usb_host_interface *alt, - char *msgtype, - struct usb_host_endpoint *curr_e, - struct tm6000_endpoint *tm_ep) -{ - u16 tmp = le16_to_cpu(curr_e->desc.wMaxPacketSize); - unsigned int size = tmp & 0x7ff; - - if (udev->speed == USB_SPEED_HIGH) - size = size * hb_mult(tmp); - - if (size > tm_ep->maxsize) { - tm_ep->endp = curr_e; - tm_ep->maxsize = size; - tm_ep->bInterfaceNumber = alt->desc.bInterfaceNumber; - tm_ep->bAlternateSetting = alt->desc.bAlternateSetting; - - printk(KERN_INFO "tm6000: %s endpoint: 0x%02x (max size=%u bytes)\n", - msgtype, curr_e->desc.bEndpointAddress, - size); - } -} - -/* - * tm6000_usb_probe() - * checks for supported devices - */ -static int tm6000_usb_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct usb_device *usbdev; - struct tm6000_core *dev = NULL; - int i, rc = 0; - int nr = 0; - char *speed; - - usbdev = usb_get_dev(interface_to_usbdev(interface)); - - /* Selects the proper interface */ - rc = usb_set_interface(usbdev, 0, 1); - if (rc < 0) - goto err; - - /* Check to see next free device and mark as used */ - nr = find_first_zero_bit(&tm6000_devused, TM6000_MAXBOARDS); - if (nr >= TM6000_MAXBOARDS) { - printk(KERN_ERR "tm6000: Supports only %i tm60xx boards.\n", TM6000_MAXBOARDS); - usb_put_dev(usbdev); - return -ENOMEM; - } - - /* Create and initialize dev struct */ - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - printk(KERN_ERR "tm6000" ": out of memory!\n"); - usb_put_dev(usbdev); - return -ENOMEM; - } - spin_lock_init(&dev->slock); - mutex_init(&dev->usb_lock); - - /* Increment usage count */ - set_bit(nr, &tm6000_devused); - snprintf(dev->name, 29, "tm6000 #%d", nr); - - dev->model = id->driver_info; - if (card[nr] < ARRAY_SIZE(tm6000_boards)) - dev->model = card[nr]; - - dev->udev = usbdev; - dev->devno = nr; - - switch (usbdev->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"; - } - - /* Get endpoints */ - for (i = 0; i < interface->num_altsetting; i++) { - int ep; - - for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) { - struct usb_host_endpoint *e; - int dir_out; - - e = &interface->altsetting[i].endpoint[ep]; - - dir_out = ((e->desc.bEndpointAddress & - USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); - - printk(KERN_INFO "tm6000: alt %d, interface %i, class %i\n", - i, - interface->altsetting[i].desc.bInterfaceNumber, - interface->altsetting[i].desc.bInterfaceClass); - - switch (e->desc.bmAttributes) { - case USB_ENDPOINT_XFER_BULK: - if (!dir_out) { - get_max_endpoint(usbdev, - &interface->altsetting[i], - "Bulk IN", e, - &dev->bulk_in); - } else { - get_max_endpoint(usbdev, - &interface->altsetting[i], - "Bulk OUT", e, - &dev->bulk_out); - } - break; - case USB_ENDPOINT_XFER_ISOC: - if (!dir_out) { - get_max_endpoint(usbdev, - &interface->altsetting[i], - "ISOC IN", e, - &dev->isoc_in); - } else { - get_max_endpoint(usbdev, - &interface->altsetting[i], - "ISOC OUT", e, - &dev->isoc_out); - } - break; - case USB_ENDPOINT_XFER_INT: - if (!dir_out) { - get_max_endpoint(usbdev, - &interface->altsetting[i], - "INT IN", e, - &dev->int_in); - } else { - get_max_endpoint(usbdev, - &interface->altsetting[i], - "INT OUT", e, - &dev->int_out); - } - break; - } - } - } - - - printk(KERN_INFO "tm6000: New video device @ %s Mbps (%04x:%04x, ifnum %d)\n", - speed, - le16_to_cpu(dev->udev->descriptor.idVendor), - le16_to_cpu(dev->udev->descriptor.idProduct), - interface->altsetting->desc.bInterfaceNumber); - -/* check if the the device has the iso in endpoint at the correct place */ - if (!dev->isoc_in.endp) { - printk(KERN_ERR "tm6000: probing error: no IN ISOC endpoint!\n"); - rc = -ENODEV; - - goto err; - } - - /* save our data pointer in this interface device */ - usb_set_intfdata(interface, dev); - - printk(KERN_INFO "tm6000: Found %s\n", tm6000_boards[dev->model].name); - - rc = tm6000_init_dev(dev); - if (rc < 0) - goto err; - - return 0; - -err: - printk(KERN_ERR "tm6000: Error %d while registering\n", rc); - - clear_bit(nr, &tm6000_devused); - usb_put_dev(usbdev); - - kfree(dev); - return rc; -} - -/* - * tm6000_usb_disconnect() - * called when the device gets diconencted - * video device will be unregistered on v4l2_close in case it is still open - */ -static void tm6000_usb_disconnect(struct usb_interface *interface) -{ - struct tm6000_core *dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - - if (!dev) - return; - - printk(KERN_INFO "tm6000: disconnecting %s\n", dev->name); - - tm6000_ir_fini(dev); - - if (dev->gpio.power_led) { - switch (dev->model) { - case TM6010_BOARD_HAUPPAUGE_900H: - case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: - case TM6010_BOARD_TWINHAN_TU501: - /* Power led off */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.power_led, 0x01); - msleep(15); - break; - case TM6010_BOARD_BEHOLD_WANDER: - case TM6010_BOARD_BEHOLD_VOYAGER: - case TM6010_BOARD_BEHOLD_WANDER_LITE: - case TM6010_BOARD_BEHOLD_VOYAGER_LITE: - /* Power led off */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.power_led, 0x00); - msleep(15); - break; - } - } - tm6000_v4l2_unregister(dev); - - tm6000_i2c_unregister(dev); - - v4l2_device_unregister(&dev->v4l2_dev); - - dev->state |= DEV_DISCONNECTED; - - usb_put_dev(dev->udev); - - tm6000_close_extension(dev); - tm6000_remove_from_devlist(dev); - - clear_bit(dev->devno, &tm6000_devused); - kfree(dev); -} - -static struct usb_driver tm6000_usb_driver = { - .name = "tm6000", - .probe = tm6000_usb_probe, - .disconnect = tm6000_usb_disconnect, - .id_table = tm6000_id_table, -}; - -static int __init tm6000_module_init(void) -{ - int result; - - printk(KERN_INFO "tm6000" " v4l2 driver version %d.%d.%d loaded\n", - (TM6000_VERSION >> 16) & 0xff, - (TM6000_VERSION >> 8) & 0xff, TM6000_VERSION & 0xff); - - /* register this driver with the USB subsystem */ - result = usb_register(&tm6000_usb_driver); - if (result) - printk(KERN_ERR "tm6000" - " usb_register failed. Error number %d.\n", result); - - return result; -} - -static void __exit tm6000_module_exit(void) -{ - /* deregister at USB subsystem */ - usb_deregister(&tm6000_usb_driver); -} - -module_init(tm6000_module_init); -module_exit(tm6000_module_exit); - -MODULE_DESCRIPTION("Trident TVMaster TM5600/TM6000/TM6010 USB2 adapter"); -MODULE_AUTHOR("Mauro Carvalho Chehab"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/tm6000/tm6000-core.c b/drivers/staging/tm6000/tm6000-core.c deleted file mode 100644 index 9783616a0da2..000000000000 --- a/drivers/staging/tm6000/tm6000-core.c +++ /dev/null @@ -1,965 +0,0 @@ -/* - * tm6000-core.c - driver for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> - * - * Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com> - * - DVB-T support - * - * 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 version 2 - * - * 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/slab.h> -#include <linux/usb.h> -#include <linux/i2c.h> -#include "tm6000.h" -#include "tm6000-regs.h" -#include <media/v4l2-common.h> -#include <media/tuner.h> - -#define USB_TIMEOUT (5 * HZ) /* ms */ - -int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req, - u16 value, u16 index, u8 *buf, u16 len) -{ - int ret, i; - unsigned int pipe; - u8 *data = NULL; - - mutex_lock(&dev->usb_lock); - - if (len) - data = kzalloc(len, GFP_KERNEL); - - if (req_type & USB_DIR_IN) - pipe = usb_rcvctrlpipe(dev->udev, 0); - else { - pipe = usb_sndctrlpipe(dev->udev, 0); - memcpy(data, buf, len); - } - - if (tm6000_debug & V4L2_DEBUG_I2C) { - printk(KERN_DEBUG "(dev %p, pipe %08x): ", dev->udev, pipe); - - printk(KERN_CONT "%s: %02x %02x %02x %02x %02x %02x %02x %02x ", - (req_type & USB_DIR_IN) ? " IN" : "OUT", - req_type, req, value&0xff, value>>8, index&0xff, - index>>8, len&0xff, len>>8); - - if (!(req_type & USB_DIR_IN)) { - printk(KERN_CONT ">>> "); - for (i = 0; i < len; i++) - printk(KERN_CONT " %02x", buf[i]); - printk(KERN_CONT "\n"); - } - } - - ret = usb_control_msg(dev->udev, pipe, req, req_type, value, index, - data, len, USB_TIMEOUT); - - if (req_type & USB_DIR_IN) - memcpy(buf, data, len); - - if (tm6000_debug & V4L2_DEBUG_I2C) { - if (ret < 0) { - if (req_type & USB_DIR_IN) - printk(KERN_DEBUG "<<< (len=%d)\n", len); - - printk(KERN_CONT "%s: Error #%d\n", __func__, ret); - } else if (req_type & USB_DIR_IN) { - printk(KERN_CONT "<<< "); - for (i = 0; i < len; i++) - printk(KERN_CONT " %02x", buf[i]); - printk(KERN_CONT "\n"); - } - } - - kfree(data); - msleep(5); - - mutex_unlock(&dev->usb_lock); - return ret; -} - -int tm6000_set_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index) -{ - return - tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR, - req, value, index, NULL, 0); -} -EXPORT_SYMBOL_GPL(tm6000_set_reg); - -int tm6000_get_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index) -{ - int rc; - u8 buf[1]; - - rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req, - value, index, buf, 1); - - if (rc < 0) - return rc; - - return *buf; -} -EXPORT_SYMBOL_GPL(tm6000_get_reg); - -int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value, - u16 index, u16 mask) -{ - int rc; - u8 buf[1]; - u8 new_index; - - rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req, - value, index, buf, 1); - - if (rc < 0) - return rc; - - new_index = (buf[0] & ~mask) | (index & mask); - - if (new_index == index) - return 0; - - return tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR, - req, value, new_index, NULL, 0); -} -EXPORT_SYMBOL_GPL(tm6000_set_reg_mask); - -int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index) -{ - int rc; - u8 buf[2]; - - rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req, - value, index, buf, 2); - - if (rc < 0) - return rc; - - return buf[1]|buf[0]<<8; -} - -int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index) -{ - int rc; - u8 buf[4]; - - rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req, - value, index, buf, 4); - - if (rc < 0) - return rc; - - return buf[3] | buf[2] << 8 | buf[1] << 16 | buf[0] << 24; -} - -int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep) -{ - int rc; - - rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 0); - if (rc < 0) - return rc; - - msleep(tsleep); - - rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1); - msleep(tsleep); - - return rc; -} - -void tm6000_set_fourcc_format(struct tm6000_core *dev) -{ - if (dev->dev_type == TM6010) { - int val; - - val = tm6000_get_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, 0) & 0xfc; - if (dev->fourcc == V4L2_PIX_FMT_UYVY) - tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val); - else - tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val | 1); - } else { - if (dev->fourcc == V4L2_PIX_FMT_UYVY) - tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0); - else - tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0x90); - } -} - -static void tm6000_set_vbi(struct tm6000_core *dev) -{ - /* - * FIXME: - * VBI lines and start/end are different between 60Hz and 50Hz - * So, it is very likely that we need to change the config to - * something that takes it into account, doing something different - * if (dev->norm & V4L2_STD_525_60) - */ - - if (dev->dev_type == TM6010) { - tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01); - tm6000_set_reg(dev, TM6010_REQ07_R41_TELETEXT_VBI_CODE1, 0x27); - tm6000_set_reg(dev, TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55); - tm6000_set_reg(dev, TM6010_REQ07_R43_VBI_DATA_TYPE_LINE7, 0x66); - tm6000_set_reg(dev, TM6010_REQ07_R44_VBI_DATA_TYPE_LINE8, 0x66); - tm6000_set_reg(dev, TM6010_REQ07_R45_VBI_DATA_TYPE_LINE9, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R46_VBI_DATA_TYPE_LINE10, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R47_VBI_DATA_TYPE_LINE11, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R48_VBI_DATA_TYPE_LINE12, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R49_VBI_DATA_TYPE_LINE13, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R4A_VBI_DATA_TYPE_LINE14, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R4B_VBI_DATA_TYPE_LINE15, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R4C_VBI_DATA_TYPE_LINE16, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R4D_VBI_DATA_TYPE_LINE17, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R4E_VBI_DATA_TYPE_LINE18, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R4F_VBI_DATA_TYPE_LINE19, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R50_VBI_DATA_TYPE_LINE20, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R52_VBI_DATA_TYPE_LINE22, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R53_VBI_DATA_TYPE_LINE23, 0x00); - tm6000_set_reg(dev, - TM6010_REQ07_R54_VBI_DATA_TYPE_RLINES, 0x00); - tm6000_set_reg(dev, - TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01); - tm6000_set_reg(dev, - TM6010_REQ07_R56_VBI_LOOP_FILTER_I_GAIN, 0x00); - tm6000_set_reg(dev, - TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02); - tm6000_set_reg(dev, TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35); - tm6000_set_reg(dev, TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0); - tm6000_set_reg(dev, TM6010_REQ07_R5A_VBI_TELETEXT_DTO1, 0x11); - tm6000_set_reg(dev, TM6010_REQ07_R5B_VBI_TELETEXT_DTO0, 0x4c); - tm6000_set_reg(dev, TM6010_REQ07_R40_TELETEXT_VBI_CODE0, 0x01); - tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00); - } -} - -int tm6000_init_analog_mode(struct tm6000_core *dev) -{ - struct v4l2_frequency f; - - if (dev->dev_type == TM6010) { - u8 active = TM6010_REQ07_RCC_ACTIVE_IF_AUDIO_ENABLE; - - if (!dev->radio) - active |= TM6010_REQ07_RCC_ACTIVE_IF_VIDEO_ENABLE; - - /* Enable video and audio */ - tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF, - active, 0x60); - /* Disable TS input */ - tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, - 0x00, 0x40); - } else { - /* Enables soft reset */ - tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01); - - if (dev->scaler) - /* Disable Hfilter and Enable TS Drop err */ - tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x20); - else /* Enable Hfilter and disable TS Drop err */ - tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x80); - - tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x88); - tm6000_set_reg(dev, TM6000_REQ07_RDA_CLK_SEL, 0x23); - tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xc0); - tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xd8); - tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x06); - tm6000_set_reg(dev, TM6000_REQ07_RDF_PWDOWN_ACLK, 0x1f); - - /* AP Software reset */ - tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08); - tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00); - - tm6000_set_fourcc_format(dev); - - /* Disables soft reset */ - tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00); - } - msleep(20); - - /* Tuner firmware can now be loaded */ - - /* - * FIXME: This is a hack! xc3028 "sleeps" when no channel is detected - * for more than a few seconds. Not sure why, as this behavior does - * not happen on other devices with xc3028. So, I suspect that it - * is yet another bug at tm6000. After start sleeping, decoding - * doesn't start automatically. Instead, it requires some - * I2C commands to wake it up. As we want to have image at the - * beginning, we needed to add this hack. The better would be to - * discover some way to make tm6000 to wake up without this hack. - */ - f.frequency = dev->freq; - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f); - - msleep(100); - tm6000_set_standard(dev); - tm6000_set_vbi(dev); - tm6000_set_audio_bitrate(dev, 48000); - - /* switch dvb led off */ - if (dev->gpio.dvb_led) { - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.dvb_led, 0x01); - } - - return 0; -} - -int tm6000_init_digital_mode(struct tm6000_core *dev) -{ - if (dev->dev_type == TM6010) { - /* Disable video and audio */ - tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF, - 0x00, 0x60); - /* Enable TS input */ - tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, - 0x40, 0x40); - /* all power down, but not the digital data port */ - tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, 0x28); - tm6000_set_reg(dev, TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xfc); - tm6000_set_reg(dev, TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0xff); - } else { - tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08); - tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00); - tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01); - tm6000_set_reg(dev, TM6000_REQ07_RDF_PWDOWN_ACLK, 0x08); - tm6000_set_reg(dev, TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x0c); - tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0xff); - tm6000_set_reg(dev, TM6000_REQ07_REB_VADC_AADC_MODE, 0xd8); - tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x40); - tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0); - tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x09); - tm6000_set_reg(dev, TM6000_REQ07_RDA_CLK_SEL, 0x37); - tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xd8); - tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xc0); - tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x60); - - tm6000_set_reg(dev, TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x0c); - tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0xff); - tm6000_set_reg(dev, TM6000_REQ07_REB_VADC_AADC_MODE, 0x08); - msleep(50); - - tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00); - msleep(50); - tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x01); - msleep(50); - tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00); - msleep(100); - } - - /* switch dvb led on */ - if (dev->gpio.dvb_led) { - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.dvb_led, 0x00); - } - - return 0; -} -EXPORT_SYMBOL(tm6000_init_digital_mode); - -struct reg_init { - u8 req; - u8 reg; - u8 val; -}; - -/* The meaning of those initializations are unknown */ -static struct reg_init tm6000_init_tab[] = { - /* REG VALUE */ - { TM6000_REQ07_RDF_PWDOWN_ACLK, 0x1f }, - { TM6010_REQ07_RFF_SOFT_RESET, 0x08 }, - { TM6010_REQ07_RFF_SOFT_RESET, 0x00 }, - { TM6010_REQ07_RD5_POWERSAVE, 0x4f }, - { TM6000_REQ07_RDA_CLK_SEL, 0x23 }, - { TM6000_REQ07_RDB_OUT_SEL, 0x08 }, - { TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x00 }, - { TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10 }, - { TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00 }, - { TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x00 }, - { TM6000_REQ07_REB_VADC_AADC_MODE, 0x64 }, /* 48000 bits/sample, external input */ - { TM6000_REQ07_REE_VADC_CTRL_SEL_CONTROL, 0xc2 }, - - { TM6010_REQ07_R3F_RESET, 0x01 }, /* Start of soft reset */ - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 }, - { TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 }, - { TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 }, - { TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 }, - { TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 }, - { TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a }, - { TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 }, - { TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 }, - { TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b }, - { TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 }, - { TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f }, - { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c }, - { TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c }, - { TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 }, - { TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c }, - { TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a }, - { TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 }, - { TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 }, - { TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a }, - { TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 }, - { TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 }, - { TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 }, - { TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 }, - { TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 }, - { TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 }, - { TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 }, - { TM6010_REQ07_RC1_TRESHOLD, 0xd0 }, - { TM6010_REQ07_RC3_HSTART1, 0x88 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, /* End of the soft reset */ - { TM6010_REQ05_R18_IMASK7, 0x00 }, -}; - -static struct reg_init tm6010_init_tab[] = { - { TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x00 }, - { TM6010_REQ07_RC4_HSTART0, 0xa0 }, - { TM6010_REQ07_RC6_HEND0, 0x40 }, - { TM6010_REQ07_RCA_VEND0, 0x31 }, - { TM6010_REQ07_RCC_ACTIVE_IF, 0xe1 }, - { TM6010_REQ07_RE0_DVIDEO_SOURCE, 0x03 }, - { TM6010_REQ07_RFE_POWER_DOWN, 0x7f }, - - { TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0 }, - { TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4 }, - { TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8 }, - { TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x00 }, - { TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2 }, - { TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0 }, - { TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2 }, - { TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x60 }, - { TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc }, - - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 }, - { TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 }, - { TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 }, - { TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 }, - { TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 }, - { TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a }, - { TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 }, - { TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 }, - { TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b }, - { TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 }, - { TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f }, - { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c }, - { TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c }, - { TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 }, - { TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c }, - { TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a }, - { TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 }, - { TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 }, - { TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a }, - { TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 }, - { TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 }, - { TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 }, - { TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 }, - { TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 }, - { TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 }, - { TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 }, - { TM6010_REQ07_RC1_TRESHOLD, 0xd0 }, - { TM6010_REQ07_RC3_HSTART1, 0x88 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - - { TM6010_REQ05_R18_IMASK7, 0x00 }, - - { TM6010_REQ07_RD8_IR_LEADER1, 0xaa }, - { TM6010_REQ07_RD8_IR_LEADER0, 0x30 }, - { TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20 }, - { TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0 }, - { REQ_04_EN_DISABLE_MCU_INT, 0x02, 0x00 }, - { TM6010_REQ07_RD8_IR, 0x2f }, - - /* set remote wakeup key:any key wakeup */ - { TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe }, - { TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0xff }, -}; - -int tm6000_init(struct tm6000_core *dev) -{ - int board, rc = 0, i, size; - struct reg_init *tab; - - /* Check board revision */ - board = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0); - if (board >= 0) { - switch (board & 0xff) { - case 0xf3: - printk(KERN_INFO "Found tm6000\n"); - if (dev->dev_type != TM6000) - dev->dev_type = TM6000; - break; - case 0xf4: - printk(KERN_INFO "Found tm6010\n"); - if (dev->dev_type != TM6010) - dev->dev_type = TM6010; - break; - default: - printk(KERN_INFO "Unknown board version = 0x%08x\n", board); - } - } else - printk(KERN_ERR "Error %i while retrieving board version\n", board); - - if (dev->dev_type == TM6010) { - tab = tm6010_init_tab; - size = ARRAY_SIZE(tm6010_init_tab); - } else { - tab = tm6000_init_tab; - size = ARRAY_SIZE(tm6000_init_tab); - } - - /* Load board's initialization table */ - for (i = 0; i < size; i++) { - rc = tm6000_set_reg(dev, tab[i].req, tab[i].reg, tab[i].val); - if (rc < 0) { - printk(KERN_ERR "Error %i while setting req %d, " - "reg %d to value %d\n", rc, - tab[i].req, tab[i].reg, tab[i].val); - return rc; - } - } - - msleep(5); /* Just to be conservative */ - - rc = tm6000_cards_setup(dev); - - return rc; -} - -int tm6000_reset(struct tm6000_core *dev) -{ - int pipe; - int err; - - msleep(500); - - err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 0); - if (err < 0) { - tm6000_err("failed to select interface %d, alt. setting 0\n", - dev->isoc_in.bInterfaceNumber); - return err; - } - - err = usb_reset_configuration(dev->udev); - if (err < 0) { - tm6000_err("failed to reset configuration\n"); - return err; - } - - if ((dev->quirks & TM6000_QUIRK_NO_USB_DELAY) == 0) - msleep(5); - - /* - * Not all devices have int_in defined - */ - if (!dev->int_in.endp) - return 0; - - err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 2); - if (err < 0) { - tm6000_err("failed to select interface %d, alt. setting 2\n", - dev->isoc_in.bInterfaceNumber); - return err; - } - - msleep(5); - - pipe = usb_rcvintpipe(dev->udev, - dev->int_in.endp->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); - - err = usb_clear_halt(dev->udev, pipe); - if (err < 0) { - tm6000_err("usb_clear_halt failed: %d\n", err); - return err; - } - - return 0; -} - -int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate) -{ - int val = 0; - u8 areg_f0 = 0x60; /* ADC MCLK = 250 Fs */ - u8 areg_0a = 0x91; /* SIF 48KHz */ - - switch (bitrate) { - case 48000: - areg_f0 = 0x60; /* ADC MCLK = 250 Fs */ - areg_0a = 0x91; /* SIF 48KHz */ - dev->audio_bitrate = bitrate; - break; - case 32000: - areg_f0 = 0x00; /* ADC MCLK = 375 Fs */ - areg_0a = 0x90; /* SIF 32KHz */ - dev->audio_bitrate = bitrate; - break; - default: - return -EINVAL; - } - - - /* enable I2S, if we use sif or external I2S device */ - if (dev->dev_type == TM6010) { - val = tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, areg_0a); - if (val < 0) - return val; - - val = tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, - areg_f0, 0xf0); - if (val < 0) - return val; - } else { - val = tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE, - areg_f0, 0xf0); - if (val < 0) - return val; - } - return 0; -} -EXPORT_SYMBOL_GPL(tm6000_set_audio_bitrate); - -int tm6000_set_audio_rinput(struct tm6000_core *dev) -{ - if (dev->dev_type == TM6010) { - /* Audio crossbar setting, default SIF1 */ - u8 areg_f0; - - switch (dev->rinput.amux) { - case TM6000_AMUX_SIF1: - case TM6000_AMUX_SIF2: - areg_f0 = 0x03; - break; - case TM6000_AMUX_ADC1: - areg_f0 = 0x00; - break; - case TM6000_AMUX_ADC2: - areg_f0 = 0x08; - break; - case TM6000_AMUX_I2S: - areg_f0 = 0x04; - break; - default: - printk(KERN_INFO "%s: audio input dosn't support\n", - dev->name); - return 0; - break; - } - /* Set audio input crossbar */ - tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, - areg_f0, 0x0f); - } else { - u8 areg_eb; - /* Audio setting, default LINE1 */ - switch (dev->rinput.amux) { - case TM6000_AMUX_ADC1: - areg_eb = 0x00; - break; - case TM6000_AMUX_ADC2: - areg_eb = 0x04; - break; - default: - printk(KERN_INFO "%s: audio input dosn't support\n", - dev->name); - return 0; - break; - } - /* Set audio input */ - tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE, - areg_eb, 0x0f); - } - return 0; -} - -static void tm6010_set_mute_sif(struct tm6000_core *dev, u8 mute) -{ - u8 mute_reg = 0; - - if (mute) - mute_reg = 0x08; - - tm6000_set_reg_mask(dev, TM6010_REQ08_R0A_A_I2S_MOD, mute_reg, 0x08); -} - -static void tm6010_set_mute_adc(struct tm6000_core *dev, u8 mute) -{ - u8 mute_reg = 0; - - if (mute) - mute_reg = 0x20; - - if (dev->dev_type == TM6010) { - tm6000_set_reg_mask(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL, - mute_reg, 0x20); - tm6000_set_reg_mask(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL, - mute_reg, 0x20); - } else { - tm6000_set_reg_mask(dev, TM6000_REQ07_REC_VADC_AADC_LVOL, - mute_reg, 0x20); - tm6000_set_reg_mask(dev, TM6000_REQ07_RED_VADC_AADC_RVOL, - mute_reg, 0x20); - } -} - -int tm6000_tvaudio_set_mute(struct tm6000_core *dev, u8 mute) -{ - enum tm6000_mux mux; - - if (dev->radio) - mux = dev->rinput.amux; - else - mux = dev->vinput[dev->input].amux; - - switch (mux) { - case TM6000_AMUX_SIF1: - case TM6000_AMUX_SIF2: - if (dev->dev_type == TM6010) - tm6010_set_mute_sif(dev, mute); - else { - printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has" - " SIF audio inputs. Please check the %s" - " configuration.\n", dev->name); - return -EINVAL; - } - break; - case TM6000_AMUX_ADC1: - case TM6000_AMUX_ADC2: - tm6010_set_mute_adc(dev, mute); - break; - default: - return -EINVAL; - break; - } - return 0; -} - -static void tm6010_set_volume_sif(struct tm6000_core *dev, int vol) -{ - u8 vol_reg; - - vol_reg = vol & 0x0F; - - if (vol < 0) - vol_reg |= 0x40; - - tm6000_set_reg(dev, TM6010_REQ08_R07_A_LEFT_VOL, vol_reg); - tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, vol_reg); -} - -static void tm6010_set_volume_adc(struct tm6000_core *dev, int vol) -{ - u8 vol_reg; - - vol_reg = (vol + 0x10) & 0x1f; - - if (dev->dev_type == TM6010) { - tm6000_set_reg(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL, vol_reg); - tm6000_set_reg(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL, vol_reg); - } else { - tm6000_set_reg(dev, TM6000_REQ07_REC_VADC_AADC_LVOL, vol_reg); - tm6000_set_reg(dev, TM6000_REQ07_RED_VADC_AADC_RVOL, vol_reg); - } -} - -void tm6000_set_volume(struct tm6000_core *dev, int vol) -{ - enum tm6000_mux mux; - - if (dev->radio) { - mux = dev->rinput.amux; - vol += 8; /* Offset to 0 dB */ - } else - mux = dev->vinput[dev->input].amux; - - switch (mux) { - case TM6000_AMUX_SIF1: - case TM6000_AMUX_SIF2: - if (dev->dev_type == TM6010) - tm6010_set_volume_sif(dev, vol); - else - printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has" - " SIF audio inputs. Please check the %s" - " configuration.\n", dev->name); - break; - case TM6000_AMUX_ADC1: - case TM6000_AMUX_ADC2: - tm6010_set_volume_adc(dev, vol); - break; - default: - break; - } -} - -static LIST_HEAD(tm6000_devlist); -static DEFINE_MUTEX(tm6000_devlist_mutex); - -/* - * tm6000_realease_resource() - */ - -void tm6000_remove_from_devlist(struct tm6000_core *dev) -{ - mutex_lock(&tm6000_devlist_mutex); - list_del(&dev->devlist); - mutex_unlock(&tm6000_devlist_mutex); -}; - -void tm6000_add_into_devlist(struct tm6000_core *dev) -{ - mutex_lock(&tm6000_devlist_mutex); - list_add_tail(&dev->devlist, &tm6000_devlist); - mutex_unlock(&tm6000_devlist_mutex); -}; - -/* - * Extension interface - */ - -static LIST_HEAD(tm6000_extension_devlist); - -int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type, - char *buf, int size) -{ - struct tm6000_ops *ops = NULL; - - /* FIXME: tm6000_extension_devlist_lock should be a spinlock */ - - if (!list_empty(&tm6000_extension_devlist)) { - list_for_each_entry(ops, &tm6000_extension_devlist, next) { - if (ops->fillbuf && ops->type == type) - ops->fillbuf(dev, buf, size); - } - } - - return 0; -} - -int tm6000_register_extension(struct tm6000_ops *ops) -{ - struct tm6000_core *dev = NULL; - - mutex_lock(&tm6000_devlist_mutex); - list_add_tail(&ops->next, &tm6000_extension_devlist); - list_for_each_entry(dev, &tm6000_devlist, devlist) { - ops->init(dev); - printk(KERN_INFO "%s: Initialized (%s) extension\n", - dev->name, ops->name); - } - mutex_unlock(&tm6000_devlist_mutex); - return 0; -} -EXPORT_SYMBOL(tm6000_register_extension); - -void tm6000_unregister_extension(struct tm6000_ops *ops) -{ - struct tm6000_core *dev = NULL; - - mutex_lock(&tm6000_devlist_mutex); - list_for_each_entry(dev, &tm6000_devlist, devlist) - ops->fini(dev); - - printk(KERN_INFO "tm6000: Remove (%s) extension\n", ops->name); - list_del(&ops->next); - mutex_unlock(&tm6000_devlist_mutex); -} -EXPORT_SYMBOL(tm6000_unregister_extension); - -void tm6000_init_extension(struct tm6000_core *dev) -{ - struct tm6000_ops *ops = NULL; - - mutex_lock(&tm6000_devlist_mutex); - if (!list_empty(&tm6000_extension_devlist)) { - list_for_each_entry(ops, &tm6000_extension_devlist, next) { - if (ops->init) - ops->init(dev); - } - } - mutex_unlock(&tm6000_devlist_mutex); -} - -void tm6000_close_extension(struct tm6000_core *dev) -{ - struct tm6000_ops *ops = NULL; - - mutex_lock(&tm6000_devlist_mutex); - if (!list_empty(&tm6000_extension_devlist)) { - list_for_each_entry(ops, &tm6000_extension_devlist, next) { - if (ops->fini) - ops->fini(dev); - } - } - mutex_unlock(&tm6000_devlist_mutex); -} diff --git a/drivers/staging/tm6000/tm6000-dvb.c b/drivers/staging/tm6000/tm6000-dvb.c deleted file mode 100644 index 5e6c129a4beb..000000000000 --- a/drivers/staging/tm6000/tm6000-dvb.c +++ /dev/null @@ -1,452 +0,0 @@ -/* - * tm6000-dvb.c - dvb-t support for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com> - * - * 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 version 2 - * - * 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/slab.h> -#include <linux/usb.h> - -#include "tm6000.h" -#include "tm6000-regs.h" - -#include "zl10353.h" - -#include <media/tuner.h> - -#include "tuner-xc2028.h" -#include "xc5000.h" - -MODULE_DESCRIPTION("DVB driver extension module for tm5600/6000/6010 based TV cards"); -MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); -MODULE_LICENSE("GPL"); - -MODULE_SUPPORTED_DEVICE("{{Trident, tm5600}," - "{{Trident, tm6000}," - "{{Trident, tm6010}"); - -static int debug; - -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "enable debug message"); - -static inline void print_err_status(struct tm6000_core *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(dev, 1, "URB status %d [%s].\n", - status, errmsg); - } else { - dprintk(dev, 1, "URB packet %d, status %d [%s].\n", - packet, status, errmsg); - } -} - -static void tm6000_urb_received(struct urb *urb) -{ - int ret; - struct tm6000_core *dev = urb->context; - - if (urb->status != 0) - print_err_status(dev, 0, urb->status); - else if (urb->actual_length > 0) - dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer, - urb->actual_length); - - if (dev->dvb->streams > 0) { - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret < 0) { - printk(KERN_ERR "tm6000: error %s\n", __func__); - kfree(urb->transfer_buffer); - usb_free_urb(urb); - } - } -} - -static int tm6000_start_stream(struct tm6000_core *dev) -{ - int ret; - unsigned int pipe, size; - struct tm6000_dvb *dvb = dev->dvb; - - printk(KERN_INFO "tm6000: got start stream request %s\n", __func__); - - if (dev->mode != TM6000_MODE_DIGITAL) { - tm6000_init_digital_mode(dev); - dev->mode = TM6000_MODE_DIGITAL; - } - - dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL); - if (dvb->bulk_urb == NULL) { - printk(KERN_ERR "tm6000: couldn't allocate urb\n"); - return -ENOMEM; - } - - pipe = usb_rcvbulkpipe(dev->udev, dev->bulk_in.endp->desc.bEndpointAddress - & USB_ENDPOINT_NUMBER_MASK); - - size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe)); - size = size * 15; /* 512 x 8 or 12 or 15 */ - - dvb->bulk_urb->transfer_buffer = kzalloc(size, GFP_KERNEL); - if (dvb->bulk_urb->transfer_buffer == NULL) { - usb_free_urb(dvb->bulk_urb); - printk(KERN_ERR "tm6000: couldn't allocate transfer buffer!\n"); - return -ENOMEM; - } - - usb_fill_bulk_urb(dvb->bulk_urb, dev->udev, pipe, - dvb->bulk_urb->transfer_buffer, - size, - tm6000_urb_received, dev); - - ret = usb_clear_halt(dev->udev, pipe); - if (ret < 0) { - printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n", - ret, __func__); - return ret; - } else - printk(KERN_ERR "tm6000: pipe resetted\n"); - -/* mutex_lock(&tm6000_driver.open_close_mutex); */ - ret = usb_submit_urb(dvb->bulk_urb, GFP_KERNEL); - -/* mutex_unlock(&tm6000_driver.open_close_mutex); */ - if (ret) { - printk(KERN_ERR "tm6000: submit of urb failed (error=%i)\n", - ret); - - kfree(dvb->bulk_urb->transfer_buffer); - usb_free_urb(dvb->bulk_urb); - return ret; - } - - return 0; -} - -static void tm6000_stop_stream(struct tm6000_core *dev) -{ - struct tm6000_dvb *dvb = dev->dvb; - - if (dvb->bulk_urb) { - printk(KERN_INFO "urb killing\n"); - usb_kill_urb(dvb->bulk_urb); - printk(KERN_INFO "urb buffer free\n"); - kfree(dvb->bulk_urb->transfer_buffer); - usb_free_urb(dvb->bulk_urb); - dvb->bulk_urb = NULL; - } -} - -static int tm6000_start_feed(struct dvb_demux_feed *feed) -{ - struct dvb_demux *demux = feed->demux; - struct tm6000_core *dev = demux->priv; - struct tm6000_dvb *dvb = dev->dvb; - printk(KERN_INFO "tm6000: got start feed request %s\n", __func__); - - mutex_lock(&dvb->mutex); - if (dvb->streams == 0) { - dvb->streams = 1; -/* mutex_init(&tm6000_dev->streming_mutex); */ - tm6000_start_stream(dev); - } else - ++(dvb->streams); - mutex_unlock(&dvb->mutex); - - return 0; -} - -static int tm6000_stop_feed(struct dvb_demux_feed *feed) -{ - struct dvb_demux *demux = feed->demux; - struct tm6000_core *dev = demux->priv; - struct tm6000_dvb *dvb = dev->dvb; - - printk(KERN_INFO "tm6000: got stop feed request %s\n", __func__); - - mutex_lock(&dvb->mutex); - - printk(KERN_INFO "stream %#x\n", dvb->streams); - --(dvb->streams); - if (dvb->streams == 0) { - printk(KERN_INFO "stop stream\n"); - tm6000_stop_stream(dev); -/* mutex_destroy(&tm6000_dev->streaming_mutex); */ - } - mutex_unlock(&dvb->mutex); -/* mutex_destroy(&tm6000_dev->streaming_mutex); */ - - return 0; -} - -static int tm6000_dvb_attach_frontend(struct tm6000_core *dev) -{ - struct tm6000_dvb *dvb = dev->dvb; - - if (dev->caps.has_zl10353) { - struct zl10353_config config = { - .demod_address = dev->demod_addr, - .no_tuner = 1, - .parallel_ts = 1, - .if2 = 45700, - .disable_i2c_gate_ctrl = 1, - }; - - dvb->frontend = dvb_attach(zl10353_attach, &config, - &dev->i2c_adap); - } else { - printk(KERN_ERR "tm6000: no frontend defined for the device!\n"); - return -1; - } - - return (!dvb->frontend) ? -1 : 0; -} - -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - -static int register_dvb(struct tm6000_core *dev) -{ - int ret = -1; - struct tm6000_dvb *dvb = dev->dvb; - - mutex_init(&dvb->mutex); - - dvb->streams = 0; - - /* attach the frontend */ - ret = tm6000_dvb_attach_frontend(dev); - if (ret < 0) { - printk(KERN_ERR "tm6000: couldn't attach the frontend!\n"); - goto err; - } - - ret = dvb_register_adapter(&dvb->adapter, "Trident TVMaster 6000 DVB-T", - THIS_MODULE, &dev->udev->dev, adapter_nr); - dvb->adapter.priv = dev; - - if (dvb->frontend) { - switch (dev->tuner_type) { - case TUNER_XC2028: { - struct xc2028_config cfg = { - .i2c_adap = &dev->i2c_adap, - .i2c_addr = dev->tuner_addr, - }; - - dvb->frontend->callback = tm6000_tuner_callback; - ret = dvb_register_frontend(&dvb->adapter, dvb->frontend); - if (ret < 0) { - printk(KERN_ERR - "tm6000: couldn't register frontend\n"); - goto adapter_err; - } - - if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) { - printk(KERN_ERR "tm6000: couldn't register " - "frontend (xc3028)\n"); - ret = -EINVAL; - goto frontend_err; - } - printk(KERN_INFO "tm6000: XC2028/3028 asked to be " - "attached to frontend!\n"); - break; - } - case TUNER_XC5000: { - struct xc5000_config cfg = { - .i2c_address = dev->tuner_addr, - }; - - dvb->frontend->callback = tm6000_xc5000_callback; - ret = dvb_register_frontend(&dvb->adapter, dvb->frontend); - if (ret < 0) { - printk(KERN_ERR - "tm6000: couldn't register frontend\n"); - goto adapter_err; - } - - if (!dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, &cfg)) { - printk(KERN_ERR "tm6000: couldn't register " - "frontend (xc5000)\n"); - ret = -EINVAL; - goto frontend_err; - } - printk(KERN_INFO "tm6000: XC5000 asked to be " - "attached to frontend!\n"); - break; - } - } - } else - printk(KERN_ERR "tm6000: no frontend found\n"); - - dvb->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING - | DMX_MEMORY_BASED_FILTERING; - dvb->demux.priv = dev; - dvb->demux.filternum = 8; - dvb->demux.feednum = 8; - dvb->demux.start_feed = tm6000_start_feed; - dvb->demux.stop_feed = tm6000_stop_feed; - dvb->demux.write_to_decoder = NULL; - ret = dvb_dmx_init(&dvb->demux); - if (ret < 0) { - printk(KERN_ERR "tm6000: dvb_dmx_init failed (errno = %d)\n", ret); - goto frontend_err; - } - - dvb->dmxdev.filternum = dev->dvb->demux.filternum; - dvb->dmxdev.demux = &dev->dvb->demux.dmx; - dvb->dmxdev.capabilities = 0; - - ret = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); - if (ret < 0) { - printk(KERN_ERR "tm6000: dvb_dmxdev_init failed (errno = %d)\n", ret); - goto dvb_dmx_err; - } - - return 0; - -dvb_dmx_err: - dvb_dmx_release(&dvb->demux); -frontend_err: - if (dvb->frontend) { - dvb_frontend_detach(dvb->frontend); - dvb_unregister_frontend(dvb->frontend); - } -adapter_err: - dvb_unregister_adapter(&dvb->adapter); -err: - return ret; -} - -static void unregister_dvb(struct tm6000_core *dev) -{ - struct tm6000_dvb *dvb = dev->dvb; - - if (dvb->bulk_urb != NULL) { - struct urb *bulk_urb = dvb->bulk_urb; - - kfree(bulk_urb->transfer_buffer); - bulk_urb->transfer_buffer = NULL; - usb_unlink_urb(bulk_urb); - usb_free_urb(bulk_urb); - } - -/* mutex_lock(&tm6000_driver.open_close_mutex); */ - if (dvb->frontend) { - dvb_frontend_detach(dvb->frontend); - dvb_unregister_frontend(dvb->frontend); - } - - dvb_dmxdev_release(&dvb->dmxdev); - dvb_dmx_release(&dvb->demux); - dvb_unregister_adapter(&dvb->adapter); - mutex_destroy(&dvb->mutex); -/* mutex_unlock(&tm6000_driver.open_close_mutex); */ -} - -static int dvb_init(struct tm6000_core *dev) -{ - struct tm6000_dvb *dvb; - int rc; - - if (!dev) - return 0; - - if (!dev->caps.has_dvb) - return 0; - - dvb = kzalloc(sizeof(struct tm6000_dvb), GFP_KERNEL); - if (!dvb) { - printk(KERN_INFO "Cannot allocate memory\n"); - return -ENOMEM; - } - - dev->dvb = dvb; - - rc = register_dvb(dev); - if (rc < 0) { - kfree(dvb); - dev->dvb = NULL; - return 0; - } - - return 0; -} - -static int dvb_fini(struct tm6000_core *dev) -{ - if (!dev) - return 0; - - if (!dev->caps.has_dvb) - return 0; - - if (dev->dvb) { - unregister_dvb(dev); - kfree(dev->dvb); - dev->dvb = NULL; - } - - return 0; -} - -static struct tm6000_ops dvb_ops = { - .type = TM6000_DVB, - .name = "TM6000 dvb Extension", - .init = dvb_init, - .fini = dvb_fini, -}; - -static int __init tm6000_dvb_register(void) -{ - return tm6000_register_extension(&dvb_ops); -} - -static void __exit tm6000_dvb_unregister(void) -{ - tm6000_unregister_extension(&dvb_ops); -} - -module_init(tm6000_dvb_register); -module_exit(tm6000_dvb_unregister); diff --git a/drivers/staging/tm6000/tm6000-i2c.c b/drivers/staging/tm6000/tm6000-i2c.c deleted file mode 100644 index 0290bbf00c3e..000000000000 --- a/drivers/staging/tm6000/tm6000-i2c.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * tm6000-i2c.c - driver for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> - * - * Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com> - * - Fix SMBus Read Byte command - * - * 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 version 2 - * - * 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 "tm6000.h" -#include "tm6000-regs.h" -#include <media/v4l2-common.h> -#include <media/tuner.h> -#include "tuner-xc2028.h" - - -/* ----------------------------------------------------------- */ - -static unsigned int i2c_debug; -module_param(i2c_debug, int, 0644); -MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); - -#define i2c_dprintk(lvl, fmt, args...) if (i2c_debug >= lvl) do { \ - printk(KERN_DEBUG "%s at %s: " fmt, \ - dev->name, __func__, ##args); } while (0) - -static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr, - __u8 reg, char *buf, int len) -{ - int rc; - unsigned int tsleep; - unsigned int i2c_packet_limit = 16; - - if (dev->dev_type == TM6010) - i2c_packet_limit = 64; - - if (!buf) - return -1; - - if (len < 1 || len > i2c_packet_limit) { - printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n", - len, i2c_packet_limit); - return -1; - } - - /* capture mutex */ - rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN, - addr | reg << 8, 0, buf, len); - - if (rc < 0) { - /* release mutex */ - return rc; - } - - /* Calculate delay time, 14000us for 64 bytes */ - tsleep = ((len * 200) + 200 + 1000) / 1000; - msleep(tsleep); - - /* release mutex */ - return rc; -} - -/* Generic read - doesn't work fine with 16bit registers */ -static int tm6000_i2c_recv_regs(struct tm6000_core *dev, unsigned char addr, - __u8 reg, char *buf, int len) -{ - int rc; - u8 b[2]; - unsigned int i2c_packet_limit = 16; - - if (dev->dev_type == TM6010) - i2c_packet_limit = 64; - - if (!buf) - return -1; - - if (len < 1 || len > i2c_packet_limit) { - printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n", - len, i2c_packet_limit); - return -1; - } - - /* capture mutex */ - if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) { - /* - * Workaround an I2C bug when reading from zl10353 - */ - reg -= 1; - len += 1; - - rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, b, len); - - *buf = b[1]; - } else { - rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len); - } - - /* release mutex */ - return rc; -} - -/* - * read from a 16bit register - * for example xc2028, xc3028 or xc3028L - */ -static int tm6000_i2c_recv_regs16(struct tm6000_core *dev, unsigned char addr, - __u16 reg, char *buf, int len) -{ - int rc; - unsigned char ureg; - - if (!buf || len != 2) - return -1; - - /* capture mutex */ - if (dev->dev_type == TM6010) { - ureg = reg & 0xFF; - rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN, - addr | (reg & 0xFF00), 0, &ureg, 1); - - if (rc < 0) { - /* release mutex */ - return rc; - } - - msleep(1400 / 1000); - rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ, - reg, 0, buf, len); - } else { - rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, REQ_14_SET_GET_I2C_WR2_RDN, - addr, reg, buf, len); - } - - /* release mutex */ - return rc; -} - -static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg msgs[], int num) -{ - struct tm6000_core *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) & 0xff; - i2c_dprintk(2, "%s %s addr=0x%x len=%d:", - (msgs[i].flags & I2C_M_RD) ? "read" : "write", - i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); - if (msgs[i].flags & I2C_M_RD) { - /* read request without preceding register selection */ - /* - * The TM6000 only supports a read transaction - * immediately after a 1 or 2 byte write to select - * a register. We cannot fulfil this request. - */ - i2c_dprintk(2, " read without preceding write not" - " supported"); - rc = -EOPNOTSUPP; - goto err; - } else if (i + 1 < num && msgs[i].len <= 2 && - (msgs[i + 1].flags & I2C_M_RD) && - msgs[i].addr == msgs[i + 1].addr) { - /* 1 or 2 byte write followed by a read */ - if (i2c_debug >= 2) - for (byte = 0; byte < msgs[i].len; byte++) - printk(KERN_CONT " %02x", msgs[i].buf[byte]); - i2c_dprintk(2, "; joined to read %s len=%d:", - i == num - 2 ? "stop" : "nonstop", - msgs[i + 1].len); - - if (msgs[i].len == 2) { - rc = tm6000_i2c_recv_regs16(dev, addr, - msgs[i].buf[0] << 8 | msgs[i].buf[1], - msgs[i + 1].buf, msgs[i + 1].len); - } else { - rc = tm6000_i2c_recv_regs(dev, addr, msgs[i].buf[0], - msgs[i + 1].buf, msgs[i + 1].len); - } - - i++; - - if (addr == dev->tuner_addr << 1) { - tm6000_set_reg(dev, REQ_50_SET_START, 0, 0); - tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0); - } - if (i2c_debug >= 2) - for (byte = 0; byte < msgs[i].len; byte++) - printk(KERN_CONT " %02x", msgs[i].buf[byte]); - } else { - /* write bytes */ - if (i2c_debug >= 2) - for (byte = 0; byte < msgs[i].len; byte++) - printk(KERN_CONT " %02x", msgs[i].buf[byte]); - rc = tm6000_i2c_send_regs(dev, addr, msgs[i].buf[0], - msgs[i].buf + 1, msgs[i].len - 1); - } - if (i2c_debug >= 2) - printk(KERN_CONT "\n"); - if (rc < 0) - goto err; - } - - return num; -err: - i2c_dprintk(2, " ERROR: %i\n", rc); - return rc; -} - -static int tm6000_i2c_eeprom(struct tm6000_core *dev) -{ - int i, rc; - unsigned char *p = dev->eedata; - unsigned char bytes[17]; - - dev->i2c_client.addr = 0xa0 >> 1; - dev->eedata_size = 0; - - bytes[16] = '\0'; - for (i = 0; i < sizeof(dev->eedata); ) { - *p = i; - rc = tm6000_i2c_recv_regs(dev, 0xa0, i, p, 1); - if (rc < 1) { - if (p == dev->eedata) - goto noeeprom; - else { - printk(KERN_WARNING - "%s: i2c eeprom read error (err=%d)\n", - dev->name, rc); - } - return -EINVAL; - } - dev->eedata_size++; - p++; - if (0 == (i % 16)) - printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i); - printk(KERN_CONT " %02x", dev->eedata[i]); - if ((dev->eedata[i] >= ' ') && (dev->eedata[i] <= 'z')) - bytes[i%16] = dev->eedata[i]; - else - bytes[i%16] = '.'; - - i++; - - if (0 == (i % 16)) { - bytes[16] = '\0'; - printk(KERN_CONT " %s\n", bytes); - } - } - if (0 != (i%16)) { - bytes[i%16] = '\0'; - for (i %= 16; i < 16; i++) - printk(KERN_CONT " "); - printk(KERN_CONT " %s\n", bytes); - } - - return 0; - -noeeprom: - printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", - dev->name, rc); - return -EINVAL; -} - -/* ----------------------------------------------------------- */ - -/* - * functionality() - */ -static u32 functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_SMBUS_EMUL; -} - -static const struct i2c_algorithm tm6000_algo = { - .master_xfer = tm6000_i2c_xfer, - .functionality = functionality, -}; - -/* ----------------------------------------------------------- */ - -/* - * tm6000_i2c_register() - * register i2c bus - */ -int tm6000_i2c_register(struct tm6000_core *dev) -{ - int rc; - - dev->i2c_adap.owner = THIS_MODULE; - dev->i2c_adap.algo = &tm6000_algo; - dev->i2c_adap.dev.parent = &dev->udev->dev; - strlcpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name)); - dev->i2c_adap.algo_data = dev; - i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); - rc = i2c_add_adapter(&dev->i2c_adap); - if (rc) - return rc; - - dev->i2c_client.adapter = &dev->i2c_adap; - strlcpy(dev->i2c_client.name, "tm6000 internal", I2C_NAME_SIZE); - tm6000_i2c_eeprom(dev); - - return 0; -} - -/* - * tm6000_i2c_unregister() - * unregister i2c_bus - */ -int tm6000_i2c_unregister(struct tm6000_core *dev) -{ - i2c_del_adapter(&dev->i2c_adap); - return 0; -} diff --git a/drivers/staging/tm6000/tm6000-input.c b/drivers/staging/tm6000/tm6000-input.c deleted file mode 100644 index 405d12729d05..000000000000 --- a/drivers/staging/tm6000/tm6000-input.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * tm6000-input.c - driver for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2010 Stefan Ringel <stefan.ringel@arcor.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 version 2 - * - * 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/init.h> -#include <linux/delay.h> - -#include <linux/input.h> -#include <linux/usb.h> - -#include <media/rc-core.h> - -#include "tm6000.h" -#include "tm6000-regs.h" - -static unsigned int ir_debug; -module_param(ir_debug, int, 0644); -MODULE_PARM_DESC(ir_debug, "enable debug message [IR]"); - -static unsigned int enable_ir = 1; -module_param(enable_ir, int, 0644); -MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)"); - -/* number of 50ms for ON-OFF-ON power led */ -/* show IR activity */ -#define PWLED_OFF 2 - -#undef dprintk - -#define dprintk(fmt, arg...) \ - if (ir_debug) { \ - printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ - } - -struct tm6000_ir_poll_result { - u16 rc_data; -}; - -struct tm6000_IR { - struct tm6000_core *dev; - struct rc_dev *rc; - char name[32]; - char phys[32]; - - /* poll expernal decoder */ - int polling; - struct delayed_work work; - u8 wait:1; - u8 key:1; - u8 pwled:1; - u8 pwledcnt; - u16 key_addr; - struct urb *int_urb; - u8 *urb_data; - - int (*get_key) (struct tm6000_IR *, struct tm6000_ir_poll_result *); - - /* IR device properties */ - u64 rc_type; -}; - - -void tm6000_ir_wait(struct tm6000_core *dev, u8 state) -{ - struct tm6000_IR *ir = dev->ir; - - if (!dev->ir) - return; - - if (state) - ir->wait = 1; - else - ir->wait = 0; -} - - -static int tm6000_ir_config(struct tm6000_IR *ir) -{ - struct tm6000_core *dev = ir->dev; - u8 buf[10]; - int rc; - - switch (ir->rc_type) { - case RC_TYPE_NEC: - /* Setup IR decoder for NEC standard 12MHz system clock */ - /* IR_LEADER_CNT = 0.9ms */ - tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER1, 0xaa); - tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER0, 0x30); - /* IR_PULSE_CNT = 0.7ms */ - tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20); - tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0); - /* Remote WAKEUP = enable */ - tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe); - /* IR_WKUP_SEL = Low byte in decoded IR data */ - tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0xff); - /* IR_WKU_ADD code */ - tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_ADD, 0xff); - tm6000_flash_led(dev, 0); - msleep(100); - tm6000_flash_led(dev, 1); - break; - default: - /* hack */ - buf[0] = 0xff; - buf[1] = 0xff; - buf[2] = 0xf2; - buf[3] = 0x2b; - buf[4] = 0x20; - buf[5] = 0x35; - buf[6] = 0x60; - buf[7] = 0x04; - buf[8] = 0xc0; - buf[9] = 0x08; - - rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, REQ_00_SET_IR_VALUE, 0, 0, buf, 0x0a); - msleep(100); - - if (rc < 0) { - printk(KERN_INFO "IR configuration failed"); - return rc; - } - break; - } - - return 0; -} - -static void tm6000_ir_urb_received(struct urb *urb) -{ - struct tm6000_core *dev = urb->context; - struct tm6000_IR *ir = dev->ir; - int rc; - - if (urb->status != 0) - printk(KERN_INFO "not ready\n"); - else if (urb->actual_length > 0) { - memcpy(ir->urb_data, urb->transfer_buffer, urb->actual_length); - - dprintk("data %02x %02x %02x %02x\n", ir->urb_data[0], - ir->urb_data[1], ir->urb_data[2], ir->urb_data[3]); - - ir->key = 1; - } - - rc = usb_submit_urb(urb, GFP_ATOMIC); -} - -static int default_polling_getkey(struct tm6000_IR *ir, - struct tm6000_ir_poll_result *poll_result) -{ - struct tm6000_core *dev = ir->dev; - int rc; - u8 buf[2]; - - if (ir->wait && !&dev->int_in) - return 0; - - if (&dev->int_in) { - switch (ir->rc_type) { - case RC_TYPE_RC5: - poll_result->rc_data = ir->urb_data[0]; - break; - case RC_TYPE_NEC: - if (ir->urb_data[1] == ((ir->key_addr >> 8) & 0xff)) { - poll_result->rc_data = ir->urb_data[0] - | ir->urb_data[1] << 8; - } - break; - default: - poll_result->rc_data = ir->urb_data[0] - | ir->urb_data[1] << 8; - break; - } - } else { - tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0); - msleep(10); - tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1); - msleep(10); - - if (ir->rc_type == RC_TYPE_RC5) { - rc = tm6000_read_write_usb(dev, USB_DIR_IN | - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - REQ_02_GET_IR_CODE, 0, 0, buf, 1); - - msleep(10); - - dprintk("read data=%02x\n", buf[0]); - if (rc < 0) - return rc; - - poll_result->rc_data = buf[0]; - } else { - rc = tm6000_read_write_usb(dev, USB_DIR_IN | - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - REQ_02_GET_IR_CODE, 0, 0, buf, 2); - - msleep(10); - - dprintk("read data=%04x\n", buf[0] | buf[1] << 8); - if (rc < 0) - return rc; - - poll_result->rc_data = buf[0] | buf[1] << 8; - } - if ((poll_result->rc_data & 0x00ff) != 0xff) - ir->key = 1; - } - return 0; -} - -static void tm6000_ir_handle_key(struct tm6000_IR *ir) -{ - struct tm6000_core *dev = ir->dev; - int result; - struct tm6000_ir_poll_result poll_result; - - /* read the registers containing the IR status */ - result = ir->get_key(ir, &poll_result); - if (result < 0) { - printk(KERN_INFO "ir->get_key() failed %d\n", result); - return; - } - - dprintk("ir->get_key result data=%04x\n", poll_result.rc_data); - - if (ir->pwled) { - if (ir->pwledcnt >= PWLED_OFF) { - ir->pwled = 0; - ir->pwledcnt = 0; - tm6000_flash_led(dev, 1); - } else - ir->pwledcnt += 1; - } - - if (ir->key) { - rc_keydown(ir->rc, poll_result.rc_data, 0); - ir->key = 0; - ir->pwled = 1; - ir->pwledcnt = 0; - tm6000_flash_led(dev, 0); - } - return; -} - -static void tm6000_ir_work(struct work_struct *work) -{ - struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work); - - tm6000_ir_handle_key(ir); - schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); -} - -static int tm6000_ir_start(struct rc_dev *rc) -{ - struct tm6000_IR *ir = rc->priv; - - INIT_DELAYED_WORK(&ir->work, tm6000_ir_work); - schedule_delayed_work(&ir->work, 0); - - return 0; -} - -static void tm6000_ir_stop(struct rc_dev *rc) -{ - struct tm6000_IR *ir = rc->priv; - - cancel_delayed_work_sync(&ir->work); -} - -static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type) -{ - struct tm6000_IR *ir = rc->priv; - - if (!ir) - return 0; - - if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC)) - ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff); - - ir->get_key = default_polling_getkey; - ir->rc_type = rc_type; - - tm6000_ir_config(ir); - /* TODO */ - return 0; -} - -int tm6000_ir_int_start(struct tm6000_core *dev) -{ - struct tm6000_IR *ir = dev->ir; - int pipe, size; - int err = -ENOMEM; - - - if (!ir) - return -ENODEV; - - ir->int_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!ir->int_urb) - return -ENOMEM; - - pipe = usb_rcvintpipe(dev->udev, - dev->int_in.endp->desc.bEndpointAddress - & USB_ENDPOINT_NUMBER_MASK); - - size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe)); - dprintk("IR max size: %d\n", size); - - ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL); - if (ir->int_urb->transfer_buffer == NULL) { - usb_free_urb(ir->int_urb); - return err; - } - dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval); - usb_fill_int_urb(ir->int_urb, dev->udev, pipe, - ir->int_urb->transfer_buffer, size, - tm6000_ir_urb_received, dev, - dev->int_in.endp->desc.bInterval); - err = usb_submit_urb(ir->int_urb, GFP_KERNEL); - if (err) { - kfree(ir->int_urb->transfer_buffer); - usb_free_urb(ir->int_urb); - return err; - } - ir->urb_data = kzalloc(size, GFP_KERNEL); - - return 0; -} - -void tm6000_ir_int_stop(struct tm6000_core *dev) -{ - struct tm6000_IR *ir = dev->ir; - - if (!ir) - return; - - usb_kill_urb(ir->int_urb); - kfree(ir->int_urb->transfer_buffer); - usb_free_urb(ir->int_urb); - ir->int_urb = NULL; - kfree(ir->urb_data); - ir->urb_data = NULL; -} - -int tm6000_ir_init(struct tm6000_core *dev) -{ - struct tm6000_IR *ir; - struct rc_dev *rc; - int err = -ENOMEM; - - if (!enable_ir) - return -ENODEV; - - if (!dev->caps.has_remote) - return 0; - - if (!dev->ir_codes) - return 0; - - ir = kzalloc(sizeof(*ir), GFP_KERNEL); - rc = rc_allocate_device(); - if (!ir || !rc) - goto out; - - /* record handles to ourself */ - ir->dev = dev; - dev->ir = ir; - ir->rc = rc; - - /* input einrichten */ - rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC; - rc->priv = ir; - rc->change_protocol = tm6000_ir_change_protocol; - rc->open = tm6000_ir_start; - rc->close = tm6000_ir_stop; - rc->driver_type = RC_DRIVER_SCANCODE; - - ir->polling = 50; - ir->pwled = 0; - ir->pwledcnt = 0; - - - snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)", - dev->name); - - usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); - strlcat(ir->phys, "/input0", sizeof(ir->phys)); - - tm6000_ir_change_protocol(rc, RC_TYPE_UNKNOWN); - - 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->map_name = dev->ir_codes; - rc->driver_name = "tm6000"; - rc->dev.parent = &dev->udev->dev; - - if (&dev->int_in) { - dprintk("IR over int\n"); - - err = tm6000_ir_int_start(dev); - - if (err) - goto out; - } - - /* ir register */ - err = rc_register_device(rc); - if (err) - goto out; - - return 0; - -out: - dev->ir = NULL; - rc_free_device(rc); - kfree(ir); - return err; -} - -int tm6000_ir_fini(struct tm6000_core *dev) -{ - struct tm6000_IR *ir = dev->ir; - - /* skip detach on non attached board */ - - if (!ir) - return 0; - - rc_unregister_device(ir->rc); - - if (ir->int_urb) - tm6000_ir_int_stop(dev); - - kfree(ir); - dev->ir = NULL; - - return 0; -} diff --git a/drivers/staging/tm6000/tm6000-regs.h b/drivers/staging/tm6000/tm6000-regs.h deleted file mode 100644 index 7f491b6de933..000000000000 --- a/drivers/staging/tm6000/tm6000-regs.h +++ /dev/null @@ -1,600 +0,0 @@ -/* - * tm6000-regs.h - driver for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 - * - * 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. - */ - -/* - * Define TV Master TM5600/TM6000/TM6010 Request codes - */ -#define REQ_00_SET_IR_VALUE 0 -#define REQ_01_SET_WAKEUP_IRCODE 1 -#define REQ_02_GET_IR_CODE 2 -#define REQ_03_SET_GET_MCU_PIN 3 -#define REQ_04_EN_DISABLE_MCU_INT 4 -#define REQ_05_SET_GET_USBREG 5 - /* Write: RegNum, Value, 0 */ - /* Read : RegNum, Value, 1, RegStatus */ -#define REQ_06_SET_GET_USBREG_BIT 6 -#define REQ_07_SET_GET_AVREG 7 - /* Write: RegNum, Value, 0 */ - /* Read : RegNum, Value, 1, RegStatus */ -#define REQ_08_SET_GET_AVREG_BIT 8 -#define REQ_09_SET_GET_TUNER_FQ 9 -#define REQ_10_SET_TUNER_SYSTEM 10 -#define REQ_11_SET_EEPROM_ADDR 11 -#define REQ_12_SET_GET_EEPROMBYTE 12 -#define REQ_13_GET_EEPROM_SEQREAD 13 -#define REQ_14_SET_GET_I2C_WR2_RDN 14 -#define REQ_15_SET_GET_I2CBYTE 15 - /* Write: Subaddr, Slave Addr, value, 0 */ - /* Read : Subaddr, Slave Addr, value, 1 */ -#define REQ_16_SET_GET_I2C_WR1_RDN 16 - /* Subaddr, Slave Addr, 0, length */ -#define REQ_17_SET_GET_I2CFP 17 - /* Write: Slave Addr, register, value */ - /* Read : Slave Addr, register, 2, data */ -#define REQ_20_DATA_TRANSFER 20 -#define REQ_30_I2C_WRITE 30 -#define REQ_31_I2C_READ 31 -#define REQ_35_AFTEK_TUNER_READ 35 -#define REQ_40_GET_VERSION 40 -#define REQ_50_SET_START 50 -#define REQ_51_SET_STOP 51 -#define REQ_52_TRANSMIT_DATA 52 -#define REQ_53_SPI_INITIAL 53 -#define REQ_54_SPI_SETSTART 54 -#define REQ_55_SPI_INOUTDATA 55 -#define REQ_56_SPI_SETSTOP 56 - -/* - * Define TV Master TM5600/TM6000/TM6010 GPIO lines - */ - -#define TM6000_GPIO_CLK 0x101 -#define TM6000_GPIO_DATA 0x100 - -#define TM6000_GPIO_1 0x102 -#define TM6000_GPIO_2 0x103 -#define TM6000_GPIO_3 0x104 -#define TM6000_GPIO_4 0x300 -#define TM6000_GPIO_5 0x301 -#define TM6000_GPIO_6 0x304 -#define TM6000_GPIO_7 0x305 - -/* tm6010 defines GPIO with different values */ -#define TM6010_GPIO_0 0x0102 -#define TM6010_GPIO_1 0x0103 -#define TM6010_GPIO_2 0x0104 -#define TM6010_GPIO_3 0x0105 -#define TM6010_GPIO_4 0x0106 -#define TM6010_GPIO_5 0x0107 -#define TM6010_GPIO_6 0x0300 -#define TM6010_GPIO_7 0x0301 -#define TM6010_GPIO_9 0x0305 -/* - * Define TV Master TM5600/TM6000/TM6010 URB message codes and length - */ - -enum { - TM6000_URB_MSG_VIDEO = 1, - TM6000_URB_MSG_AUDIO, - TM6000_URB_MSG_VBI, - TM6000_URB_MSG_PTS, - TM6000_URB_MSG_ERR, -}; - -/* Define specific TM6000 Video decoder registers */ -#define TM6000_REQ07_RD8_TEST_SEL 0x07, 0xd8 -#define TM6000_REQ07_RD9_A_SIM_SEL 0x07, 0xd9 -#define TM6000_REQ07_RDA_CLK_SEL 0x07, 0xda -#define TM6000_REQ07_RDB_OUT_SEL 0x07, 0xdb -#define TM6000_REQ07_RDC_NSEL_I2S 0x07, 0xdc -#define TM6000_REQ07_RDD_GPIO2_MDRV 0x07, 0xdd -#define TM6000_REQ07_RDE_GPIO1_MDRV 0x07, 0xde -#define TM6000_REQ07_RDF_PWDOWN_ACLK 0x07, 0xdf -#define TM6000_REQ07_RE0_VADC_REF_CTL 0x07, 0xe0 -#define TM6000_REQ07_RE1_VADC_DACLIMP 0x07, 0xe1 -#define TM6000_REQ07_RE2_VADC_STATUS_CTL 0x07, 0xe2 -#define TM6000_REQ07_RE3_VADC_INP_LPF_SEL1 0x07, 0xe3 -#define TM6000_REQ07_RE4_VADC_TARGET1 0x07, 0xe4 -#define TM6000_REQ07_RE5_VADC_INP_LPF_SEL2 0x07, 0xe5 -#define TM6000_REQ07_RE6_VADC_TARGET2 0x07, 0xe6 -#define TM6000_REQ07_RE7_VADC_AGAIN_CTL 0x07, 0xe7 -#define TM6000_REQ07_RE8_VADC_PWDOWN_CTL 0x07, 0xe8 -#define TM6000_REQ07_RE9_VADC_INPUT_CTL1 0x07, 0xe9 -#define TM6000_REQ07_REA_VADC_INPUT_CTL2 0x07, 0xea -#define TM6000_REQ07_REB_VADC_AADC_MODE 0x07, 0xeb -#define TM6000_REQ07_REC_VADC_AADC_LVOL 0x07, 0xec -#define TM6000_REQ07_RED_VADC_AADC_RVOL 0x07, 0xed -#define TM6000_REQ07_REE_VADC_CTRL_SEL_CONTROL 0x07, 0xee -#define TM6000_REQ07_REF_VADC_GAIN_MAP_CTL 0x07, 0xef -#define TM6000_REQ07_RFD_BIST_ERR_VST_LOW 0x07, 0xfd -#define TM6000_REQ07_RFE_BIST_ERR_VST_HIGH 0x07, 0xfe - -/* Define TM6000/TM6010 Video decoder registers */ -#define TM6010_REQ07_R00_VIDEO_CONTROL0 0x07, 0x00 -#define TM6010_REQ07_R01_VIDEO_CONTROL1 0x07, 0x01 -#define TM6010_REQ07_R02_VIDEO_CONTROL2 0x07, 0x02 -#define TM6010_REQ07_R03_YC_SEP_CONTROL 0x07, 0x03 -#define TM6010_REQ07_R04_LUMA_HAGC_CONTROL 0x07, 0x04 -#define TM6010_REQ07_R05_NOISE_THRESHOLD 0x07, 0x05 -#define TM6010_REQ07_R06_AGC_GATE_THRESHOLD 0x07, 0x06 -#define TM6010_REQ07_R07_OUTPUT_CONTROL 0x07, 0x07 -#define TM6010_REQ07_R08_LUMA_CONTRAST_ADJ 0x07, 0x08 -#define TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ 0x07, 0x09 -#define TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ 0x07, 0x0a -#define TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ 0x07, 0x0b -#define TM6010_REQ07_R0C_CHROMA_AGC_CONTROL 0x07, 0x0c -#define TM6010_REQ07_R0D_CHROMA_KILL_LEVEL 0x07, 0x0d -#define TM6010_REQ07_R0F_CHROMA_AUTO_POSITION 0x07, 0x0f -#define TM6010_REQ07_R10_AGC_PEAK_NOMINAL 0x07, 0x10 -#define TM6010_REQ07_R11_AGC_PEAK_CONTROL 0x07, 0x11 -#define TM6010_REQ07_R12_AGC_GATE_STARTH 0x07, 0x12 -#define TM6010_REQ07_R13_AGC_GATE_STARTL 0x07, 0x13 -#define TM6010_REQ07_R14_AGC_GATE_WIDTH 0x07, 0x14 -#define TM6010_REQ07_R15_AGC_BP_DELAY 0x07, 0x15 -#define TM6010_REQ07_R16_LOCK_COUNT 0x07, 0x16 -#define TM6010_REQ07_R17_HLOOP_MAXSTATE 0x07, 0x17 -#define TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3 0x07, 0x18 -#define TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2 0x07, 0x19 -#define TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1 0x07, 0x1a -#define TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0 0x07, 0x1b -#define TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3 0x07, 0x1c -#define TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2 0x07, 0x1d -#define TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1 0x07, 0x1e -#define TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0 0x07, 0x1f -#define TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME 0x07, 0x20 -#define TM6010_REQ07_R21_HSYNC_PHASE_OFFSET 0x07, 0x21 -#define TM6010_REQ07_R22_HSYNC_PLL_START_TIME 0x07, 0x22 -#define TM6010_REQ07_R23_HSYNC_PLL_END_TIME 0x07, 0x23 -#define TM6010_REQ07_R24_HSYNC_TIP_START_TIME 0x07, 0x24 -#define TM6010_REQ07_R25_HSYNC_TIP_END_TIME 0x07, 0x25 -#define TM6010_REQ07_R26_HSYNC_RISING_EDGE_START 0x07, 0x26 -#define TM6010_REQ07_R27_HSYNC_RISING_EDGE_END 0x07, 0x27 -#define TM6010_REQ07_R28_BACKPORCH_START 0x07, 0x28 -#define TM6010_REQ07_R29_BACKPORCH_END 0x07, 0x29 -#define TM6010_REQ07_R2A_HSYNC_FILTER_START 0x07, 0x2a -#define TM6010_REQ07_R2B_HSYNC_FILTER_END 0x07, 0x2b -#define TM6010_REQ07_R2C_CHROMA_BURST_START 0x07, 0x2c -#define TM6010_REQ07_R2D_CHROMA_BURST_END 0x07, 0x2d -#define TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART 0x07, 0x2e -#define TM6010_REQ07_R2F_ACTIVE_VIDEO_HWIDTH 0x07, 0x2f -#define TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART 0x07, 0x30 -#define TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT 0x07, 0x31 -#define TM6010_REQ07_R32_VSYNC_HLOCK_MIN 0x07, 0x32 -#define TM6010_REQ07_R33_VSYNC_HLOCK_MAX 0x07, 0x33 -#define TM6010_REQ07_R34_VSYNC_AGC_MIN 0x07, 0x34 -#define TM6010_REQ07_R35_VSYNC_AGC_MAX 0x07, 0x35 -#define TM6010_REQ07_R36_VSYNC_VBI_MIN 0x07, 0x36 -#define TM6010_REQ07_R37_VSYNC_VBI_MAX 0x07, 0x37 -#define TM6010_REQ07_R38_VSYNC_THRESHOLD 0x07, 0x38 -#define TM6010_REQ07_R39_VSYNC_TIME_CONSTANT 0x07, 0x39 -#define TM6010_REQ07_R3A_STATUS1 0x07, 0x3a -#define TM6010_REQ07_R3B_STATUS2 0x07, 0x3b -#define TM6010_REQ07_R3C_STATUS3 0x07, 0x3c -#define TM6010_REQ07_R3F_RESET 0x07, 0x3f -#define TM6010_REQ07_R40_TELETEXT_VBI_CODE0 0x07, 0x40 -#define TM6010_REQ07_R41_TELETEXT_VBI_CODE1 0x07, 0x41 -#define TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL 0x07, 0x42 -#define TM6010_REQ07_R43_VBI_DATA_TYPE_LINE7 0x07, 0x43 -#define TM6010_REQ07_R44_VBI_DATA_TYPE_LINE8 0x07, 0x44 -#define TM6010_REQ07_R45_VBI_DATA_TYPE_LINE9 0x07, 0x45 -#define TM6010_REQ07_R46_VBI_DATA_TYPE_LINE10 0x07, 0x46 -#define TM6010_REQ07_R47_VBI_DATA_TYPE_LINE11 0x07, 0x47 -#define TM6010_REQ07_R48_VBI_DATA_TYPE_LINE12 0x07, 0x48 -#define TM6010_REQ07_R49_VBI_DATA_TYPE_LINE13 0x07, 0x49 -#define TM6010_REQ07_R4A_VBI_DATA_TYPE_LINE14 0x07, 0x4a -#define TM6010_REQ07_R4B_VBI_DATA_TYPE_LINE15 0x07, 0x4b -#define TM6010_REQ07_R4C_VBI_DATA_TYPE_LINE16 0x07, 0x4c -#define TM6010_REQ07_R4D_VBI_DATA_TYPE_LINE17 0x07, 0x4d -#define TM6010_REQ07_R4E_VBI_DATA_TYPE_LINE18 0x07, 0x4e -#define TM6010_REQ07_R4F_VBI_DATA_TYPE_LINE19 0x07, 0x4f -#define TM6010_REQ07_R50_VBI_DATA_TYPE_LINE20 0x07, 0x50 -#define TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21 0x07, 0x51 -#define TM6010_REQ07_R52_VBI_DATA_TYPE_LINE22 0x07, 0x52 -#define TM6010_REQ07_R53_VBI_DATA_TYPE_LINE23 0x07, 0x53 -#define TM6010_REQ07_R54_VBI_DATA_TYPE_RLINES 0x07, 0x54 -#define TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN 0x07, 0x55 -#define TM6010_REQ07_R56_VBI_LOOP_FILTER_I_GAIN 0x07, 0x56 -#define TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN 0x07, 0x57 -#define TM6010_REQ07_R58_VBI_CAPTION_DTO1 0x07, 0x58 -#define TM6010_REQ07_R59_VBI_CAPTION_DTO0 0x07, 0x59 -#define TM6010_REQ07_R5A_VBI_TELETEXT_DTO1 0x07, 0x5a -#define TM6010_REQ07_R5B_VBI_TELETEXT_DTO0 0x07, 0x5b -#define TM6010_REQ07_R5C_VBI_WSS625_DTO1 0x07, 0x5c -#define TM6010_REQ07_R5D_VBI_WSS625_DTO0 0x07, 0x5d -#define TM6010_REQ07_R5E_VBI_CAPTION_FRAME_START 0x07, 0x5e -#define TM6010_REQ07_R5F_VBI_WSS625_FRAME_START 0x07, 0x5f -#define TM6010_REQ07_R60_TELETEXT_FRAME_START 0x07, 0x60 -#define TM6010_REQ07_R61_VBI_CCDATA1 0x07, 0x61 -#define TM6010_REQ07_R62_VBI_CCDATA2 0x07, 0x62 -#define TM6010_REQ07_R63_VBI_WSS625_DATA1 0x07, 0x63 -#define TM6010_REQ07_R64_VBI_WSS625_DATA2 0x07, 0x64 -#define TM6010_REQ07_R65_VBI_DATA_STATUS 0x07, 0x65 -#define TM6010_REQ07_R66_VBI_CAPTION_START 0x07, 0x66 -#define TM6010_REQ07_R67_VBI_WSS625_START 0x07, 0x67 -#define TM6010_REQ07_R68_VBI_TELETEXT_START 0x07, 0x68 -#define TM6010_REQ07_R70_HSYNC_DTO_INC_STATUS3 0x07, 0x70 -#define TM6010_REQ07_R71_HSYNC_DTO_INC_STATUS2 0x07, 0x71 -#define TM6010_REQ07_R72_HSYNC_DTO_INC_STATUS1 0x07, 0x72 -#define TM6010_REQ07_R73_HSYNC_DTO_INC_STATUS0 0x07, 0x73 -#define TM6010_REQ07_R74_CHROMA_DTO_INC_STATUS3 0x07, 0x74 -#define TM6010_REQ07_R75_CHROMA_DTO_INC_STATUS2 0x07, 0x75 -#define TM6010_REQ07_R76_CHROMA_DTO_INC_STATUS1 0x07, 0x76 -#define TM6010_REQ07_R77_CHROMA_DTO_INC_STATUS0 0x07, 0x77 -#define TM6010_REQ07_R78_AGC_AGAIN_STATUS 0x07, 0x78 -#define TM6010_REQ07_R79_AGC_DGAIN_STATUS 0x07, 0x79 -#define TM6010_REQ07_R7A_CHROMA_MAG_STATUS 0x07, 0x7a -#define TM6010_REQ07_R7B_CHROMA_GAIN_STATUS1 0x07, 0x7b -#define TM6010_REQ07_R7C_CHROMA_GAIN_STATUS0 0x07, 0x7c -#define TM6010_REQ07_R7D_CORDIC_FREQ_STATUS 0x07, 0x7d -#define TM6010_REQ07_R7F_STATUS_NOISE 0x07, 0x7f -#define TM6010_REQ07_R80_COMB_FILTER_TRESHOLD 0x07, 0x80 -#define TM6010_REQ07_R82_COMB_FILTER_CONFIG 0x07, 0x82 -#define TM6010_REQ07_R83_CHROMA_LOCK_CONFIG 0x07, 0x83 -#define TM6010_REQ07_R84_NOISE_NTSC_C 0x07, 0x84 -#define TM6010_REQ07_R85_NOISE_PAL_C 0x07, 0x85 -#define TM6010_REQ07_R86_NOISE_PHASE_C 0x07, 0x86 -#define TM6010_REQ07_R87_NOISE_PHASE_Y 0x07, 0x87 -#define TM6010_REQ07_R8A_CHROMA_LOOPFILTER_STATE 0x07, 0x8a -#define TM6010_REQ07_R8B_CHROMA_HRESAMPLER 0x07, 0x8b -#define TM6010_REQ07_R8D_CPUMP_DELAY_ADJ 0x07, 0x8d -#define TM6010_REQ07_R8E_CPUMP_ADJ 0x07, 0x8e -#define TM6010_REQ07_R8F_CPUMP_DELAY 0x07, 0x8f - -/* Define TM6000/TM6010 Miscellaneous registers */ -#define TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE 0x07, 0xc0 -#define TM6010_REQ07_RC1_TRESHOLD 0x07, 0xc1 -#define TM6010_REQ07_RC2_HSYNC_WIDTH 0x07, 0xc2 -#define TM6010_REQ07_RC3_HSTART1 0x07, 0xc3 -#define TM6010_REQ07_RC4_HSTART0 0x07, 0xc4 -#define TM6010_REQ07_RC5_HEND1 0x07, 0xc5 -#define TM6010_REQ07_RC6_HEND0 0x07, 0xc6 -#define TM6010_REQ07_RC7_VSTART1 0x07, 0xc7 -#define TM6010_REQ07_RC8_VSTART0 0x07, 0xc8 -#define TM6010_REQ07_RC9_VEND1 0x07, 0xc9 -#define TM6010_REQ07_RCA_VEND0 0x07, 0xca -#define TM6010_REQ07_RCB_DELAY 0x07, 0xcb -/* ONLY for TM6010 */ -#define TM6010_REQ07_RCC_ACTIVE_IF 0x07, 0xcc -#define TM6010_REQ07_RCC_ACTIVE_IF_VIDEO_ENABLE (1 << 5) -#define TM6010_REQ07_RCC_ACTIVE_IF_AUDIO_ENABLE (1 << 6) -#define TM6010_REQ07_RD0_USB_PERIPHERY_CONTROL 0x07, 0xd0 -#define TM6010_REQ07_RD1_ADDR_FOR_REQ1 0x07, 0xd1 -#define TM6010_REQ07_RD2_ADDR_FOR_REQ2 0x07, 0xd2 -#define TM6010_REQ07_RD3_ADDR_FOR_REQ3 0x07, 0xd3 -#define TM6010_REQ07_RD4_ADDR_FOR_REQ4 0x07, 0xd4 -#define TM6010_REQ07_RD5_POWERSAVE 0x07, 0xd5 -#define TM6010_REQ07_RD6_ENDP_REQ1_REQ2 0x07, 0xd6 -#define TM6010_REQ07_RD7_ENDP_REQ3_REQ4 0x07, 0xd7 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RD8_IR 0x07, 0xd8 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RD8_IR_BSIZE 0x07, 0xd9 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RD8_IR_WAKEUP_SEL 0x07, 0xda -/* ONLY for TM6010 */ -#define TM6010_REQ07_RD8_IR_WAKEUP_ADD 0x07, 0xdb -/* ONLY for TM6010 */ -#define TM6010_REQ07_RD8_IR_LEADER1 0x07, 0xdc -/* ONLY for TM6010 */ -#define TM6010_REQ07_RD8_IR_LEADER0 0x07, 0xdd -/* ONLY for TM6010 */ -#define TM6010_REQ07_RD8_IR_PULSE_CNT1 0x07, 0xde -/* ONLY for TM6010 */ -#define TM6010_REQ07_RD8_IR_PULSE_CNT0 0x07, 0xdf -/* ONLY for TM6010 */ -#define TM6010_REQ07_RE0_DVIDEO_SOURCE 0x07, 0xe0 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RE0_DVIDEO_SOURCE_IF 0x07, 0xe1 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RE2_OUT_SEL2 0x07, 0xe2 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RE3_OUT_SEL1 0x07, 0xe3 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RE4_OUT_SEL0 0x07, 0xe4 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RE5_REMOTE_WAKEUP 0x07, 0xe5 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RE7_PUB_GPIO 0x07, 0xe7 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RE8_TYPESEL_MOS_I2S 0x07, 0xe8 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RE9_TYPESEL_MOS_TS 0x07, 0xe9 -/* ONLY for TM6010 */ -#define TM6010_REQ07_REA_TYPESEL_MOS_CCIR 0x07, 0xea -/* ONLY for TM6010 */ -#define TM6010_REQ07_RF0_BIST_CRC_RESULT0 0x07, 0xf0 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RF1_BIST_CRC_RESULT1 0x07, 0xf1 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RF2_BIST_CRC_RESULT2 0x07, 0xf2 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RF3_BIST_CRC_RESULT3 0x07, 0xf3 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RF4_BIST_ERR_VST2 0x07, 0xf4 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RF5_BIST_ERR_VST1 0x07, 0xf5 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RF6_BIST_ERR_VST0 0x07, 0xf6 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RF7_BIST 0x07, 0xf7 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RFE_POWER_DOWN 0x07, 0xfe -#define TM6010_REQ07_RFF_SOFT_RESET 0x07, 0xff - -/* Define TM6000/TM6010 USB registers */ -#define TM6010_REQ05_R00_MAIN_CTRL 0x05, 0x00 -#define TM6010_REQ05_R01_DEVADDR 0x05, 0x01 -#define TM6010_REQ05_R02_TEST 0x05, 0x02 -#define TM6010_REQ05_R04_SOFN0 0x05, 0x04 -#define TM6010_REQ05_R05_SOFN1 0x05, 0x05 -#define TM6010_REQ05_R06_SOFTM0 0x05, 0x06 -#define TM6010_REQ05_R07_SOFTM1 0x05, 0x07 -#define TM6010_REQ05_R08_PHY_TEST 0x05, 0x08 -#define TM6010_REQ05_R09_VCTL 0x05, 0x09 -#define TM6010_REQ05_R0A_VSTA 0x05, 0x0a -#define TM6010_REQ05_R0B_CX_CFG 0x05, 0x0b -#define TM6010_REQ05_R0C_ENDP0_REG0 0x05, 0x0c -#define TM6010_REQ05_R10_GMASK 0x05, 0x10 -#define TM6010_REQ05_R11_IMASK0 0x05, 0x11 -#define TM6010_REQ05_R12_IMASK1 0x05, 0x12 -#define TM6010_REQ05_R13_IMASK2 0x05, 0x13 -#define TM6010_REQ05_R14_IMASK3 0x05, 0x14 -#define TM6010_REQ05_R15_IMASK4 0x05, 0x15 -#define TM6010_REQ05_R16_IMASK5 0x05, 0x16 -#define TM6010_REQ05_R17_IMASK6 0x05, 0x17 -#define TM6010_REQ05_R18_IMASK7 0x05, 0x18 -#define TM6010_REQ05_R19_ZEROP0 0x05, 0x19 -#define TM6010_REQ05_R1A_ZEROP1 0x05, 0x1a -#define TM6010_REQ05_R1C_FIFO_EMP0 0x05, 0x1c -#define TM6010_REQ05_R1D_FIFO_EMP1 0x05, 0x1d -#define TM6010_REQ05_R20_IRQ_GROUP 0x05, 0x20 -#define TM6010_REQ05_R21_IRQ_SOURCE0 0x05, 0x21 -#define TM6010_REQ05_R22_IRQ_SOURCE1 0x05, 0x22 -#define TM6010_REQ05_R23_IRQ_SOURCE2 0x05, 0x23 -#define TM6010_REQ05_R24_IRQ_SOURCE3 0x05, 0x24 -#define TM6010_REQ05_R25_IRQ_SOURCE4 0x05, 0x25 -#define TM6010_REQ05_R26_IRQ_SOURCE5 0x05, 0x26 -#define TM6010_REQ05_R27_IRQ_SOURCE6 0x05, 0x27 -#define TM6010_REQ05_R28_IRQ_SOURCE7 0x05, 0x28 -#define TM6010_REQ05_R29_SEQ_ERR0 0x05, 0x29 -#define TM6010_REQ05_R2A_SEQ_ERR1 0x05, 0x2a -#define TM6010_REQ05_R2B_SEQ_ABORT0 0x05, 0x2b -#define TM6010_REQ05_R2C_SEQ_ABORT1 0x05, 0x2c -#define TM6010_REQ05_R2D_TX_ZERO0 0x05, 0x2d -#define TM6010_REQ05_R2E_TX_ZERO1 0x05, 0x2e -#define TM6010_REQ05_R2F_IDLE_CNT 0x05, 0x2f -#define TM6010_REQ05_R30_FNO_P1 0x05, 0x30 -#define TM6010_REQ05_R31_FNO_P2 0x05, 0x31 -#define TM6010_REQ05_R32_FNO_P3 0x05, 0x32 -#define TM6010_REQ05_R33_FNO_P4 0x05, 0x33 -#define TM6010_REQ05_R34_FNO_P5 0x05, 0x34 -#define TM6010_REQ05_R35_FNO_P6 0x05, 0x35 -#define TM6010_REQ05_R36_FNO_P7 0x05, 0x36 -#define TM6010_REQ05_R37_FNO_P8 0x05, 0x37 -#define TM6010_REQ05_R38_FNO_P9 0x05, 0x38 -#define TM6010_REQ05_R30_FNO_P10 0x05, 0x39 -#define TM6010_REQ05_R30_FNO_P11 0x05, 0x3a -#define TM6010_REQ05_R30_FNO_P12 0x05, 0x3b -#define TM6010_REQ05_R30_FNO_P13 0x05, 0x3c -#define TM6010_REQ05_R30_FNO_P14 0x05, 0x3d -#define TM6010_REQ05_R30_FNO_P15 0x05, 0x3e -#define TM6010_REQ05_R40_IN_MAXPS_LOW1 0x05, 0x40 -#define TM6010_REQ05_R41_IN_MAXPS_HIGH1 0x05, 0x41 -#define TM6010_REQ05_R42_IN_MAXPS_LOW2 0x05, 0x42 -#define TM6010_REQ05_R43_IN_MAXPS_HIGH2 0x05, 0x43 -#define TM6010_REQ05_R44_IN_MAXPS_LOW3 0x05, 0x44 -#define TM6010_REQ05_R45_IN_MAXPS_HIGH3 0x05, 0x45 -#define TM6010_REQ05_R46_IN_MAXPS_LOW4 0x05, 0x46 -#define TM6010_REQ05_R47_IN_MAXPS_HIGH4 0x05, 0x47 -#define TM6010_REQ05_R48_IN_MAXPS_LOW5 0x05, 0x48 -#define TM6010_REQ05_R49_IN_MAXPS_HIGH5 0x05, 0x49 -#define TM6010_REQ05_R4A_IN_MAXPS_LOW6 0x05, 0x4a -#define TM6010_REQ05_R4B_IN_MAXPS_HIGH6 0x05, 0x4b -#define TM6010_REQ05_R4C_IN_MAXPS_LOW7 0x05, 0x4c -#define TM6010_REQ05_R4D_IN_MAXPS_HIGH7 0x05, 0x4d -#define TM6010_REQ05_R4E_IN_MAXPS_LOW8 0x05, 0x4e -#define TM6010_REQ05_R4F_IN_MAXPS_HIGH8 0x05, 0x4f -#define TM6010_REQ05_R50_IN_MAXPS_LOW9 0x05, 0x50 -#define TM6010_REQ05_R51_IN_MAXPS_HIGH9 0x05, 0x51 -#define TM6010_REQ05_R40_IN_MAXPS_LOW10 0x05, 0x52 -#define TM6010_REQ05_R41_IN_MAXPS_HIGH10 0x05, 0x53 -#define TM6010_REQ05_R40_IN_MAXPS_LOW11 0x05, 0x54 -#define TM6010_REQ05_R41_IN_MAXPS_HIGH11 0x05, 0x55 -#define TM6010_REQ05_R40_IN_MAXPS_LOW12 0x05, 0x56 -#define TM6010_REQ05_R41_IN_MAXPS_HIGH12 0x05, 0x57 -#define TM6010_REQ05_R40_IN_MAXPS_LOW13 0x05, 0x58 -#define TM6010_REQ05_R41_IN_MAXPS_HIGH13 0x05, 0x59 -#define TM6010_REQ05_R40_IN_MAXPS_LOW14 0x05, 0x5a -#define TM6010_REQ05_R41_IN_MAXPS_HIGH14 0x05, 0x5b -#define TM6010_REQ05_R40_IN_MAXPS_LOW15 0x05, 0x5c -#define TM6010_REQ05_R41_IN_MAXPS_HIGH15 0x05, 0x5d -#define TM6010_REQ05_R60_OUT_MAXPS_LOW1 0x05, 0x60 -#define TM6010_REQ05_R61_OUT_MAXPS_HIGH1 0x05, 0x61 -#define TM6010_REQ05_R62_OUT_MAXPS_LOW2 0x05, 0x62 -#define TM6010_REQ05_R63_OUT_MAXPS_HIGH2 0x05, 0x63 -#define TM6010_REQ05_R64_OUT_MAXPS_LOW3 0x05, 0x64 -#define TM6010_REQ05_R65_OUT_MAXPS_HIGH3 0x05, 0x65 -#define TM6010_REQ05_R66_OUT_MAXPS_LOW4 0x05, 0x66 -#define TM6010_REQ05_R67_OUT_MAXPS_HIGH4 0x05, 0x67 -#define TM6010_REQ05_R68_OUT_MAXPS_LOW5 0x05, 0x68 -#define TM6010_REQ05_R69_OUT_MAXPS_HIGH5 0x05, 0x69 -#define TM6010_REQ05_R6A_OUT_MAXPS_LOW6 0x05, 0x6a -#define TM6010_REQ05_R6B_OUT_MAXPS_HIGH6 0x05, 0x6b -#define TM6010_REQ05_R6C_OUT_MAXPS_LOW7 0x05, 0x6c -#define TM6010_REQ05_R6D_OUT_MAXPS_HIGH7 0x05, 0x6d -#define TM6010_REQ05_R6E_OUT_MAXPS_LOW8 0x05, 0x6e -#define TM6010_REQ05_R6F_OUT_MAXPS_HIGH8 0x05, 0x6f -#define TM6010_REQ05_R70_OUT_MAXPS_LOW9 0x05, 0x70 -#define TM6010_REQ05_R71_OUT_MAXPS_HIGH9 0x05, 0x71 -#define TM6010_REQ05_R60_OUT_MAXPS_LOW10 0x05, 0x72 -#define TM6010_REQ05_R61_OUT_MAXPS_HIGH10 0x05, 0x73 -#define TM6010_REQ05_R60_OUT_MAXPS_LOW11 0x05, 0x74 -#define TM6010_REQ05_R61_OUT_MAXPS_HIGH11 0x05, 0x75 -#define TM6010_REQ05_R60_OUT_MAXPS_LOW12 0x05, 0x76 -#define TM6010_REQ05_R61_OUT_MAXPS_HIGH12 0x05, 0x77 -#define TM6010_REQ05_R60_OUT_MAXPS_LOW13 0x05, 0x78 -#define TM6010_REQ05_R61_OUT_MAXPS_HIGH13 0x05, 0x79 -#define TM6010_REQ05_R60_OUT_MAXPS_LOW14 0x05, 0x7a -#define TM6010_REQ05_R61_OUT_MAXPS_HIGH14 0x05, 0x7b -#define TM6010_REQ05_R60_OUT_MAXPS_LOW15 0x05, 0x7c -#define TM6010_REQ05_R61_OUT_MAXPS_HIGH15 0x05, 0x7d -#define TM6010_REQ05_R80_FIFO0 0x05, 0x80 -#define TM6010_REQ05_R81_FIFO1 0x05, 0x81 -#define TM6010_REQ05_R82_FIFO2 0x05, 0x82 -#define TM6010_REQ05_R83_FIFO3 0x05, 0x83 -#define TM6010_REQ05_R84_FIFO4 0x05, 0x84 -#define TM6010_REQ05_R85_FIFO5 0x05, 0x85 -#define TM6010_REQ05_R86_FIFO6 0x05, 0x86 -#define TM6010_REQ05_R87_FIFO7 0x05, 0x87 -#define TM6010_REQ05_R88_FIFO8 0x05, 0x88 -#define TM6010_REQ05_R89_FIFO9 0x05, 0x89 -#define TM6010_REQ05_R81_FIFO10 0x05, 0x8a -#define TM6010_REQ05_R81_FIFO11 0x05, 0x8b -#define TM6010_REQ05_R81_FIFO12 0x05, 0x8c -#define TM6010_REQ05_R81_FIFO13 0x05, 0x8d -#define TM6010_REQ05_R81_FIFO14 0x05, 0x8e -#define TM6010_REQ05_R81_FIFO15 0x05, 0x8f -#define TM6010_REQ05_R90_CFG_FIFO0 0x05, 0x90 -#define TM6010_REQ05_R91_CFG_FIFO1 0x05, 0x91 -#define TM6010_REQ05_R92_CFG_FIFO2 0x05, 0x92 -#define TM6010_REQ05_R93_CFG_FIFO3 0x05, 0x93 -#define TM6010_REQ05_R94_CFG_FIFO4 0x05, 0x94 -#define TM6010_REQ05_R95_CFG_FIFO5 0x05, 0x95 -#define TM6010_REQ05_R96_CFG_FIFO6 0x05, 0x96 -#define TM6010_REQ05_R97_CFG_FIFO7 0x05, 0x97 -#define TM6010_REQ05_R98_CFG_FIFO8 0x05, 0x98 -#define TM6010_REQ05_R99_CFG_FIFO9 0x05, 0x99 -#define TM6010_REQ05_R91_CFG_FIFO10 0x05, 0x9a -#define TM6010_REQ05_R91_CFG_FIFO11 0x05, 0x9b -#define TM6010_REQ05_R91_CFG_FIFO12 0x05, 0x9c -#define TM6010_REQ05_R91_CFG_FIFO13 0x05, 0x9d -#define TM6010_REQ05_R91_CFG_FIFO14 0x05, 0x9e -#define TM6010_REQ05_R91_CFG_FIFO15 0x05, 0x9f -#define TM6010_REQ05_RA0_CTL_FIFO0 0x05, 0xa0 -#define TM6010_REQ05_RA1_CTL_FIFO1 0x05, 0xa1 -#define TM6010_REQ05_RA2_CTL_FIFO2 0x05, 0xa2 -#define TM6010_REQ05_RA3_CTL_FIFO3 0x05, 0xa3 -#define TM6010_REQ05_RA4_CTL_FIFO4 0x05, 0xa4 -#define TM6010_REQ05_RA5_CTL_FIFO5 0x05, 0xa5 -#define TM6010_REQ05_RA6_CTL_FIFO6 0x05, 0xa6 -#define TM6010_REQ05_RA7_CTL_FIFO7 0x05, 0xa7 -#define TM6010_REQ05_RA8_CTL_FIFO8 0x05, 0xa8 -#define TM6010_REQ05_RA9_CTL_FIFO9 0x05, 0xa9 -#define TM6010_REQ05_RA1_CTL_FIFO10 0x05, 0xaa -#define TM6010_REQ05_RA1_CTL_FIFO11 0x05, 0xab -#define TM6010_REQ05_RA1_CTL_FIFO12 0x05, 0xac -#define TM6010_REQ05_RA1_CTL_FIFO13 0x05, 0xad -#define TM6010_REQ05_RA1_CTL_FIFO14 0x05, 0xae -#define TM6010_REQ05_RA1_CTL_FIFO15 0x05, 0xaf -#define TM6010_REQ05_RB0_BC_LOW_FIFO0 0x05, 0xb0 -#define TM6010_REQ05_RB1_BC_LOW_FIFO1 0x05, 0xb1 -#define TM6010_REQ05_RB2_BC_LOW_FIFO2 0x05, 0xb2 -#define TM6010_REQ05_RB3_BC_LOW_FIFO3 0x05, 0xb3 -#define TM6010_REQ05_RB4_BC_LOW_FIFO4 0x05, 0xb4 -#define TM6010_REQ05_RB5_BC_LOW_FIFO5 0x05, 0xb5 -#define TM6010_REQ05_RB6_BC_LOW_FIFO6 0x05, 0xb6 -#define TM6010_REQ05_RB7_BC_LOW_FIFO7 0x05, 0xb7 -#define TM6010_REQ05_RB8_BC_LOW_FIFO8 0x05, 0xb8 -#define TM6010_REQ05_RB9_BC_LOW_FIFO9 0x05, 0xb9 -#define TM6010_REQ05_RB1_BC_LOW_FIFO10 0x05, 0xba -#define TM6010_REQ05_RB1_BC_LOW_FIFO11 0x05, 0xbb -#define TM6010_REQ05_RB1_BC_LOW_FIFO12 0x05, 0xbc -#define TM6010_REQ05_RB1_BC_LOW_FIFO13 0x05, 0xbd -#define TM6010_REQ05_RB1_BC_LOW_FIFO14 0x05, 0xbe -#define TM6010_REQ05_RB1_BC_LOW_FIFO15 0x05, 0xbf -#define TM6010_REQ05_RC0_DATA_FIFO0 0x05, 0xc0 -#define TM6010_REQ05_RC4_DATA_FIFO1 0x05, 0xc4 -#define TM6010_REQ05_RC8_DATA_FIFO2 0x05, 0xc8 -#define TM6010_REQ05_RCC_DATA_FIFO3 0x05, 0xcc -#define TM6010_REQ05_RD0_DATA_FIFO4 0x05, 0xd0 -#define TM6010_REQ05_RD4_DATA_FIFO5 0x05, 0xd4 -#define TM6010_REQ05_RD8_DATA_FIFO6 0x05, 0xd8 -#define TM6010_REQ05_RDC_DATA_FIFO7 0x05, 0xdc -#define TM6010_REQ05_RE0_DATA_FIFO8 0x05, 0xe0 -#define TM6010_REQ05_RE4_DATA_FIFO9 0x05, 0xe4 -#define TM6010_REQ05_RC4_DATA_FIFO10 0x05, 0xe8 -#define TM6010_REQ05_RC4_DATA_FIFO11 0x05, 0xec -#define TM6010_REQ05_RC4_DATA_FIFO12 0x05, 0xf0 -#define TM6010_REQ05_RC4_DATA_FIFO13 0x05, 0xf4 -#define TM6010_REQ05_RC4_DATA_FIFO14 0x05, 0xf8 -#define TM6010_REQ05_RC4_DATA_FIFO15 0x05, 0xfc - -/* Define TM6010 Audio decoder registers */ -/* This core available only in TM6010 */ -#define TM6010_REQ08_R00_A_VERSION 0x08, 0x00 -#define TM6010_REQ08_R01_A_INIT 0x08, 0x01 -#define TM6010_REQ08_R02_A_FIX_GAIN_CTRL 0x08, 0x02 -#define TM6010_REQ08_R03_A_AUTO_GAIN_CTRL 0x08, 0x03 -#define TM6010_REQ08_R04_A_SIF_AMP_CTRL 0x08, 0x04 -#define TM6010_REQ08_R05_A_STANDARD_MOD 0x08, 0x05 -#define TM6010_REQ08_R06_A_SOUND_MOD 0x08, 0x06 -#define TM6010_REQ08_R07_A_LEFT_VOL 0x08, 0x07 -#define TM6010_REQ08_R08_A_RIGHT_VOL 0x08, 0x08 -#define TM6010_REQ08_R09_A_MAIN_VOL 0x08, 0x09 -#define TM6010_REQ08_R0A_A_I2S_MOD 0x08, 0x0a -#define TM6010_REQ08_R0B_A_ASD_THRES1 0x08, 0x0b -#define TM6010_REQ08_R0C_A_ASD_THRES2 0x08, 0x0c -#define TM6010_REQ08_R0D_A_AMD_THRES 0x08, 0x0d -#define TM6010_REQ08_R0E_A_MONO_THRES1 0x08, 0x0e -#define TM6010_REQ08_R0F_A_MONO_THRES2 0x08, 0x0f -#define TM6010_REQ08_R10_A_MUTE_THRES1 0x08, 0x10 -#define TM6010_REQ08_R11_A_MUTE_THRES2 0x08, 0x11 -#define TM6010_REQ08_R12_A_AGC_U 0x08, 0x12 -#define TM6010_REQ08_R13_A_AGC_ERR_T 0x08, 0x13 -#define TM6010_REQ08_R14_A_AGC_GAIN_INIT 0x08, 0x14 -#define TM6010_REQ08_R15_A_AGC_STEP_THR 0x08, 0x15 -#define TM6010_REQ08_R16_A_AGC_GAIN_MAX 0x08, 0x16 -#define TM6010_REQ08_R17_A_AGC_GAIN_MIN 0x08, 0x17 -#define TM6010_REQ08_R18_A_TR_CTRL 0x08, 0x18 -#define TM6010_REQ08_R19_A_FH_2FH_GAIN 0x08, 0x19 -#define TM6010_REQ08_R1A_A_NICAM_SER_MAX 0x08, 0x1a -#define TM6010_REQ08_R1B_A_NICAM_SER_MIN 0x08, 0x1b -#define TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT 0x08, 0x1e -#define TM6010_REQ08_R1F_A_TEST_INTF_SEL 0x08, 0x1f -#define TM6010_REQ08_R20_A_TEST_PIN_SEL 0x08, 0x20 -#define TM6010_REQ08_R21_A_AGC_ERR 0x08, 0x21 -#define TM6010_REQ08_R22_A_AGC_GAIN 0x08, 0x22 -#define TM6010_REQ08_R23_A_NICAM_INFO 0x08, 0x23 -#define TM6010_REQ08_R24_A_SER 0x08, 0x24 -#define TM6010_REQ08_R25_A_C1_AMP 0x08, 0x25 -#define TM6010_REQ08_R26_A_C2_AMP 0x08, 0x26 -#define TM6010_REQ08_R27_A_NOISE_AMP 0x08, 0x27 -#define TM6010_REQ08_R28_A_AUDIO_MODE_RES 0x08, 0x28 - -/* Define TM6010 Video ADC registers */ -#define TM6010_REQ08_RE0_ADC_REF 0x08, 0xe0 -#define TM6010_REQ08_RE1_DAC_CLMP 0x08, 0xe1 -#define TM6010_REQ08_RE2_POWER_DOWN_CTRL1 0x08, 0xe2 -#define TM6010_REQ08_RE3_ADC_IN1_SEL 0x08, 0xe3 -#define TM6010_REQ08_RE4_ADC_IN2_SEL 0x08, 0xe4 -#define TM6010_REQ08_RE5_GAIN_PARAM 0x08, 0xe5 -#define TM6010_REQ08_RE6_POWER_DOWN_CTRL2 0x08, 0xe6 -#define TM6010_REQ08_RE7_REG_GAIN_Y 0x08, 0xe7 -#define TM6010_REQ08_RE8_REG_GAIN_C 0x08, 0xe8 -#define TM6010_REQ08_RE9_BIAS_CTRL 0x08, 0xe9 -#define TM6010_REQ08_REA_BUFF_DRV_CTRL 0x08, 0xea -#define TM6010_REQ08_REB_SIF_GAIN_CTRL 0x08, 0xeb -#define TM6010_REQ08_REC_REVERSE_YC_CTRL 0x08, 0xec -#define TM6010_REQ08_RED_GAIN_SEL 0x08, 0xed - -/* Define TM6010 Audio ADC registers */ -#define TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG 0x08, 0xf0 -#define TM6010_REQ08_RF1_AADC_POWER_DOWN 0x08, 0xf1 -#define TM6010_REQ08_RF2_LEFT_CHANNEL_VOL 0x08, 0xf2 -#define TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL 0x08, 0xf3 diff --git a/drivers/staging/tm6000/tm6000-stds.c b/drivers/staging/tm6000/tm6000-stds.c deleted file mode 100644 index 9a4145dc3d87..000000000000 --- a/drivers/staging/tm6000/tm6000-stds.c +++ /dev/null @@ -1,659 +0,0 @@ -/* - * tm6000-stds.c - driver for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2007 Mauro Carvalho Chehab <mchehab@redhat.com> - * - * 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 version 2 - * - * 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 "tm6000.h" -#include "tm6000-regs.h" - -static unsigned int tm6010_a_mode; -module_param(tm6010_a_mode, int, 0644); -MODULE_PARM_DESC(tm6010_a_mode, "set tm6010 sif audio mode"); - -struct tm6000_reg_settings { - unsigned char req; - unsigned char reg; - unsigned char value; -}; - - -struct tm6000_std_settings { - v4l2_std_id id; - struct tm6000_reg_settings *common; -}; - -static struct tm6000_reg_settings composite_pal_m[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x04 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83 }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe0 }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x20 }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f }, - { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_reg_settings composite_pal_nc[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x36 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91 }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x0c }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f }, - { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_reg_settings composite_pal[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x32 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25 }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5 }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63 }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x50 }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f }, - { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_reg_settings composite_secam[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x38 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24 }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92 }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8 }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xed }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x2c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x18 }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xff }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_reg_settings composite_ntsc[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f }, - { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_std_settings composite_stds[] = { - { .id = V4L2_STD_PAL_M, .common = composite_pal_m, }, - { .id = V4L2_STD_PAL_Nc, .common = composite_pal_nc, }, - { .id = V4L2_STD_PAL, .common = composite_pal, }, - { .id = V4L2_STD_SECAM, .common = composite_secam, }, - { .id = V4L2_STD_NTSC, .common = composite_ntsc, }, -}; - -static struct tm6000_reg_settings svideo_pal_m[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x05 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83 }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe0 }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f }, - { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_reg_settings svideo_pal_nc[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x37 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91 }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x0c }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f }, - { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_reg_settings svideo_pal[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x33 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x30 }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25 }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5 }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63 }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x50 }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2a }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f }, - { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_reg_settings svideo_secam[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x39 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24 }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92 }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8 }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xed }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2a }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x2c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x18 }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xff }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_reg_settings svideo_ntsc[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x01 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x30 }, - { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0x8b }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f }, - { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_std_settings svideo_stds[] = { - { .id = V4L2_STD_PAL_M, .common = svideo_pal_m, }, - { .id = V4L2_STD_PAL_Nc, .common = svideo_pal_nc, }, - { .id = V4L2_STD_PAL, .common = svideo_pal, }, - { .id = V4L2_STD_SECAM, .common = svideo_secam, }, - { .id = V4L2_STD_NTSC, .common = svideo_ntsc, }, -}; - -static int tm6000_set_audio_std(struct tm6000_core *dev) -{ - uint8_t areg_02 = 0x04; /* GC1 Fixed gain 0dB */ - uint8_t areg_05 = 0x01; /* Auto 4.5 = M Japan, Auto 6.5 = DK */ - uint8_t areg_06 = 0x02; /* Auto de-emphasis, mannual channel mode */ - uint8_t nicam_flag = 0; /* No NICAM */ - - if (dev->radio) { - tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x00); - tm6000_set_reg(dev, TM6010_REQ08_R02_A_FIX_GAIN_CTRL, 0x04); - tm6000_set_reg(dev, TM6010_REQ08_R03_A_AUTO_GAIN_CTRL, 0x00); - tm6000_set_reg(dev, TM6010_REQ08_R04_A_SIF_AMP_CTRL, 0x80); - tm6000_set_reg(dev, TM6010_REQ08_R05_A_STANDARD_MOD, 0x0c); - /* set mono or stereo */ - if (dev->amode == V4L2_TUNER_MODE_MONO) - tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x00); - else if (dev->amode == V4L2_TUNER_MODE_STEREO) - tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x02); - tm6000_set_reg(dev, TM6010_REQ08_R09_A_MAIN_VOL, 0x18); - tm6000_set_reg(dev, TM6010_REQ08_R0C_A_ASD_THRES2, 0x0a); - tm6000_set_reg(dev, TM6010_REQ08_R0D_A_AMD_THRES, 0x40); - tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfe); - tm6000_set_reg(dev, TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT, 0x13); - tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x80); - tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, 0xff); - return 0; - } - - switch (tm6010_a_mode) { - /* auto */ - case 0: - switch (dev->norm) { - case V4L2_STD_NTSC_M_KR: - areg_05 |= 0x00; - break; - case V4L2_STD_NTSC_M_JP: - areg_05 |= 0x40; - break; - case V4L2_STD_NTSC_M: - case V4L2_STD_PAL_M: - case V4L2_STD_PAL_N: - areg_05 |= 0x20; - break; - case V4L2_STD_PAL_Nc: - areg_05 |= 0x60; - break; - case V4L2_STD_SECAM_L: - areg_05 |= 0x00; - break; - case V4L2_STD_DK: - areg_05 |= 0x10; - break; - } - break; - /* A2 */ - case 1: - switch (dev->norm) { - case V4L2_STD_B: - case V4L2_STD_GH: - areg_05 = 0x05; - break; - case V4L2_STD_DK: - areg_05 = 0x09; - break; - } - break; - /* NICAM */ - case 2: - switch (dev->norm) { - case V4L2_STD_B: - case V4L2_STD_GH: - areg_05 = 0x07; - break; - case V4L2_STD_DK: - areg_05 = 0x06; - break; - case V4L2_STD_PAL_I: - areg_05 = 0x08; - break; - case V4L2_STD_SECAM_L: - areg_05 = 0x0a; - areg_02 = 0x02; - break; - } - nicam_flag = 1; - break; - /* other */ - case 3: - switch (dev->norm) { - /* DK3_A2 */ - case V4L2_STD_DK: - areg_05 = 0x0b; - break; - /* Korea */ - case V4L2_STD_NTSC_M_KR: - areg_05 = 0x04; - break; - /* EIAJ */ - case V4L2_STD_NTSC_M_JP: - areg_05 = 0x03; - break; - default: - areg_05 = 0x02; - break; - } - break; - } - - tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x00); - tm6000_set_reg(dev, TM6010_REQ08_R02_A_FIX_GAIN_CTRL, areg_02); - tm6000_set_reg(dev, TM6010_REQ08_R03_A_AUTO_GAIN_CTRL, 0x00); - tm6000_set_reg(dev, TM6010_REQ08_R04_A_SIF_AMP_CTRL, 0xa0); - tm6000_set_reg(dev, TM6010_REQ08_R05_A_STANDARD_MOD, areg_05); - tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, areg_06); - tm6000_set_reg(dev, TM6010_REQ08_R07_A_LEFT_VOL, 0x00); - tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, 0x00); - tm6000_set_reg(dev, TM6010_REQ08_R09_A_MAIN_VOL, 0x08); - tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, 0x91); - tm6000_set_reg(dev, TM6010_REQ08_R0B_A_ASD_THRES1, 0x20); - tm6000_set_reg(dev, TM6010_REQ08_R0C_A_ASD_THRES2, 0x12); - tm6000_set_reg(dev, TM6010_REQ08_R0D_A_AMD_THRES, 0x20); - tm6000_set_reg(dev, TM6010_REQ08_R0E_A_MONO_THRES1, 0xf0); - tm6000_set_reg(dev, TM6010_REQ08_R0F_A_MONO_THRES2, 0x80); - tm6000_set_reg(dev, TM6010_REQ08_R10_A_MUTE_THRES1, 0xc0); - tm6000_set_reg(dev, TM6010_REQ08_R11_A_MUTE_THRES2, 0x80); - tm6000_set_reg(dev, TM6010_REQ08_R12_A_AGC_U, 0x12); - tm6000_set_reg(dev, TM6010_REQ08_R13_A_AGC_ERR_T, 0xfe); - tm6000_set_reg(dev, TM6010_REQ08_R14_A_AGC_GAIN_INIT, 0x20); - tm6000_set_reg(dev, TM6010_REQ08_R15_A_AGC_STEP_THR, 0x14); - tm6000_set_reg(dev, TM6010_REQ08_R16_A_AGC_GAIN_MAX, 0xfe); - tm6000_set_reg(dev, TM6010_REQ08_R17_A_AGC_GAIN_MIN, 0x01); - tm6000_set_reg(dev, TM6010_REQ08_R18_A_TR_CTRL, 0xa0); - tm6000_set_reg(dev, TM6010_REQ08_R19_A_FH_2FH_GAIN, 0x32); - tm6000_set_reg(dev, TM6010_REQ08_R1A_A_NICAM_SER_MAX, 0x64); - tm6000_set_reg(dev, TM6010_REQ08_R1B_A_NICAM_SER_MIN, 0x20); - tm6000_set_reg(dev, REQ_08_SET_GET_AVREG_BIT, 0x1c, 0x00); - tm6000_set_reg(dev, REQ_08_SET_GET_AVREG_BIT, 0x1d, 0x00); - tm6000_set_reg(dev, TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT, 0x13); - tm6000_set_reg(dev, TM6010_REQ08_R1F_A_TEST_INTF_SEL, 0x00); - tm6000_set_reg(dev, TM6010_REQ08_R20_A_TEST_PIN_SEL, 0x00); - tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x80); - - return 0; -} - -void tm6000_get_std_res(struct tm6000_core *dev) -{ - /* Currently, those are the only supported resoltions */ - if (dev->norm & V4L2_STD_525_60) - dev->height = 480; - else - dev->height = 576; - - dev->width = 720; -} - -static int tm6000_load_std(struct tm6000_core *dev, struct tm6000_reg_settings *set) -{ - int i, rc; - - /* Load board's initialization table */ - for (i = 0; set[i].req; i++) { - rc = tm6000_set_reg(dev, set[i].req, set[i].reg, set[i].value); - if (rc < 0) { - printk(KERN_ERR "Error %i while setting " - "req %d, reg %d to value %d\n", - rc, set[i].req, set[i].reg, set[i].value); - return rc; - } - } - - return 0; -} - -int tm6000_set_standard(struct tm6000_core *dev) -{ - struct tm6000_input *input; - int i, rc = 0; - u8 reg_07_fe = 0x8a; - u8 reg_08_f1 = 0xfc; - u8 reg_08_e2 = 0xf0; - u8 reg_08_e6 = 0x0f; - - tm6000_get_std_res(dev); - - if (!dev->radio) - input = &dev->vinput[dev->input]; - else - input = &dev->rinput; - - if (dev->dev_type == TM6010) { - switch (input->vmux) { - case TM6000_VMUX_VIDEO_A: - tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4); - tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1); - tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0); - tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2); - tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe8); - reg_07_fe |= 0x01; - break; - case TM6000_VMUX_VIDEO_B: - tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8); - tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1); - tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0); - tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2); - tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe8); - reg_07_fe |= 0x01; - break; - case TM6000_VMUX_VIDEO_AB: - tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xfc); - tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8); - reg_08_e6 = 0x00; - tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2); - tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0); - tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2); - tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe0); - break; - default: - break; - } - switch (input->amux) { - case TM6000_AMUX_ADC1: - tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, - 0x00, 0x0f); - break; - case TM6000_AMUX_ADC2: - tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, - 0x08, 0x0f); - break; - case TM6000_AMUX_SIF1: - reg_08_e2 |= 0x02; - reg_08_e6 = 0x08; - reg_07_fe |= 0x40; - reg_08_f1 |= 0x02; - tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3); - tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, - 0x02, 0x0f); - break; - case TM6000_AMUX_SIF2: - reg_08_e2 |= 0x02; - reg_08_e6 = 0x08; - reg_07_fe |= 0x40; - reg_08_f1 |= 0x02; - tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf7); - tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, - 0x02, 0x0f); - break; - default: - break; - } - tm6000_set_reg(dev, TM6010_REQ08_RE2_POWER_DOWN_CTRL1, reg_08_e2); - tm6000_set_reg(dev, TM6010_REQ08_RE6_POWER_DOWN_CTRL2, reg_08_e6); - tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, reg_08_f1); - tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, reg_07_fe); - } else { - switch (input->vmux) { - case TM6000_VMUX_VIDEO_A: - tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10); - tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00); - tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x0f); - tm6000_set_reg(dev, - REQ_03_SET_GET_MCU_PIN, input->v_gpio, 0); - break; - case TM6000_VMUX_VIDEO_B: - tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x00); - tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00); - tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x0f); - tm6000_set_reg(dev, - REQ_03_SET_GET_MCU_PIN, input->v_gpio, 0); - break; - case TM6000_VMUX_VIDEO_AB: - tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10); - tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x10); - tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x00); - tm6000_set_reg(dev, - REQ_03_SET_GET_MCU_PIN, input->v_gpio, 1); - break; - default: - break; - } - switch (input->amux) { - case TM6000_AMUX_ADC1: - tm6000_set_reg_mask(dev, - TM6000_REQ07_REB_VADC_AADC_MODE, 0x00, 0x0f); - break; - case TM6000_AMUX_ADC2: - tm6000_set_reg_mask(dev, - TM6000_REQ07_REB_VADC_AADC_MODE, 0x04, 0x0f); - break; - default: - break; - } - } - if (input->type == TM6000_INPUT_SVIDEO) { - for (i = 0; i < ARRAY_SIZE(svideo_stds); i++) { - if (dev->norm & svideo_stds[i].id) { - rc = tm6000_load_std(dev, svideo_stds[i].common); - goto ret; - } - } - return -EINVAL; - } else { - for (i = 0; i < ARRAY_SIZE(composite_stds); i++) { - if (dev->norm & composite_stds[i].id) { - rc = tm6000_load_std(dev, composite_stds[i].common); - goto ret; - } - } - return -EINVAL; - } - -ret: - if (rc < 0) - return rc; - - if ((dev->dev_type == TM6010) && - ((input->amux == TM6000_AMUX_SIF1) || - (input->amux == TM6000_AMUX_SIF2))) - tm6000_set_audio_std(dev); - - msleep(40); - - return 0; -} diff --git a/drivers/staging/tm6000/tm6000-usb-isoc.h b/drivers/staging/tm6000/tm6000-usb-isoc.h deleted file mode 100644 index 99d15a55aa03..000000000000 --- a/drivers/staging/tm6000/tm6000-usb-isoc.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * tm6000-buf.c - driver for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 - * - * 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/videodev2.h> - -#define TM6000_URB_MSG_LEN 180 - -struct usb_isoc_ctl { - /* max packet size of isoc transaction */ - int max_pkt_size; - - /* number of allocated urbs */ - int num_bufs; - - /* urb for isoc transfers */ - struct urb **urb; - - /* transfer buffers for isoc transfer */ - char **transfer_buffer; - - /* Last buffer command and region */ - u8 cmd; - int pos, size, pktsize; - - /* Last field: ODD or EVEN? */ - int vfield, field; - - /* Stores incomplete commands */ - u32 tmp_buf; - int tmp_buf_len; - - /* Stores already requested buffers */ - struct tm6000_buffer *buf; -}; diff --git a/drivers/staging/tm6000/tm6000-video.c b/drivers/staging/tm6000/tm6000-video.c deleted file mode 100644 index 1e5ace0b5d10..000000000000 --- a/drivers/staging/tm6000/tm6000-video.c +++ /dev/null @@ -1,1813 +0,0 @@ -/* - * tm6000-video.c - driver for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> - * - * Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com> - * - Fixed module load/unload - * - * 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 version 2 - * - * 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/delay.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/sched.h> -#include <linux/random.h> -#include <linux/usb.h> -#include <linux/videodev2.h> -#include <media/v4l2-ioctl.h> -#include <media/tuner.h> -#include <linux/interrupt.h> -#include <linux/kthread.h> -#include <linux/highmem.h> -#include <linux/freezer.h> - -#include "tm6000-regs.h" -#include "tm6000.h" - -#define BUFFER_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ - -/* Limits minimum and default number of buffers */ -#define TM6000_MIN_BUF 4 -#define TM6000_DEF_BUF 8 - -#define TM6000_MAX_ISO_PACKETS 46 /* Max number of ISO packets */ - -/* Declare static vars that will be used as parameters */ -static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ -static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ -static int radio_nr = -1; /* /dev/radioN, -1 for autodetect */ - -/* Debug level */ -int tm6000_debug; -EXPORT_SYMBOL_GPL(tm6000_debug); - -static const struct v4l2_queryctrl no_ctrl = { - .name = "42", - .flags = V4L2_CTRL_FLAG_DISABLED, -}; - -/* supported controls */ -static struct v4l2_queryctrl tm6000_qctrl[] = { - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = 0, - .maximum = 255, - .step = 1, - .default_value = 54, - .flags = 0, - }, { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contrast", - .minimum = 0, - .maximum = 255, - .step = 0x1, - .default_value = 119, - .flags = 0, - }, { - .id = V4L2_CID_SATURATION, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Saturation", - .minimum = 0, - .maximum = 255, - .step = 0x1, - .default_value = 112, - .flags = 0, - }, { - .id = V4L2_CID_HUE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Hue", - .minimum = -128, - .maximum = 127, - .step = 0x1, - .default_value = 0, - .flags = 0, - }, - /* --- audio --- */ - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - }, { - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = -15, - .maximum = 15, - .step = 1, - .default_value = 0, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; - -static const unsigned int CTRLS = ARRAY_SIZE(tm6000_qctrl); -static int qctl_regs[ARRAY_SIZE(tm6000_qctrl)]; - -static struct tm6000_fmt format[] = { - { - .name = "4:2:2, packed, YVY2", - .fourcc = V4L2_PIX_FMT_YUYV, - .depth = 16, - }, { - .name = "4:2:2, packed, UYVY", - .fourcc = V4L2_PIX_FMT_UYVY, - .depth = 16, - }, { - .name = "A/V + VBI mux packet", - .fourcc = V4L2_PIX_FMT_TM6000, - .depth = 16, - } -}; - -static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id) -{ - unsigned int i; - - for (i = 0; i < CTRLS; i++) - if (tm6000_qctrl[i].id == id) - return tm6000_qctrl+i; - return NULL; -} - -/* ------------------------------------------------------------------ - * DMA and thread functions - * ------------------------------------------------------------------ - */ - -#define norm_maxw(a) 720 -#define norm_maxh(a) 576 - -#define norm_minw(a) norm_maxw(a) -#define norm_minh(a) norm_maxh(a) - -/* - * video-buf generic routine to get the next available buffer - */ -static inline void get_next_buf(struct tm6000_dmaqueue *dma_q, - struct tm6000_buffer **buf) -{ - struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq); - char *outp; - - if (list_empty(&dma_q->active)) { - dprintk(dev, V4L2_DEBUG_QUEUE, "No active queue to serve\n"); - *buf = NULL; - return; - } - - *buf = list_entry(dma_q->active.next, - struct tm6000_buffer, vb.queue); - - /* Cleans up buffer - Useful for testing for frame/URB loss */ - outp = videobuf_to_vmalloc(&(*buf)->vb); - - return; -} - -/* - * Announces that a buffer were filled and request the next - */ -static inline void buffer_filled(struct tm6000_core *dev, - struct tm6000_dmaqueue *dma_q, - struct tm6000_buffer *buf) -{ - /* Advice that buffer was filled */ - dprintk(dev, V4L2_DEBUG_ISOC, "[%p/%d] wakeup\n", buf, buf->vb.i); - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - do_gettimeofday(&buf->vb.ts); - - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); -} - -/* - * Identify the tm5600/6000 buffer header type and properly handles - */ -static int copy_streams(u8 *data, unsigned long len, - struct urb *urb) -{ - struct tm6000_dmaqueue *dma_q = urb->context; - struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq); - u8 *ptr = data, *endp = data+len, c; - unsigned long header = 0; - int rc = 0; - unsigned int cmd, cpysize, pktsize, size, field, block, line, pos = 0; - struct tm6000_buffer *vbuf = NULL; - char *voutp = NULL; - unsigned int linewidth; - - if (!dev->radio) { - /* get video buffer */ - get_next_buf(dma_q, &vbuf); - - if (!vbuf) - return rc; - voutp = videobuf_to_vmalloc(&vbuf->vb); - - if (!voutp) - return 0; - } - - for (ptr = data; ptr < endp;) { - if (!dev->isoc_ctl.cmd) { - /* Header */ - if (dev->isoc_ctl.tmp_buf_len > 0) { - /* from last urb or packet */ - header = dev->isoc_ctl.tmp_buf; - if (4 - dev->isoc_ctl.tmp_buf_len > 0) { - memcpy((u8 *)&header + - dev->isoc_ctl.tmp_buf_len, - ptr, - 4 - dev->isoc_ctl.tmp_buf_len); - ptr += 4 - dev->isoc_ctl.tmp_buf_len; - } - dev->isoc_ctl.tmp_buf_len = 0; - } else { - if (ptr + 3 >= endp) { - /* have incomplete header */ - dev->isoc_ctl.tmp_buf_len = endp - ptr; - memcpy(&dev->isoc_ctl.tmp_buf, ptr, - dev->isoc_ctl.tmp_buf_len); - return rc; - } - /* Seek for sync */ - for (; ptr < endp - 3; ptr++) { - if (*(ptr + 3) == 0x47) - break; - } - /* Get message header */ - header = *(unsigned long *)ptr; - ptr += 4; - } - - /* split the header fields */ - c = (header >> 24) & 0xff; - size = ((header & 0x7e) << 1); - if (size > 0) - size -= 4; - block = (header >> 7) & 0xf; - field = (header >> 11) & 0x1; - line = (header >> 12) & 0x1ff; - cmd = (header >> 21) & 0x7; - /* Validates haeder fields */ - if (size > TM6000_URB_MSG_LEN) - size = TM6000_URB_MSG_LEN; - pktsize = TM6000_URB_MSG_LEN; - /* - * calculate position in buffer and change the buffer - */ - switch (cmd) { - case TM6000_URB_MSG_VIDEO: - if (!dev->radio) { - if ((dev->isoc_ctl.vfield != field) && - (field == 1)) { - /* - * Announces that a new buffer - * were filled - */ - buffer_filled(dev, dma_q, vbuf); - dprintk(dev, V4L2_DEBUG_ISOC, - "new buffer filled\n"); - get_next_buf(dma_q, &vbuf); - if (!vbuf) - return rc; - voutp = videobuf_to_vmalloc(&vbuf->vb); - if (!voutp) - return rc; - memset(voutp, 0, vbuf->vb.size); - } - linewidth = vbuf->vb.width << 1; - pos = ((line << 1) - field - 1) * - linewidth + block * TM6000_URB_MSG_LEN; - /* Don't allow to write out of the buffer */ - if (pos + size > vbuf->vb.size) - cmd = TM6000_URB_MSG_ERR; - dev->isoc_ctl.vfield = field; - } - break; - case TM6000_URB_MSG_VBI: - break; - case TM6000_URB_MSG_AUDIO: - case TM6000_URB_MSG_PTS: - size = pktsize; /* Size is always 180 bytes */ - break; - } - } else { - /* Continue the last copy */ - cmd = dev->isoc_ctl.cmd; - size = dev->isoc_ctl.size; - pos = dev->isoc_ctl.pos; - pktsize = dev->isoc_ctl.pktsize; - field = dev->isoc_ctl.field; - } - cpysize = (endp - ptr > size) ? size : endp - ptr; - if (cpysize) { - /* copy data in different buffers */ - switch (cmd) { - case TM6000_URB_MSG_VIDEO: - /* Fills video buffer */ - if (vbuf) - memcpy(&voutp[pos], ptr, cpysize); - break; - case TM6000_URB_MSG_AUDIO: { - int i; - for (i = 0; i < cpysize; i += 2) - swab16s((u16 *)(ptr + i)); - - tm6000_call_fillbuf(dev, TM6000_AUDIO, ptr, cpysize); - break; - } - case TM6000_URB_MSG_VBI: - /* Need some code to copy vbi buffer */ - break; - case TM6000_URB_MSG_PTS: { - /* Need some code to copy pts */ - u32 pts; - pts = *(u32 *)ptr; - dprintk(dev, V4L2_DEBUG_ISOC, "field %d, PTS %x", - field, pts); - break; - } - } - } - if (ptr + pktsize > endp) { - /* - * End of URB packet, but cmd processing is not - * complete. Preserve the state for a next packet - */ - dev->isoc_ctl.pos = pos + cpysize; - dev->isoc_ctl.size = size - cpysize; - dev->isoc_ctl.cmd = cmd; - dev->isoc_ctl.field = field; - dev->isoc_ctl.pktsize = pktsize - (endp - ptr); - ptr += endp - ptr; - } else { - dev->isoc_ctl.cmd = 0; - ptr += pktsize; - } - } - return 0; -} - -/* - * Identify the tm5600/6000 buffer header type and properly handles - */ -static int copy_multiplexed(u8 *ptr, unsigned long len, - struct urb *urb) -{ - struct tm6000_dmaqueue *dma_q = urb->context; - struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq); - unsigned int pos = dev->isoc_ctl.pos, cpysize; - int rc = 1; - struct tm6000_buffer *buf; - char *outp = NULL; - - get_next_buf(dma_q, &buf); - if (buf) - outp = videobuf_to_vmalloc(&buf->vb); - - if (!outp) - return 0; - - while (len > 0) { - cpysize = min(len, buf->vb.size-pos); - memcpy(&outp[pos], ptr, cpysize); - pos += cpysize; - ptr += cpysize; - len -= cpysize; - if (pos >= buf->vb.size) { - pos = 0; - /* Announces that a new buffer were filled */ - buffer_filled(dev, dma_q, buf); - dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n"); - get_next_buf(dma_q, &buf); - if (!buf) - break; - outp = videobuf_to_vmalloc(&(buf->vb)); - if (!outp) - return rc; - pos = 0; - } - } - - dev->isoc_ctl.pos = pos; - return rc; -} - -static inline void print_err_status(struct tm6000_core *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(dev, V4L2_DEBUG_QUEUE, "URB status %d [%s].\n", - status, errmsg); - } else { - dprintk(dev, V4L2_DEBUG_QUEUE, "URB packet %d, status %d [%s].\n", - packet, status, errmsg); - } -} - - -/* - * Controls the isoc copy of each urb packet - */ -static inline int tm6000_isoc_copy(struct urb *urb) -{ - struct tm6000_dmaqueue *dma_q = urb->context; - struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq); - int i, len = 0, rc = 1, status; - char *p; - - if (urb->status < 0) { - print_err_status(dev, -1, urb->status); - return 0; - } - - for (i = 0; i < urb->number_of_packets; i++) { - status = urb->iso_frame_desc[i].status; - - if (status < 0) { - print_err_status(dev, i, status); - continue; - } - - len = urb->iso_frame_desc[i].actual_length; - - if (len > 0) { - p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - if (!urb->iso_frame_desc[i].status) { - if ((dev->fourcc) == V4L2_PIX_FMT_TM6000) { - rc = copy_multiplexed(p, len, urb); - if (rc <= 0) - return rc; - } else { - copy_streams(p, len, urb); - } - } - } - } - return rc; -} - -/* ------------------------------------------------------------------ - * URB control - * ------------------------------------------------------------------ - */ - -/* - * IRQ callback, called by URB callback - */ -static void tm6000_irq_callback(struct urb *urb) -{ - struct tm6000_dmaqueue *dma_q = urb->context; - struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq); - int i; - - switch (urb->status) { - case 0: - case -ETIMEDOUT: - break; - - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - return; - - default: - tm6000_err("urb completion error %d.\n", urb->status); - break; - } - - spin_lock(&dev->slock); - tm6000_isoc_copy(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 = usb_submit_urb(urb, GFP_ATOMIC); - if (urb->status) - tm6000_err("urb resubmit failed (error=%i)\n", - urb->status); -} - -/* - * Stop and Deallocate URBs - */ -static void tm6000_uninit_isoc(struct tm6000_core *dev) -{ - struct urb *urb; - int i; - - dev->isoc_ctl.buf = NULL; - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - urb = dev->isoc_ctl.urb[i]; - if (urb) { - usb_kill_urb(urb); - usb_unlink_urb(urb); - if (dev->isoc_ctl.transfer_buffer[i]) { - usb_free_coherent(dev->udev, - urb->transfer_buffer_length, - dev->isoc_ctl.transfer_buffer[i], - urb->transfer_dma); - } - usb_free_urb(urb); - dev->isoc_ctl.urb[i] = NULL; - } - dev->isoc_ctl.transfer_buffer[i] = NULL; - } - - kfree(dev->isoc_ctl.urb); - kfree(dev->isoc_ctl.transfer_buffer); - - dev->isoc_ctl.urb = NULL; - dev->isoc_ctl.transfer_buffer = NULL; - dev->isoc_ctl.num_bufs = 0; -} - -/* - * Allocate URBs and start IRQ - */ -static int tm6000_prepare_isoc(struct tm6000_core *dev) -{ - struct tm6000_dmaqueue *dma_q = &dev->vidq; - int i, j, sb_size, pipe, size, max_packets, num_bufs = 8; - struct urb *urb; - - /* De-allocates all pending stuff */ - tm6000_uninit_isoc(dev); - /* Stop interrupt USB pipe */ - tm6000_ir_int_stop(dev); - - usb_set_interface(dev->udev, - dev->isoc_in.bInterfaceNumber, - dev->isoc_in.bAlternateSetting); - - /* Start interrupt USB pipe */ - tm6000_ir_int_start(dev); - - pipe = usb_rcvisocpipe(dev->udev, - dev->isoc_in.endp->desc.bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK); - - size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe)); - - if (size > dev->isoc_in.maxsize) - size = dev->isoc_in.maxsize; - - dev->isoc_ctl.max_pkt_size = size; - - max_packets = TM6000_MAX_ISO_PACKETS; - sb_size = max_packets * size; - - dev->isoc_ctl.num_bufs = num_bufs; - - dev->isoc_ctl.urb = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL); - if (!dev->isoc_ctl.urb) { - tm6000_err("cannot alloc memory for usb buffers\n"); - return -ENOMEM; - } - - dev->isoc_ctl.transfer_buffer = kmalloc(sizeof(void *)*num_bufs, - GFP_KERNEL); - if (!dev->isoc_ctl.transfer_buffer) { - tm6000_err("cannot allocate memory for usbtransfer\n"); - kfree(dev->isoc_ctl.urb); - return -ENOMEM; - } - - dprintk(dev, V4L2_DEBUG_QUEUE, "Allocating %d x %d packets" - " (%d bytes) of %d bytes each to handle %u size\n", - max_packets, num_bufs, sb_size, - dev->isoc_in.maxsize, size); - - /* allocate urbs and transfer buffers */ - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - urb = usb_alloc_urb(max_packets, GFP_KERNEL); - if (!urb) { - tm6000_err("cannot alloc isoc_ctl.urb %i\n", i); - tm6000_uninit_isoc(dev); - usb_free_urb(urb); - return -ENOMEM; - } - dev->isoc_ctl.urb[i] = urb; - - dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev, - sb_size, GFP_KERNEL, &urb->transfer_dma); - if (!dev->isoc_ctl.transfer_buffer[i]) { - tm6000_err("unable to allocate %i bytes for transfer" - " buffer %i%s\n", - sb_size, i, - in_interrupt() ? " while in int" : ""); - tm6000_uninit_isoc(dev); - return -ENOMEM; - } - memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size); - - usb_fill_bulk_urb(urb, dev->udev, pipe, - dev->isoc_ctl.transfer_buffer[i], sb_size, - tm6000_irq_callback, dma_q); - urb->interval = dev->isoc_in.endp->desc.bInterval; - urb->number_of_packets = max_packets; - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; - - for (j = 0; j < max_packets; j++) { - urb->iso_frame_desc[j].offset = size * j; - urb->iso_frame_desc[j].length = size; - } - } - - return 0; -} - -static int tm6000_start_thread(struct tm6000_core *dev) -{ - struct tm6000_dmaqueue *dma_q = &dev->vidq; - int i; - - dma_q->frame = 0; - dma_q->ini_jiffies = jiffies; - - init_waitqueue_head(&dma_q->wq); - - /* submit urbs and enables IRQ */ - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - int rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC); - if (rc) { - tm6000_err("submit of urb %i failed (error=%i)\n", i, - rc); - tm6000_uninit_isoc(dev); - return rc; - } - } - - return 0; -} - -/* ------------------------------------------------------------------ - * Videobuf operations - * ------------------------------------------------------------------ - */ - -static int -buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) -{ - struct tm6000_fh *fh = vq->priv_data; - - *size = fh->fmt->depth * fh->width * fh->height >> 3; - if (0 == *count) - *count = TM6000_DEF_BUF; - - if (*count < TM6000_MIN_BUF) - *count = TM6000_MIN_BUF; - - while (*size * *count > vid_limit * 1024 * 1024) - (*count)--; - - return 0; -} - -static void free_buffer(struct videobuf_queue *vq, struct tm6000_buffer *buf) -{ - struct tm6000_fh *fh = vq->priv_data; - struct tm6000_core *dev = fh->dev; - unsigned long flags; - - 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.buf == buf) - dev->isoc_ctl.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 tm6000_fh *fh = vq->priv_data; - struct tm6000_buffer *buf = container_of(vb, struct tm6000_buffer, vb); - struct tm6000_core *dev = fh->dev; - int rc = 0; - - BUG_ON(NULL == fh->fmt); - - - /* FIXME: It assumes depth=2 */ - /* The only currently supported format is 16 bits/pixel */ - buf->vb.size = fh->fmt->depth*fh->width*fh->height >> 3; - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - if (buf->fmt != fh->fmt || - buf->vb.width != fh->width || - buf->vb.height != fh->height || - buf->vb.field != field) { - buf->fmt = fh->fmt; - buf->vb.width = fh->width; - buf->vb.height = fh->height; - buf->vb.field = field; - buf->vb.state = VIDEOBUF_NEEDS_INIT; - } - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - rc = videobuf_iolock(vq, &buf->vb, NULL); - if (rc != 0) - goto fail; - } - - if (!dev->isoc_ctl.num_bufs) { - rc = tm6000_prepare_isoc(dev); - if (rc < 0) - goto fail; - - rc = tm6000_start_thread(dev); - 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 tm6000_buffer *buf = container_of(vb, struct tm6000_buffer, vb); - struct tm6000_fh *fh = vq->priv_data; - struct tm6000_core *dev = fh->dev; - struct tm6000_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 tm6000_buffer *buf = container_of(vb, struct tm6000_buffer, vb); - - free_buffer(vq, buf); -} - -static struct videobuf_queue_ops tm6000_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, -}; - -/* ------------------------------------------------------------------ - * IOCTL handling - * ------------------------------------------------------------------ - */ - -static bool is_res_read(struct tm6000_core *dev, struct tm6000_fh *fh) -{ - /* Is the current fh handling it? if so, that's OK */ - if (dev->resources == fh && dev->is_res_read) - return true; - - return false; -} - -static bool is_res_streaming(struct tm6000_core *dev, struct tm6000_fh *fh) -{ - /* Is the current fh handling it? if so, that's OK */ - if (dev->resources == fh) - return true; - - return false; -} - -static bool res_get(struct tm6000_core *dev, struct tm6000_fh *fh, - bool is_res_read) -{ - /* Is the current fh handling it? if so, that's OK */ - if (dev->resources == fh && dev->is_res_read == is_res_read) - return true; - - /* is it free? */ - if (dev->resources) - return false; - - /* grab it */ - dev->resources = fh; - dev->is_res_read = is_res_read; - dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: get\n"); - return true; -} - -static void res_free(struct tm6000_core *dev, struct tm6000_fh *fh) -{ - /* Is the current fh handling it? if so, that's OK */ - if (dev->resources != fh) - return; - - dev->resources = NULL; - dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: put\n"); -} - -/* ------------------------------------------------------------------ - * IOCTL vidioc handling - * ------------------------------------------------------------------ - */ -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev; - - strlcpy(cap->driver, "tm6000", sizeof(cap->driver)); - strlcpy(cap->card, "Trident TVMaster TM5600/6000/6010", sizeof(cap->card)); - cap->version = TM6000_VERSION; - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_STREAMING | - V4L2_CAP_AUDIO | - V4L2_CAP_READWRITE; - - 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_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct tm6000_fh *fh = priv; - - f->fmt.pix.width = fh->width; - f->fmt.pix.height = fh->height; - f->fmt.pix.field = fh->vb_vidq.field; - f->fmt.pix.pixelformat = fh->fmt->fourcc; - f->fmt.pix.bytesperline = - (f->fmt.pix.width * fh->fmt->depth) >> 3; - f->fmt.pix.sizeimage = - f->fmt.pix.height * f->fmt.pix.bytesperline; - - return 0; -} - -static struct tm6000_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 tm6000_core *dev = ((struct tm6000_fh *)priv)->dev; - struct tm6000_fmt *fmt; - enum v4l2_field field; - - fmt = format_by_fourcc(f->fmt.pix.pixelformat); - if (NULL == fmt) { - dprintk(dev, V4L2_DEBUG_IOCTL_ARG, "Fourcc format (0x%08x)" - " invalid.\n", f->fmt.pix.pixelformat); - return -EINVAL; - } - - field = f->fmt.pix.field; - - if (field == V4L2_FIELD_ANY) - field = V4L2_FIELD_SEQ_TB; - else if (V4L2_FIELD_INTERLACED != field) { - dprintk(dev, V4L2_DEBUG_IOCTL_ARG, "Field type invalid.\n"); - return -EINVAL; - } - - tm6000_get_std_res(dev); - - f->fmt.pix.width = dev->width; - f->fmt.pix.height = dev->height; - - f->fmt.pix.width &= ~0x01; - - f->fmt.pix.field = field; - - f->fmt.pix.bytesperline = - (f->fmt.pix.width * fmt->depth) >> 3; - f->fmt.pix.sizeimage = - f->fmt.pix.height * f->fmt.pix.bytesperline; - - return 0; -} - -/*FIXME: This seems to be generic enough to be at videodev2 */ -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - int ret = vidioc_try_fmt_vid_cap(file, fh, f); - if (ret < 0) - return ret; - - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; - fh->vb_vidq.field = f->fmt.pix.field; - fh->type = f->type; - - dev->fourcc = f->fmt.pix.pixelformat; - - tm6000_set_fourcc_format(dev); - - return 0; -} - -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *p) -{ - struct tm6000_fh *fh = priv; - - return videobuf_reqbufs(&fh->vb_vidq, p); -} - -static int vidioc_querybuf(struct file *file, void *priv, - struct v4l2_buffer *p) -{ - struct tm6000_fh *fh = priv; - - return videobuf_querybuf(&fh->vb_vidq, p); -} - -static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct tm6000_fh *fh = priv; - - return videobuf_qbuf(&fh->vb_vidq, p); -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct tm6000_fh *fh = priv; - - return videobuf_dqbuf(&fh->vb_vidq, p, - file->f_flags & O_NONBLOCK); -} - -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - if (!res_get(dev, fh, false)) - return -EBUSY; - return videobuf_streamon(&fh->vb_vidq); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (i != fh->type) - return -EINVAL; - - videobuf_streamoff(&fh->vb_vidq); - res_free(dev, fh); - - return 0; -} - -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) -{ - int rc = 0; - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - dev->norm = *norm; - rc = tm6000_init_analog_mode(dev); - - fh->width = dev->width; - fh->height = dev->height; - - if (rc < 0) - return rc; - - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm); - - return 0; -} - -static const char *iname[] = { - [TM6000_INPUT_TV] = "Television", - [TM6000_INPUT_COMPOSITE1] = "Composite 1", - [TM6000_INPUT_COMPOSITE2] = "Composite 2", - [TM6000_INPUT_SVIDEO] = "S-Video", -}; - -static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *i) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - unsigned int n; - - n = i->index; - if (n >= 3) - return -EINVAL; - - if (!dev->vinput[n].type) - return -EINVAL; - - i->index = n; - - if (dev->vinput[n].type == TM6000_INPUT_TV) - i->type = V4L2_INPUT_TYPE_TUNER; - else - i->type = V4L2_INPUT_TYPE_CAMERA; - - strcpy(i->name, iname[dev->vinput[n].type]); - - i->std = TM6000_STD; - - return 0; -} - -static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - *i = dev->input; - - return 0; -} - -static int vidioc_s_input(struct file *file, void *priv, unsigned int i) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - int rc = 0; - - if (i >= 3) - return -EINVAL; - if (!dev->vinput[i].type) - return -EINVAL; - - dev->input = i; - - rc = vidioc_s_std(file, priv, &dev->vfd->current_norm); - - return rc; -} - -/* --- controls ---------------------------------------------- */ -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++) - if (qc->id && qc->id == tm6000_qctrl[i].id) { - memcpy(qc, &(tm6000_qctrl[i]), - sizeof(*qc)); - return 0; - } - - return -EINVAL; -} - -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - int val; - - /* FIXME: Probably, those won't work! Maybe we need shadow regs */ - switch (ctrl->id) { - case V4L2_CID_CONTRAST: - val = tm6000_get_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0); - break; - case V4L2_CID_BRIGHTNESS: - val = tm6000_get_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0); - return 0; - case V4L2_CID_SATURATION: - val = tm6000_get_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0); - return 0; - case V4L2_CID_HUE: - val = tm6000_get_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, 0); - return 0; - case V4L2_CID_AUDIO_MUTE: - val = dev->ctl_mute; - return 0; - case V4L2_CID_AUDIO_VOLUME: - val = dev->ctl_volume; - return 0; - default: - return -EINVAL; - } - - if (val < 0) - return val; - - ctrl->value = val; - - return 0; -} -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - u8 val = ctrl->value; - - switch (ctrl->id) { - case V4L2_CID_CONTRAST: - tm6000_set_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, val); - return 0; - case V4L2_CID_BRIGHTNESS: - tm6000_set_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, val); - return 0; - case V4L2_CID_SATURATION: - tm6000_set_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, val); - return 0; - case V4L2_CID_HUE: - tm6000_set_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, val); - return 0; - case V4L2_CID_AUDIO_MUTE: - dev->ctl_mute = val; - tm6000_tvaudio_set_mute(dev, val); - return 0; - case V4L2_CID_AUDIO_VOLUME: - dev->ctl_volume = val; - tm6000_set_volume(dev, val); - return 0; - } - return -EINVAL; -} - -static int vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - if (unlikely(UNSET == dev->tuner_type)) - return -EINVAL; - if (0 != t->index) - return -EINVAL; - - strcpy(t->name, "Television"); - t->type = V4L2_TUNER_ANALOG_TV; - t->capability = V4L2_TUNER_CAP_NORM; - t->rangehigh = 0xffffffffUL; - t->rxsubchans = V4L2_TUNER_SUB_STEREO; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); - - t->audmode = dev->amode; - - return 0; -} - -static int vidioc_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - if (UNSET == dev->tuner_type) - return -EINVAL; - if (0 != t->index) - return -EINVAL; - - dev->amode = t->audmode; - dprintk(dev, 3, "audio mode: %x\n", t->audmode); - - 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 tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - if (unlikely(UNSET == dev->tuner_type)) - return -EINVAL; - - f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - f->frequency = dev->freq; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, f); - - return 0; -} - -static int vidioc_s_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - if (unlikely(UNSET == dev->tuner_type)) - return -EINVAL; - if (unlikely(f->tuner != 0)) - return -EINVAL; - if (0 == fh->radio && V4L2_TUNER_ANALOG_TV != f->type) - return -EINVAL; - if (1 == fh->radio && V4L2_TUNER_RADIO != f->type) - return -EINVAL; - - dev->freq = f->frequency; - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f); - - return 0; -} - -static int radio_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct tm6000_fh *fh = file->private_data; - struct tm6000_core *dev = fh->dev; - - strcpy(cap->driver, "tm6000"); - strlcpy(cap->card, dev->name, sizeof(dev->name)); - sprintf(cap->bus_info, "USB%04x:%04x", - le16_to_cpu(dev->udev->descriptor.idVendor), - le16_to_cpu(dev->udev->descriptor.idProduct)); - cap->version = dev->dev_type; - cap->capabilities = V4L2_CAP_TUNER | - V4L2_CAP_AUDIO | - V4L2_CAP_RADIO | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; - - return 0; -} - -static int radio_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct tm6000_fh *fh = file->private_data; - struct tm6000_core *dev = fh->dev; - - if (0 != t->index) - return -EINVAL; - - memset(t, 0, sizeof(*t)); - strcpy(t->name, "Radio"); - t->type = V4L2_TUNER_RADIO; - t->rxsubchans = V4L2_TUNER_SUB_STEREO; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); - - return 0; -} - -static int radio_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct tm6000_fh *fh = file->private_data; - struct tm6000_core *dev = fh->dev; - - if (0 != t->index) - return -EINVAL; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); - - return 0; -} - -static int radio_enum_input(struct file *file, void *priv, - struct v4l2_input *i) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - if (i->index != 0) - return -EINVAL; - - if (!dev->rinput.type) - return -EINVAL; - - strcpy(i->name, "Radio"); - i->type = V4L2_INPUT_TYPE_TUNER; - - return 0; -} - -static int radio_g_input(struct file *filp, void *priv, unsigned int *i) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - if (dev->input != 5) - return -EINVAL; - - *i = dev->input - 5; - - return 0; -} - -static int radio_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - memset(a, 0, sizeof(*a)); - strcpy(a->name, "Radio"); - return 0; -} - -static int radio_s_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - return 0; -} - -static int radio_s_input(struct file *filp, void *priv, unsigned int i) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - if (i) - return -EINVAL; - - if (!dev->rinput.type) - return -EINVAL; - - dev->input = i + 5; - - return 0; -} - -static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm) -{ - return 0; -} - -static int radio_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *c) -{ - const struct v4l2_queryctrl *ctrl; - - if (c->id < V4L2_CID_BASE || - c->id >= V4L2_CID_LASTP1) - return -EINVAL; - if (c->id == V4L2_CID_AUDIO_MUTE) { - ctrl = ctrl_by_id(c->id); - *c = *ctrl; - } else - *c = no_ctrl; - - return 0; -} - -/* ------------------------------------------------------------------ - File operations for the device - ------------------------------------------------------------------*/ - -static int tm6000_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct tm6000_core *dev = video_drvdata(file); - struct tm6000_fh *fh; - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - int i, rc; - int radio = 0; - - dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: open called (dev=%s)\n", - video_device_node_name(vdev)); - - switch (vdev->vfl_type) { - case VFL_TYPE_GRABBER: - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - break; - case VFL_TYPE_VBI: - type = V4L2_BUF_TYPE_VBI_CAPTURE; - break; - case VFL_TYPE_RADIO: - radio = 1; - break; - } - - /* If more than one user, mutex should be added */ - dev->users++; - - dprintk(dev, V4L2_DEBUG_OPEN, "open dev=%s type=%s users=%d\n", - video_device_node_name(vdev), v4l2_type_names[type], - dev->users); - - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - dev->users--; - return -ENOMEM; - } - - file->private_data = fh; - fh->dev = dev; - fh->radio = radio; - dev->radio = radio; - fh->type = type; - dev->fourcc = format[0].fourcc; - - fh->fmt = format_by_fourcc(dev->fourcc); - - tm6000_get_std_res(dev); - - fh->width = dev->width; - fh->height = dev->height; - - dprintk(dev, V4L2_DEBUG_OPEN, "Open: fh=0x%08lx, dev=0x%08lx, " - "dev->vidq=0x%08lx\n", - (unsigned long)fh, (unsigned long)dev, - (unsigned long)&dev->vidq); - dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty " - "queued=%d\n", list_empty(&dev->vidq.queued)); - dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty " - "active=%d\n", list_empty(&dev->vidq.active)); - - /* initialize hardware on analog mode */ - rc = tm6000_init_analog_mode(dev); - if (rc < 0) - return rc; - - if (dev->mode != TM6000_MODE_ANALOG) { - /* Put all controls at a sane state */ - for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++) - qctl_regs[i] = tm6000_qctrl[i].default_value; - - dev->mode = TM6000_MODE_ANALOG; - } - - if (!fh->radio) { - videobuf_queue_vmalloc_init(&fh->vb_vidq, &tm6000_video_qops, - NULL, &dev->slock, - fh->type, - V4L2_FIELD_INTERLACED, - sizeof(struct tm6000_buffer), fh, &dev->lock); - } else { - dprintk(dev, V4L2_DEBUG_OPEN, "video_open: setting radio device\n"); - dev->input = 5; - tm6000_set_audio_rinput(dev); - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio); - tm6000_prepare_isoc(dev); - tm6000_start_thread(dev); - } - - return 0; -} - -static ssize_t -tm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos) -{ - struct tm6000_fh *fh = file->private_data; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (!res_get(fh->dev, fh, true)) - return -EBUSY; - - return videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0, - file->f_flags & O_NONBLOCK); - } - return 0; -} - -static unsigned int -tm6000_poll(struct file *file, struct poll_table_struct *wait) -{ - struct tm6000_fh *fh = file->private_data; - struct tm6000_buffer *buf; - - if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) - return POLLERR; - - if (!!is_res_streaming(fh->dev, fh)) - return POLLERR; - - if (!is_res_read(fh->dev, fh)) { - /* streaming capture */ - if (list_empty(&fh->vb_vidq.stream)) - return POLLERR; - buf = list_entry(fh->vb_vidq.stream.next, struct tm6000_buffer, vb.stream); - } else { - /* read() capture */ - return videobuf_poll_stream(file, &fh->vb_vidq, wait); - } - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || - buf->vb.state == VIDEOBUF_ERROR) - return POLLIN | POLLRDNORM; - return 0; -} - -static int tm6000_release(struct file *file) -{ - struct tm6000_fh *fh = file->private_data; - struct tm6000_core *dev = fh->dev; - struct video_device *vdev = video_devdata(file); - - dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: close called (dev=%s, users=%d)\n", - video_device_node_name(vdev), dev->users); - - dev->users--; - - res_free(dev, fh); - - if (!dev->users) { - int err; - - tm6000_uninit_isoc(dev); - - if (!fh->radio) - videobuf_mmap_free(&fh->vb_vidq); - - err = tm6000_reset(dev); - if (err < 0) - dev_err(&vdev->dev, "reset failed: %d\n", err); - } - - kfree(fh); - - return 0; -} - -static int tm6000_mmap(struct file *file, struct vm_area_struct * vma) -{ - struct tm6000_fh *fh = file->private_data; - - return videobuf_mmap_mapper(&fh->vb_vidq, vma); -} - -static struct v4l2_file_operations tm6000_fops = { - .owner = THIS_MODULE, - .open = tm6000_open, - .release = tm6000_release, - .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ - .read = tm6000_read, - .poll = tm6000_poll, - .mmap = tm6000_mmap, -}; - -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_s_std = vidioc_s_std, - .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_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, -}; - -static struct video_device tm6000_template = { - .name = "tm6000", - .fops = &tm6000_fops, - .ioctl_ops = &video_ioctl_ops, - .release = video_device_release, - .tvnorms = TM6000_STD, - .current_norm = V4L2_STD_NTSC_M, -}; - -static const struct v4l2_file_operations radio_fops = { - .owner = THIS_MODULE, - .open = tm6000_open, - .release = tm6000_release, - .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_s_std = radio_s_std, - .vidioc_queryctrl = radio_queryctrl, - .vidioc_g_input = radio_g_input, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, -}; - -static struct video_device tm6000_radio_template = { - .name = "tm6000", - .fops = &radio_fops, - .ioctl_ops = &radio_ioctl_ops, -}; - -/* ----------------------------------------------------------------- - * Initialization and module stuff - * ------------------------------------------------------------------ - */ - -static struct video_device *vdev_init(struct tm6000_core *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 = tm6000_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 tm6000_v4l2_register(struct tm6000_core *dev) -{ - int ret = -1; - - dev->vfd = vdev_init(dev, &tm6000_template, "video"); - - if (!dev->vfd) { - printk(KERN_INFO "%s: can't register video device\n", - dev->name); - return -ENOMEM; - } - - /* init video dma queues */ - INIT_LIST_HEAD(&dev->vidq.active); - INIT_LIST_HEAD(&dev->vidq.queued); - - ret = video_register_device(dev->vfd, VFL_TYPE_GRABBER, video_nr); - - if (ret < 0) { - printk(KERN_INFO "%s: can't register video device\n", - dev->name); - return ret; - } - - printk(KERN_INFO "%s: registered device %s\n", - dev->name, video_device_node_name(dev->vfd)); - - if (dev->caps.has_radio) { - dev->radio_dev = vdev_init(dev, &tm6000_radio_template, - "radio"); - if (!dev->radio_dev) { - printk(KERN_INFO "%s: can't register radio device\n", - dev->name); - return ret; /* FIXME release resource */ - } - - ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, - radio_nr); - if (ret < 0) { - printk(KERN_INFO "%s: can't register radio device\n", - dev->name); - return ret; /* FIXME release resource */ - } - - printk(KERN_INFO "%s: registered device %s\n", - dev->name, video_device_node_name(dev->radio_dev)); - } - - printk(KERN_INFO "Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load status: %d)\n", ret); - return ret; -} - -int tm6000_v4l2_unregister(struct tm6000_core *dev) -{ - video_unregister_device(dev->vfd); - - 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; - } - - return 0; -} - -int tm6000_v4l2_exit(void) -{ - return 0; -} - -module_param(video_nr, int, 0); -MODULE_PARM_DESC(video_nr, "Allow changing video device number"); - -module_param_named(debug, tm6000_debug, int, 0444); -MODULE_PARM_DESC(debug, "activates debug info"); - -module_param(vid_limit, int, 0644); -MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); - diff --git a/drivers/staging/tm6000/tm6000.h b/drivers/staging/tm6000/tm6000.h deleted file mode 100644 index 2777e514eff2..000000000000 --- a/drivers/staging/tm6000/tm6000.h +++ /dev/null @@ -1,398 +0,0 @@ -/* - * tm6000.h - driver for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> - * - * Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com> - * - DVB-T support - * - * 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 version 2 - * - * 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/videodev2.h> -#include <media/v4l2-common.h> -#include <media/videobuf-vmalloc.h> -#include "tm6000-usb-isoc.h" -#include <linux/i2c.h> -#include <linux/mutex.h> -#include <media/v4l2-device.h> - -#include <linux/dvb/frontend.h> -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dmxdev.h" - -#define TM6000_VERSION KERNEL_VERSION(0, 0, 2) - -/* Inputs */ -enum tm6000_itype { - TM6000_INPUT_TV = 1, - TM6000_INPUT_COMPOSITE1, - TM6000_INPUT_COMPOSITE2, - TM6000_INPUT_SVIDEO, - TM6000_INPUT_DVB, - TM6000_INPUT_RADIO, -}; - -enum tm6000_mux { - TM6000_VMUX_VIDEO_A = 1, - TM6000_VMUX_VIDEO_B, - TM6000_VMUX_VIDEO_AB, - TM6000_AMUX_ADC1, - TM6000_AMUX_ADC2, - TM6000_AMUX_SIF1, - TM6000_AMUX_SIF2, - TM6000_AMUX_I2S, -}; - -enum tm6000_devtype { - TM6000 = 0, - TM5600, - TM6010, -}; - -struct tm6000_input { - enum tm6000_itype type; - enum tm6000_mux vmux; - enum tm6000_mux amux; - unsigned int v_gpio; - unsigned int a_gpio; -}; - -/* ------------------------------------------------------------------ - * Basic structures - * ------------------------------------------------------------------ - */ - -struct tm6000_fmt { - char *name; - u32 fourcc; /* v4l2 format id */ - int depth; -}; - -/* buffer for one video frame */ -struct tm6000_buffer { - /* common v4l buffer stuff -- must be first */ - struct videobuf_buffer vb; - - struct tm6000_fmt *fmt; -}; - -struct tm6000_dmaqueue { - struct list_head active; - struct list_head queued; - - /* thread for generating video stream*/ - struct task_struct *kthread; - wait_queue_head_t wq; - /* Counters to control fps rate */ - int frame; - int ini_jiffies; -}; - -/* device states */ -enum tm6000_core_state { - DEV_INITIALIZED = 0x01, - DEV_DISCONNECTED = 0x02, - DEV_MISCONFIGURED = 0x04, -}; - -/* io methods */ -enum tm6000_io_method { - IO_NONE, - IO_READ, - IO_MMAP, -}; - -enum tm6000_mode { - TM6000_MODE_UNKNOWN = 0, - TM6000_MODE_ANALOG, - TM6000_MODE_DIGITAL, -}; - -struct tm6000_gpio { - int tuner_reset; - int tuner_on; - int demod_reset; - int demod_on; - int power_led; - int dvb_led; - int ir; -}; - -struct tm6000_capabilities { - unsigned int has_tuner:1; - unsigned int has_tda9874:1; - unsigned int has_dvb:1; - unsigned int has_zl10353:1; - unsigned int has_eeprom:1; - unsigned int has_remote:1; - unsigned int has_radio:1; -}; - -struct tm6000_dvb { - struct dvb_adapter adapter; - struct dvb_demux demux; - struct dvb_frontend *frontend; - struct dmxdev dmxdev; - unsigned int streams; - struct urb *bulk_urb; - struct mutex mutex; -}; - -struct snd_tm6000_card { - struct snd_card *card; - spinlock_t reg_lock; - struct tm6000_core *core; - struct snd_pcm_substream *substream; - - /* temporary data for buffer fill processing */ - unsigned buf_pos; - unsigned period_pos; -}; - -struct tm6000_endpoint { - struct usb_host_endpoint *endp; - __u8 bInterfaceNumber; - __u8 bAlternateSetting; - unsigned maxsize; -}; - -#define TM6000_QUIRK_NO_USB_DELAY (1 << 0) - -struct tm6000_core { - /* 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 tm6000_devtype dev_type; /* type of device */ - unsigned char eedata[256]; /* Eeprom data */ - unsigned eedata_size; /* Size of the eeprom info */ - - v4l2_std_id norm; /* Current norm */ - int width, height; /* Selected resolution */ - - enum tm6000_core_state state; - - /* Device Capabilities*/ - struct tm6000_capabilities caps; - - /* Tuner configuration */ - int tuner_type; /* type of the tuner */ - int tuner_addr; /* tuner address */ - - struct tm6000_gpio gpio; - - char *ir_codes; - - __u8 radio; - - /* Demodulator configuration */ - int demod_addr; /* demodulator address */ - - int audio_bitrate; - /* i2c i/o */ - struct i2c_adapter i2c_adap; - struct i2c_client i2c_client; - - - /* extension */ - struct list_head devlist; - - /* video for linux */ - int users; - - /* various device info */ - struct tm6000_fh *resources; /* Points to fh that is streaming */ - bool is_res_read; - - struct video_device *vfd; - struct video_device *radio_dev; - struct tm6000_dmaqueue vidq; - struct v4l2_device v4l2_dev; - - int input; - struct tm6000_input vinput[3]; /* video input */ - struct tm6000_input rinput; /* radio input */ - - int freq; - unsigned int fourcc; - - enum tm6000_mode mode; - - int ctl_mute; /* audio */ - int ctl_volume; - int amode; - - /* DVB-T support */ - struct tm6000_dvb *dvb; - - /* audio support */ - struct snd_tm6000_card *adev; - struct work_struct wq_trigger; /* Trigger to start/stop audio for alsa module */ - atomic_t stream_started; /* stream should be running if true */ - - struct tm6000_IR *ir; - - /* locks */ - struct mutex lock; - struct mutex usb_lock; - - /* usb transfer */ - struct usb_device *udev; /* the usb device */ - - struct tm6000_endpoint bulk_in, bulk_out, isoc_in, isoc_out; - struct tm6000_endpoint int_in, int_out; - - /* scaler!=0 if scaler is active*/ - int scaler; - - /* Isoc control struct */ - struct usb_isoc_ctl isoc_ctl; - - spinlock_t slock; - - unsigned long quirks; -}; - -enum tm6000_ops_type { - TM6000_AUDIO = 0x10, - TM6000_DVB = 0x20, -}; - -struct tm6000_ops { - struct list_head next; - char *name; - enum tm6000_ops_type type; - int (*init)(struct tm6000_core *); - int (*fini)(struct tm6000_core *); - int (*fillbuf)(struct tm6000_core *, char *buf, int size); -}; - -struct tm6000_fh { - struct tm6000_core *dev; - unsigned int radio; - - /* video capture */ - struct tm6000_fmt *fmt; - unsigned int width, height; - struct videobuf_queue vb_vidq; - - enum v4l2_buf_type type; -}; - -#define TM6000_STD (V4L2_STD_PAL|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc| \ - V4L2_STD_PAL_M|V4L2_STD_PAL_60|V4L2_STD_NTSC_M| \ - V4L2_STD_NTSC_M_JP|V4L2_STD_SECAM) - -/* In tm6000-cards.c */ - -int tm6000_tuner_callback(void *ptr, int component, int command, int arg); -int tm6000_xc5000_callback(void *ptr, int component, int command, int arg); -int tm6000_cards_setup(struct tm6000_core *dev); -void tm6000_flash_led(struct tm6000_core *dev, u8 state); - -/* In tm6000-core.c */ - -int tm6000_read_write_usb(struct tm6000_core *dev, u8 reqtype, u8 req, - u16 value, u16 index, u8 *buf, u16 len); -int tm6000_get_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index); -int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index); -int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index); -int tm6000_set_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index); -int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value, - u16 index, u16 mask); -int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep); -int tm6000_init(struct tm6000_core *dev); -int tm6000_reset(struct tm6000_core *dev); - -int tm6000_init_analog_mode(struct tm6000_core *dev); -int tm6000_init_digital_mode(struct tm6000_core *dev); -int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate); -int tm6000_set_audio_rinput(struct tm6000_core *dev); -int tm6000_tvaudio_set_mute(struct tm6000_core *dev, u8 mute); -void tm6000_set_volume(struct tm6000_core *dev, int vol); - -int tm6000_v4l2_register(struct tm6000_core *dev); -int tm6000_v4l2_unregister(struct tm6000_core *dev); -int tm6000_v4l2_exit(void); -void tm6000_set_fourcc_format(struct tm6000_core *dev); - -void tm6000_remove_from_devlist(struct tm6000_core *dev); -void tm6000_add_into_devlist(struct tm6000_core *dev); -int tm6000_register_extension(struct tm6000_ops *ops); -void tm6000_unregister_extension(struct tm6000_ops *ops); -void tm6000_init_extension(struct tm6000_core *dev); -void tm6000_close_extension(struct tm6000_core *dev); -int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type, - char *buf, int size); - - -/* In tm6000-stds.c */ -void tm6000_get_std_res(struct tm6000_core *dev); -int tm6000_set_standard(struct tm6000_core *dev); - -/* In tm6000-i2c.c */ -int tm6000_i2c_register(struct tm6000_core *dev); -int tm6000_i2c_unregister(struct tm6000_core *dev); - -/* In tm6000-queue.c */ - -int tm6000_v4l2_mmap(struct file *filp, struct vm_area_struct *vma); - -int tm6000_vidioc_streamon(struct file *file, void *priv, - enum v4l2_buf_type i); -int tm6000_vidioc_streamoff(struct file *file, void *priv, - enum v4l2_buf_type i); -int tm6000_vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *rb); -int tm6000_vidioc_querybuf(struct file *file, void *priv, - struct v4l2_buffer *b); -int tm6000_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b); -int tm6000_vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b); -ssize_t tm6000_v4l2_read(struct file *filp, char __user * buf, size_t count, - loff_t *f_pos); -unsigned int tm6000_v4l2_poll(struct file *file, - struct poll_table_struct *wait); -int tm6000_queue_init(struct tm6000_core *dev); - -/* In tm6000-alsa.c */ -/*int tm6000_audio_init(struct tm6000_core *dev, int idx);*/ - -/* In tm6000-input.c */ -int tm6000_ir_init(struct tm6000_core *dev); -int tm6000_ir_fini(struct tm6000_core *dev); -void tm6000_ir_wait(struct tm6000_core *dev, u8 state); -int tm6000_ir_int_start(struct tm6000_core *dev); -void tm6000_ir_int_stop(struct tm6000_core *dev); - -/* Debug stuff */ - -extern int tm6000_debug; - -#define dprintk(dev, level, fmt, arg...) do {\ - if (tm6000_debug & level) \ - printk(KERN_INFO "(%lu) %s %s :"fmt, jiffies, \ - dev->name, __func__ , ##arg); } while (0) - -#define V4L2_DEBUG_REG 0x0004 -#define V4L2_DEBUG_I2C 0x0008 -#define V4L2_DEBUG_QUEUE 0x0010 -#define V4L2_DEBUG_ISOC 0x0020 -#define V4L2_DEBUG_RES_LOCK 0x0040 /* Resource locking */ -#define V4L2_DEBUG_OPEN 0x0080 /* video open/close debug */ - -#define tm6000_err(fmt, arg...) do {\ - printk(KERN_ERR "tm6000 %s :"fmt, \ - __func__ , ##arg); } while (0) |