media: tm6000: remove deprecated driver

The tm6000 driver does not use the vb2 framework for streaming
video, instead it uses the old vb1 framework and nobody stepped in to
convert this driver to vb2.

The hardware is very old, so the decision was made to remove it
altogether since we want to get rid of the old vb1 framework.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
This commit is contained in:
Hans Verkuil 2023-01-10 13:45:33 +01:00 committed by Mauro Carvalho Chehab
parent d2a8e92f0b
commit 7120d6bfd6
19 changed files with 0 additions and 7531 deletions

View File

@ -1,83 +0,0 @@
.. SPDX-License-Identifier: GPL-2.0
TM6000 cards list
=================
.. tabularcolumns:: |p{1.4cm}|p{11.1cm}|p{4.2cm}|
.. flat-table::
:header-rows: 1
:widths: 2 19 18
:stub-columns: 0
* - Card number
- Card name
- USB IDs
* - 0
- Unknown tm6000 video grabber
-
* - 1
- Generic tm5600 board
- 6000:0001
* - 2
- Generic tm6000 board
-
* - 3
- Generic tm6010 board
- 6000:0002
* - 4
- 10Moons UT 821
-
* - 5
- 10Moons UT 330
-
* - 6
- ADSTECH Dual TV USB
- 06e1:f332
* - 7
- Freecom Hybrid Stick / Moka DVB-T Receiver Dual
- 14aa:0620
* - 8
- ADSTECH Mini Dual TV USB
- 06e1:b339
* - 9
- Hauppauge WinTV HVR-900H / WinTV USB2-Stick
- 2040:6600, 2040:6601, 2040:6610, 2040:6611
* - 10
- Beholder Wander DVB-T/TV/FM USB2.0
- 6000:dec0
* - 11
- Beholder Voyager TV/FM USB2.0
- 6000:dec1
* - 12
- Terratec Cinergy Hybrid XE / Cinergy Hybrid-Stick
- 0ccd:0086, 0ccd:00A5
* - 13
- Twinhan TU501(704D1)
- 13d3:3240, 13d3:3241, 13d3:3243, 13d3:3264
* - 14
- Beholder Wander Lite DVB-T/TV/FM USB2.0
- 6000:dec2
* - 15
- Beholder Voyager Lite TV/FM USB2.0
- 6000:dec3
* - 16
- Terratec Grabster AV 150/250 MX
- 0ccd:0079

View File

@ -92,9 +92,6 @@ pwc USB Philips Cameras
s2250 Sensoray 2250/2251
s2255drv USB Sensoray 2255 video capture device
smsusb Siano SMS1xxx based MDTV receiver
tm6000-alsa TV Master TM5600/6000/6010 audio
tm6000-dvb DVB Support for tm6000 based TV cards
tm6000 TV Master TM5600/6000/6010 driver
ttusb_dec Technotrend/Hauppauge USB DEC devices
usbtv USBTV007 video capture
uvcvideo USB Video Class (UVC)
@ -107,7 +104,6 @@ zd1301 ZyDAS ZD1301
au0828-cardlist
cx231xx-cardlist
em28xx-cardlist
tm6000-cardlist
siano-cardlist
gspca-cardlist

View File

@ -20976,15 +20976,6 @@ W: http://sourceforge.net/projects/tlan/
F: Documentation/networking/device_drivers/ethernet/ti/tlan.rst
F: drivers/net/ethernet/ti/tlan.*
TM6000 VIDEO4LINUX DRIVER
M: Mauro Carvalho Chehab <mchehab@kernel.org>
L: linux-media@vger.kernel.org
S: Odd fixes
W: https://linuxtv.org
T: git git://linuxtv.org/media_tree.git
F: Documentation/admin-guide/media/tm6000*
F: drivers/staging/media/deprecated/tm6000/
TMIO/SDHI MMC DRIVER
M: Wolfram Sang <wsa+renesas@sang-engineering.com>
L: linux-mmc@vger.kernel.org

View File

@ -53,7 +53,6 @@ menuconfig STAGING_MEDIA_DEPRECATED
if STAGING_MEDIA_DEPRECATED
source "drivers/staging/media/deprecated/atmel/Kconfig"
source "drivers/staging/media/deprecated/saa7146/Kconfig"
source "drivers/staging/media/deprecated/tm6000/Kconfig"
endif
endif

View File

@ -9,5 +9,4 @@ obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rkvdec/
obj-$(CONFIG_VIDEO_SUNXI) += sunxi/
obj-$(CONFIG_VIDEO_TEGRA) += tegra-video/
obj-$(CONFIG_VIDEO_IPU3_IMGU) += ipu3/
obj-$(CONFIG_VIDEO_TM6000) += deprecated/tm6000/
obj-y += deprecated/saa7146/

View File

@ -1,37 +0,0 @@
# SPDX-License-Identifier: GPL-2.0-only
config VIDEO_TM6000
tristate "TV Master TM5600/6000/6010 driver (DEPRECATED)"
depends on VIDEO_DEV && I2C && INPUT && RC_CORE && USB
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.
This driver is deprecated and is scheduled for removal by
the beginning of 2023. See the TODO file for more information.
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
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
select DVB_ZL10353
help
This adds support for DVB cards based on the tm5600/tm6000 chip.

View File

@ -1,14 +0,0 @@
# SPDX-License-Identifier: GPL-2.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 += -I $(srctree)/drivers/media/tuners
ccflags-y += -I $(srctree)/drivers/media/dvb-frontends

View File

@ -1,7 +0,0 @@
This is one of the few drivers still not using the vb2
framework, so this driver is now deprecated with the intent of
removing it altogether by the beginning of 2023.
In order to keep this driver it has to be converted to vb2.
If someone is interested in doing this work, then contact the
linux-media mailinglist (https://linuxtv.org/lists.php).

View File

@ -1,440 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
// Support for audio capture for tm5600/6000/6010
// Copyright (c) 2007-2008 Mauro Carvalho Chehab <mchehab@kernel.org>
//
// Based on cx88-alsa.c
#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/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 bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
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");
MODULE_LICENSE("GPL v2");
static unsigned int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable debug messages");
/****************************************************************************
Module specific functions
****************************************************************************/
/*
* 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;
}
/****************************************************************************
ALSA PCM Interface
****************************************************************************/
/*
* Digital hardware definition
*/
#define DEFAULT_FIFO_SIZE 4096
static const struct snd_pcm_hardware snd_tm6000_digital_hw = {
.info = SNDRV_PCM_INFO_BATCH |
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 | SNDRV_PCM_RATE_KNOT,
.rate_min = 48000,
.rate_max = 48000,
.channels_min = 2,
.channels_max = 2,
.period_bytes_min = 64,
.period_bytes_max = 12544,
.periods_min = 2,
.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;
snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
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;
}
/*
* 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_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_START:
atomic_set(&core->stream_started, 1);
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
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 const struct snd_pcm_ops snd_tm6000_pcm_ops = {
.open = snd_tm6000_pcm_open,
.close = snd_tm6000_close,
.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_new(&dev->udev->dev, index[devnr], "tm6000",
THIS_MODULE, 0, &card);
if (rc < 0) {
snd_printk(KERN_ERR "cannot create card instance %d\n", devnr);
return rc;
}
strscpy(card->driver, "tm6000-alsa", sizeof(card->driver));
strscpy(card->shortname, "TM5600/60x0", sizeof(card->shortname));
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);
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;
strscpy(pcm->name, "Trident TM5600/60x0", sizeof(pcm->name));
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_tm6000_pcm_ops);
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
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;
if (!dev)
return 0;
chip = dev->adev;
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);

File diff suppressed because it is too large Load Diff

View File

@ -1,916 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
// tm6000-core.c - driver for TM5600/TM6000/TM6010 USB video capture devices
//
// Copyright (c) 2006-2007 Mauro Carvalho Chehab <mchehab@kernel.org>
//
// Copyright (c) 2007 Michel Ludwig <michel.ludwig@gmail.com>
// - DVB-T support
#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;
int delay = 5000;
if (len) {
data = kzalloc(len, GFP_KERNEL);
if (!data)
return -ENOMEM;
}
mutex_lock(&dev->usb_lock);
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);
if (dev->quirks & TM6000_QUIRK_NO_USB_DELAY)
delay = 0;
if (req == REQ_16_SET_GET_I2C_WR1_RDN && !(req_type & USB_DIR_IN)) {
unsigned int tsleep;
/* Calculate delay time, 14000us for 64 bytes */
tsleep = (len * 200) + 200;
if (tsleep < delay)
tsleep = delay;
usleep_range(tsleep, tsleep + 1000);
}
else if (delay)
usleep_range(delay, delay + 1000);
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, 0, buf, 1);
if (rc < 0)
return rc;
new_index = (buf[0] & ~mask) | (index & mask);
if (new_index == buf[0])
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_RDC_IR_LEADER1, 0xaa },
{ TM6010_REQ07_RDD_IR_LEADER0, 0x30 },
{ TM6010_REQ07_RDE_IR_PULSE_CNT1, 0x20 },
{ TM6010_REQ07_RDF_IR_PULSE_CNT0, 0xd0 },
{ REQ_04_EN_DISABLE_MCU_INT, 0x02, 0x00 },
{ TM6010_REQ07_RD8_IR, 0x0f },
/* set remote wakeup key:any key wakeup */
{ TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe },
{ TM6010_REQ07_RDA_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_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;
u8 areg_07 = 0x10;
switch (dev->rinput.amux) {
case TM6000_AMUX_SIF1:
case TM6000_AMUX_SIF2:
areg_f0 = 0x03;
areg_07 = 0x30;
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 doesn'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);
/* Mux overflow workaround */
tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
areg_07, 0xf0);
} 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 doesn'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 */
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);
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);
list_for_each_entry(ops, &tm6000_extension_devlist, next) {
if (ops->fini)
ops->fini(dev);
}
mutex_unlock(&tm6000_devlist_mutex);
}

View File

@ -1,454 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* tm6000-dvb.c - dvb-t support for TM5600/TM6000/TM6010 USB video capture devices
*
* Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
*/
#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 "xc2028.h"
#include "xc5000.h"
MODULE_DESCRIPTION("DVB driver extension module for tm5600/6000/6010 based TV cards");
MODULE_AUTHOR("Mauro Carvalho Chehab");
MODULE_LICENSE("GPL");
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 synchronously";
break;
case -ECONNRESET:
errmsg = "unlinked asynchronously";
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;
switch (urb->status) {
case 0:
case -ETIMEDOUT:
break;
case -ENOENT:
case -ECONNRESET:
case -ESHUTDOWN:
return;
default:
print_err_status(dev, 0, urb->status);
}
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);
dev->dvb->bulk_urb = NULL;
}
}
}
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)
return -ENOMEM;
pipe = usb_rcvbulkpipe(dev->udev, dev->bulk_in.endp->desc.bEndpointAddress
& USB_ENDPOINT_NUMBER_MASK);
size = usb_maxpacket(dev->udev, 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) {
usb_free_urb(dvb->bulk_urb);
dvb->bulk_urb = NULL;
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__);
kfree(dvb->bulk_urb->transfer_buffer);
usb_free_urb(dvb->bulk_urb);
dvb->bulk_urb = NULL;
return ret;
} else
printk(KERN_ERR "tm6000: pipe reset\n");
/* mutex_lock(&tm6000_driver.open_close_mutex); */
ret = usb_submit_urb(dvb->bulk_urb, GFP_ATOMIC);
/* 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);
dvb->bulk_urb = NULL;
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);
if (ret < 0) {
pr_err("tm6000: couldn't register the adapter!\n");
goto err;
}
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_unregister_frontend(dvb->frontend);
dvb_frontend_detach(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) {
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_unregister_frontend(dvb->frontend);
dvb_frontend_detach(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;
if (dev->udev->speed == USB_SPEED_FULL) {
printk(KERN_INFO "This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)\n");
return 0;
}
dvb = kzalloc(sizeof(struct tm6000_dvb), GFP_KERNEL);
if (!dvb)
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);

View File

@ -1,317 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
// tm6000-i2c.c - driver for TM5600/TM6000/TM6010 USB video capture devices
//
// Copyright (c) 2006-2007 Mauro Carvalho Chehab <mchehab@kernel.org>
//
// Copyright (c) 2007 Michel Ludwig <michel.ludwig@gmail.com>
// - Fix SMBus Read Byte command
#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 "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 i2c_packet_limit = 16;
if (dev->dev_type == TM6010)
i2c_packet_limit = 80;
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;
}
/* 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;
}
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;
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 fulfill 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;
strscpy(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;
strscpy(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;
}

View File

@ -1,503 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* tm6000-input.c - driver for TM5600/TM6000/TM6010 USB video capture devices
*
* Copyright (C) 2010 Stefan Ringel <stefan.ringel@arcor.de>
*/
#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, "debug message level");
static unsigned int enable_ir = 1;
module_param(enable_ir, int, 0644);
MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)");
static unsigned int ir_clock_mhz = 12;
module_param(ir_clock_mhz, int, 0644);
MODULE_PARM_DESC(ir_clock_mhz, "ir clock, in MHz");
#define URB_SUBMIT_DELAY 100 /* ms - Delay to submit an URB request on retrial and init */
#define URB_INT_LED_DELAY 100 /* ms - Delay to turn led on again on int mode */
#undef dprintk
#define dprintk(level, fmt, arg...) do {\
if (ir_debug >= level) \
printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
} while (0)
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 pwled:2;
u8 submit_urb:1;
struct urb *int_urb;
/* IR device properties */
u64 rc_proto;
};
void tm6000_ir_wait(struct tm6000_core *dev, u8 state)
{
struct tm6000_IR *ir = dev->ir;
if (!dev->ir)
return;
dprintk(2, "%s: %i\n",__func__, ir->wait);
if (state)
ir->wait = 1;
else
ir->wait = 0;
}
static int tm6000_ir_config(struct tm6000_IR *ir)
{
struct tm6000_core *dev = ir->dev;
u32 pulse = 0, leader = 0;
dprintk(2, "%s\n",__func__);
/*
* The IR decoder supports RC-5 or NEC, with a configurable timing.
* The timing configuration there is not that accurate, as it uses
* approximate values. The NEC spec mentions a 562.5 unit period,
* and RC-5 uses a 888.8 period.
* Currently, driver assumes a clock provided by a 12 MHz XTAL, but
* a modprobe parameter can adjust it.
* Adjustments are required for other timings.
* It seems that the 900ms timing for NEC is used to detect a RC-5
* IR, in order to discard such decoding
*/
switch (ir->rc_proto) {
case RC_PROTO_BIT_NEC:
leader = 900; /* ms */
pulse = 700; /* ms - the actual value would be 562 */
break;
default:
case RC_PROTO_BIT_RC5:
leader = 900; /* ms - from the NEC decoding */
pulse = 1780; /* ms - The actual value would be 1776 */
break;
}
pulse = ir_clock_mhz * pulse;
leader = ir_clock_mhz * leader;
if (ir->rc_proto == RC_PROTO_BIT_NEC)
leader = leader | 0x8000;
dprintk(2, "%s: %s, %d MHz, leader = 0x%04x, pulse = 0x%06x \n",
__func__,
(ir->rc_proto == RC_PROTO_BIT_NEC) ? "NEC" : "RC-5",
ir_clock_mhz, leader, pulse);
/* Remote WAKEUP = enable, normal mode, from IR decoder output */
tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe);
/* Enable IR reception on non-busrt mode */
tm6000_set_reg(dev, TM6010_REQ07_RD8_IR, 0x2f);
/* IR_WKUP_SEL = Low byte in decoded IR data */
tm6000_set_reg(dev, TM6010_REQ07_RDA_IR_WAKEUP_SEL, 0xff);
/* IR_WKU_ADD code */
tm6000_set_reg(dev, TM6010_REQ07_RDB_IR_WAKEUP_ADD, 0xff);
tm6000_set_reg(dev, TM6010_REQ07_RDC_IR_LEADER1, leader >> 8);
tm6000_set_reg(dev, TM6010_REQ07_RDD_IR_LEADER0, leader);
tm6000_set_reg(dev, TM6010_REQ07_RDE_IR_PULSE_CNT1, pulse >> 8);
tm6000_set_reg(dev, TM6010_REQ07_RDF_IR_PULSE_CNT0, pulse);
if (!ir->polling)
tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
else
tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1);
msleep(10);
/* Shows that IR is working via the LED */
tm6000_flash_led(dev, 0);
msleep(100);
tm6000_flash_led(dev, 1);
ir->pwled = 1;
return 0;
}
static void tm6000_ir_keydown(struct tm6000_IR *ir,
const char *buf, unsigned int len)
{
u8 device, command;
u32 scancode;
enum rc_proto protocol;
if (len < 1)
return;
command = buf[0];
device = (len > 1 ? buf[1] : 0x0);
switch (ir->rc_proto) {
case RC_PROTO_BIT_RC5:
protocol = RC_PROTO_RC5;
scancode = RC_SCANCODE_RC5(device, command);
break;
case RC_PROTO_BIT_NEC:
protocol = RC_PROTO_NEC;
scancode = RC_SCANCODE_NEC(device, command);
break;
default:
protocol = RC_PROTO_OTHER;
scancode = RC_SCANCODE_OTHER(device << 8 | command);
break;
}
dprintk(1, "%s, protocol: 0x%04x, scancode: 0x%08x\n",
__func__, protocol, scancode);
rc_keydown(ir->rc, protocol, scancode, 0);
}
static void tm6000_ir_urb_received(struct urb *urb)
{
struct tm6000_core *dev = urb->context;
struct tm6000_IR *ir = dev->ir;
char *buf;
dprintk(2, "%s\n",__func__);
if (urb->status < 0 || urb->actual_length <= 0) {
printk(KERN_INFO "tm6000: IR URB failure: status: %i, length %i\n",
urb->status, urb->actual_length);
ir->submit_urb = 1;
schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY));
return;
}
buf = urb->transfer_buffer;
if (ir_debug)
print_hex_dump(KERN_DEBUG, "tm6000: IR data: ",
DUMP_PREFIX_OFFSET,16, 1,
buf, urb->actual_length, false);
tm6000_ir_keydown(ir, urb->transfer_buffer, urb->actual_length);
usb_submit_urb(urb, GFP_ATOMIC);
/*
* Flash the led. We can't do it here, as it is running on IRQ context.
* So, use the scheduler to do it, in a few ms.
*/
ir->pwled = 2;
schedule_delayed_work(&ir->work, msecs_to_jiffies(10));
}
static void tm6000_ir_handle_key(struct work_struct *work)
{
struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
struct tm6000_core *dev = ir->dev;
int rc;
u8 buf[2];
if (ir->wait)
return;
dprintk(3, "%s\n",__func__);
rc = tm6000_read_write_usb(dev, USB_DIR_IN |
USB_TYPE_VENDOR | USB_RECIP_DEVICE,
REQ_02_GET_IR_CODE, 0, 0, buf, 2);
if (rc < 0)
return;
/* Check if something was read */
if ((buf[0] & 0xff) == 0xff) {
if (!ir->pwled) {
tm6000_flash_led(dev, 1);
ir->pwled = 1;
}
return;
}
tm6000_ir_keydown(ir, buf, rc);
tm6000_flash_led(dev, 0);
ir->pwled = 0;
/* Re-schedule polling */
schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
}
static void tm6000_ir_int_work(struct work_struct *work)
{
struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
struct tm6000_core *dev = ir->dev;
int rc;
dprintk(3, "%s, submit_urb = %d, pwled = %d\n",__func__, ir->submit_urb,
ir->pwled);
if (ir->submit_urb) {
dprintk(3, "Resubmit urb\n");
tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
rc = usb_submit_urb(ir->int_urb, GFP_ATOMIC);
if (rc < 0) {
printk(KERN_ERR "tm6000: Can't submit an IR interrupt. Error %i\n",
rc);
/* Retry in 100 ms */
schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY));
return;
}
ir->submit_urb = 0;
}
/* Led is enabled only if USB submit doesn't fail */
if (ir->pwled == 2) {
tm6000_flash_led(dev, 0);
ir->pwled = 0;
schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_INT_LED_DELAY));
} else if (!ir->pwled) {
tm6000_flash_led(dev, 1);
ir->pwled = 1;
}
}
static int tm6000_ir_start(struct rc_dev *rc)
{
struct tm6000_IR *ir = rc->priv;
dprintk(2, "%s\n",__func__);
schedule_delayed_work(&ir->work, 0);
return 0;
}
static void tm6000_ir_stop(struct rc_dev *rc)
{
struct tm6000_IR *ir = rc->priv;
dprintk(2, "%s\n",__func__);
cancel_delayed_work_sync(&ir->work);
}
static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 *rc_proto)
{
struct tm6000_IR *ir = rc->priv;
if (!ir)
return 0;
dprintk(2, "%s\n",__func__);
ir->rc_proto = *rc_proto;
tm6000_ir_config(ir);
/* TODO */
return 0;
}
static int __tm6000_ir_int_start(struct rc_dev *rc)
{
struct tm6000_IR *ir = rc->priv;
struct tm6000_core *dev;
int pipe, size;
int err = -ENOMEM;
if (!ir)
return -ENODEV;
dev = ir->dev;
dprintk(2, "%s\n",__func__);
ir->int_urb = usb_alloc_urb(0, GFP_ATOMIC);
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);
dprintk(1, "IR max size: %d\n", size);
ir->int_urb->transfer_buffer = kzalloc(size, GFP_ATOMIC);
if (!ir->int_urb->transfer_buffer) {
usb_free_urb(ir->int_urb);
return err;
}
dprintk(1, "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);
ir->submit_urb = 1;
schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY));
return 0;
}
static void __tm6000_ir_int_stop(struct rc_dev *rc)
{
struct tm6000_IR *ir = rc->priv;
if (!ir || !ir->int_urb)
return;
dprintk(2, "%s\n",__func__);
usb_kill_urb(ir->int_urb);
kfree(ir->int_urb->transfer_buffer);
usb_free_urb(ir->int_urb);
ir->int_urb = NULL;
}
int tm6000_ir_int_start(struct tm6000_core *dev)
{
struct tm6000_IR *ir = dev->ir;
if (!ir)
return 0;
return __tm6000_ir_int_start(ir->rc);
}
void tm6000_ir_int_stop(struct tm6000_core *dev)
{
struct tm6000_IR *ir = dev->ir;
if (!ir || !ir->rc)
return;
__tm6000_ir_int_stop(ir->rc);
}
int tm6000_ir_init(struct tm6000_core *dev)
{
struct tm6000_IR *ir;
struct rc_dev *rc;
int err = -ENOMEM;
u64 rc_proto;
if (!enable_ir)
return -ENODEV;
if (!dev->caps.has_remote)
return 0;
if (!dev->ir_codes)
return 0;
ir = kzalloc(sizeof(*ir), GFP_ATOMIC);
rc = rc_allocate_device(RC_DRIVER_SCANCODE);
if (!ir || !rc)
goto out;
dprintk(2, "%s\n", __func__);
/* record handles to ourself */
ir->dev = dev;
dev->ir = ir;
ir->rc = rc;
/* input setup */
rc->allowed_protocols = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_NEC;
/* Needed, in order to support NEC remotes with 24 or 32 bits */
rc->scancode_mask = 0xffff;
rc->priv = ir;
rc->change_protocol = tm6000_ir_change_protocol;
if (dev->int_in.endp) {
rc->open = __tm6000_ir_int_start;
rc->close = __tm6000_ir_int_stop;
INIT_DELAYED_WORK(&ir->work, tm6000_ir_int_work);
} else {
rc->open = tm6000_ir_start;
rc->close = tm6000_ir_stop;
ir->polling = 50;
INIT_DELAYED_WORK(&ir->work, tm6000_ir_handle_key);
}
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));
rc_proto = RC_PROTO_BIT_UNKNOWN;
tm6000_ir_change_protocol(rc, &rc_proto);
rc->device_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;
/* 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;
dprintk(2, "%s\n",__func__);
if (!ir->polling)
__tm6000_ir_int_stop(ir->rc);
tm6000_ir_stop(ir->rc);
/* Turn off the led */
tm6000_flash_led(dev, 0);
ir->pwled = 0;
rc_unregister_device(ir->rc);
kfree(ir);
dev->ir = NULL;
return 0;
}

View File

@ -1,588 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* tm6000-regs.h - driver for TM5600/TM6000/TM6010 USB video capture devices
*
* Copyright (c) 2006-2007 Mauro Carvalho Chehab <mchehab@kernel.org>
*/
/*
* 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_RD9_IR_BSIZE 0x07, 0xd9
/* ONLY for TM6010 */
#define TM6010_REQ07_RDA_IR_WAKEUP_SEL 0x07, 0xda
/* ONLY for TM6010 */
#define TM6010_REQ07_RDB_IR_WAKEUP_ADD 0x07, 0xdb
/* ONLY for TM6010 */
#define TM6010_REQ07_RDC_IR_LEADER1 0x07, 0xdc
/* ONLY for TM6010 */
#define TM6010_REQ07_RDD_IR_LEADER0 0x07, 0xdd
/* ONLY for TM6010 */
#define TM6010_REQ07_RDE_IR_PULSE_CNT1 0x07, 0xde
/* ONLY for TM6010 */
#define TM6010_REQ07_RDF_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

View File

@ -1,623 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
// tm6000-stds.c - driver for TM5600/TM6000/TM6010 USB video capture devices
//
// Copyright (c) 2007 Mauro Carvalho Chehab <mchehab@kernel.org>
#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, manual channel mode */
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;
}
/*
* STD/MN shouldn't be affected by tm6010_a_mode, as there's just one
* audio standard for each V4L2_STD type.
*/
if ((dev->norm & V4L2_STD_NTSC) == V4L2_STD_NTSC_M_KR) {
areg_05 |= 0x04;
} else if ((dev->norm & V4L2_STD_NTSC) == V4L2_STD_NTSC_M_JP) {
areg_05 |= 0x43;
} else if (dev->norm & V4L2_STD_MN) {
areg_05 |= 0x22;
} else switch (tm6010_a_mode) {
/* auto */
case 0:
if ((dev->norm & V4L2_STD_SECAM) == V4L2_STD_SECAM_L)
areg_05 |= 0x00;
else /* Other PAL/SECAM standards */
areg_05 |= 0x10;
break;
/* A2 */
case 1:
if (dev->norm & V4L2_STD_DK)
areg_05 = 0x09;
else
areg_05 = 0x05;
break;
/* NICAM */
case 2:
if (dev->norm & V4L2_STD_DK) {
areg_05 = 0x06;
} else if (dev->norm & V4L2_STD_PAL_I) {
areg_05 = 0x08;
} else if (dev->norm & V4L2_STD_SECAM_L) {
areg_05 = 0x0a;
areg_02 = 0x02;
} else {
areg_05 = 0x07;
}
break;
/* other */
case 3:
if (dev->norm & V4L2_STD_DK) {
areg_05 = 0x0b;
} else {
areg_05 = 0x02;
}
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);
/* Mux overflow workaround */
tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
0x10, 0xf0);
break;
case TM6000_AMUX_ADC2:
tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
0x08, 0x0f);
/* Mux overflow workaround */
tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
0x10, 0xf0);
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);
/* Mux overflow workaround */
tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
0x30, 0xf0);
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);
/* Mux overflow workaround */
tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
0x30, 0xf0);
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;
}

View File

@ -1,38 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* tm6000-buf.c - driver for TM5600/TM6000/TM6010 USB video capture devices
*
* Copyright (c) 2006-2007 Mauro Carvalho Chehab <mchehab@kernel.org>
*/
#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;
};

File diff suppressed because it is too large Load Diff

View File

@ -1,396 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* tm6000.h - driver for TM5600/TM6000/TM6010 USB video capture devices
*
* Copyright (c) 2006-2007 Mauro Carvalho Chehab <mchehab@kernel.org>
*
* Copyright (c) 2007 Michel Ludwig <michel.ludwig@gmail.com>
* - DVB-T support
*/
#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 <media/v4l2-ctrls.h>
#include <media/v4l2-fh.h>
#include <linux/dvb/frontend.h>
#include <media/dvb_demux.h>
#include <media/dvb_frontend.h>
#include <media/dmxdev.h>
/* 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 {
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;
/* Used to load alsa/dvb */
struct work_struct request_module_wk;
/* 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;
struct v4l2_ctrl_handler ctrl_handler;
struct v4l2_ctrl_handler radio_ctrl_handler;
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;
/* urb dma buffers */
char **urb_buffer;
dma_addr_t *urb_dma;
unsigned int urb_size;
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 v4l2_fh 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)