aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/tm6000
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--drivers/staging/tm6000/Makefile10
-rw-r--r--drivers/staging/tm6000/TODO6
-rw-r--r--drivers/staging/tm6000/tm6000-alsa.c109
-rw-r--r--drivers/staging/tm6000/tm6000-cards.c41
-rw-r--r--drivers/staging/tm6000/tm6000-core.c163
-rw-r--r--drivers/staging/tm6000/tm6000-dvb.c32
-rw-r--r--drivers/staging/tm6000/tm6000-i2c.c43
-rw-r--r--drivers/staging/tm6000/tm6000-input.c34
-rw-r--r--drivers/staging/tm6000/tm6000-regs.h32
-rw-r--r--drivers/staging/tm6000/tm6000-stds.c350
-rw-r--r--drivers/staging/tm6000/tm6000-usb-isoc.h32
-rw-r--r--drivers/staging/tm6000/tm6000-video.c442
-rw-r--r--drivers/staging/tm6000/tm6000.h54
13 files changed, 862 insertions, 486 deletions
diff --git a/drivers/staging/tm6000/Makefile b/drivers/staging/tm6000/Makefile
index 77e06bfd2c46..395515b4a888 100644
--- a/drivers/staging/tm6000/Makefile
+++ b/drivers/staging/tm6000/Makefile
@@ -1,4 +1,4 @@
-tm6000-objs := tm6000-cards.o \
+tm6000-y := tm6000-cards.o \
tm6000-core.o \
tm6000-i2c.o \
tm6000-video.o \
@@ -9,7 +9,7 @@ obj-$(CONFIG_VIDEO_TM6000) += tm6000.o
obj-$(CONFIG_VIDEO_TM6000_ALSA) += tm6000-alsa.o
obj-$(CONFIG_VIDEO_TM6000_DVB) += tm6000-dvb.o
-EXTRA_CFLAGS = -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y := -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff --git a/drivers/staging/tm6000/TODO b/drivers/staging/tm6000/TODO
new file mode 100644
index 000000000000..34780fc17b16
--- /dev/null
+++ b/drivers/staging/tm6000/TODO
@@ -0,0 +1,6 @@
+There a few things to do before putting this driver in production:
+ - CodingStyle;
+ - Fix audio;
+ - Fix some panic/OOPS conditions.
+
+Please send patches to linux-media@vger.kernel.org
diff --git a/drivers/staging/tm6000/tm6000-alsa.c b/drivers/staging/tm6000/tm6000-alsa.c
index 087137d9164d..184cc505ed86 100644
--- a/drivers/staging/tm6000/tm6000-alsa.c
+++ b/drivers/staging/tm6000/tm6000-alsa.c
@@ -160,15 +160,15 @@ static struct snd_pcm_hardware snd_tm6000_digital_hw = {
SNDRV_PCM_INFO_MMAP_VALID,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
- .rates = SNDRV_PCM_RATE_48000,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
.rate_min = 48000,
.rate_max = 48000,
.channels_min = 2,
.channels_max = 2,
- .period_bytes_min = 62720,
- .period_bytes_max = 62720,
+ .period_bytes_min = 64,
+ .period_bytes_max = 12544,
.periods_min = 1,
- .periods_max = 1024,
+ .periods_max = 98,
.buffer_bytes_max = 62720 * 8,
};
@@ -201,6 +201,14 @@ _error:
*/
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;
}
@@ -211,38 +219,67 @@ static int tm6000_fillbuf(struct tm6000_core *core, char *buf, int size)
struct snd_pcm_runtime *runtime;
int period_elapsed = 0;
unsigned int stride, buf_pos;
+ int length;
- if (!size || !substream)
+ 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)
+ 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 + size >= runtime->buffer_size * stride) {
- unsigned int cnt = runtime->buffer_size * stride - buf_pos;
- memcpy(runtime->dma_area + buf_pos, buf, cnt);
- memcpy(runtime->dma_area, buf + cnt, size - cnt);
+ 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, buf, size);
+ memcpy(runtime->dma_area + buf_pos * stride, buf,
+ length * stride);
- chip->buf_pos += size;
- if (chip->buf_pos >= runtime->buffer_size * stride)
- chip->buf_pos -= runtime->buffer_size * stride;
+#ifndef NO_PCM_LOCK
+ snd_pcm_stream_lock(substream);
+#endif
- chip->period_pos += size;
+ 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;
}
+#ifndef NO_PCM_LOCK
+ snd_pcm_stream_unlock(substream);
+#endif
+
if (period_elapsed)
snd_pcm_period_elapsed(substream);
@@ -272,8 +309,12 @@ static int snd_tm6000_hw_params(struct snd_pcm_substream *substream,
static int snd_tm6000_hw_free(struct snd_pcm_substream *substream)
{
struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+ struct tm6000_core *core = chip->core;
- _tm6000_stop_audio_dma(chip);
+ if (atomic_read(&core->stream_started) > 0) {
+ atomic_set(&core->stream_started, 0);
+ schedule_work(&core->wq_trigger);
+ }
return 0;
}
@@ -295,30 +336,42 @@ static int snd_tm6000_prepare(struct snd_pcm_substream *substream)
/*
* 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);
- int err;
-
- spin_lock(&chip->reg_lock);
+ struct tm6000_core *core = chip->core;
+ int err = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- err = _tm6000_start_audio_dma(chip);
+ atomic_set(&core->stream_started, 1);
break;
case SNDRV_PCM_TRIGGER_STOP:
- err = _tm6000_stop_audio_dma(chip);
+ atomic_set(&core->stream_started, 0);
break;
default:
err = -EINVAL;
break;
}
-
- spin_unlock(&chip->reg_lock);
+ schedule_work(&core->wq_trigger);
return err;
}
-
/*
* pointer callback
*/
@@ -403,7 +456,7 @@ int tm6000_audio_init(struct tm6000_core *dev)
rc = snd_pcm_new(card, "TM6000 Audio", 0, 0, 1, &pcm);
if (rc < 0)
- goto error;
+ goto error_chip;
pcm->info_flags = 0;
pcm->private_data = chip;
@@ -411,14 +464,18 @@ int tm6000_audio_init(struct tm6000_core *dev)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_tm6000_pcm_ops);
+ INIT_WORK(&dev->wq_trigger, audio_trigger);
rc = snd_card_register(card);
if (rc < 0)
- goto error;
+ 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;
diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/staging/tm6000/tm6000-cards.c
index 9d091c34991b..664e6038090d 100644
--- a/drivers/staging/tm6000/tm6000-cards.c
+++ b/drivers/staging/tm6000/tm6000-cards.c
@@ -1,20 +1,20 @@
/*
- tm6000-cards.c - driver for TM5600/TM6000/TM6010 USB video capture devices
-
- Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation version 2
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * tm6000-cards.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/init.h>
@@ -349,7 +349,7 @@ int tm6000_xc5000_callback(void *ptr, int component, int command, int arg)
dev->gpio.tuner_reset, 0x01);
break;
}
- return (rc);
+ return rc;
}
EXPORT_SYMBOL_GPL(tm6000_xc5000_callback);
@@ -545,7 +545,7 @@ static void tm6000_config_tuner(struct tm6000_core *dev)
/* Load tuner module */
v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
- "tuner", "tuner", dev->tuner_addr, NULL);
+ NULL, "tuner", dev->tuner_addr, NULL);
memset(&tun_setup, 0, sizeof(tun_setup));
tun_setup.type = dev->tuner_type;
@@ -683,7 +683,7 @@ static int tm6000_init_dev(struct tm6000_core *dev)
if (dev->caps.has_tda9874)
v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
- "tvaudio", "tvaudio", I2C_ADDR_TDA9874, NULL);
+ NULL, "tvaudio", I2C_ADDR_TDA9874, NULL);
/* register and initialize V4L2 */
rc = tm6000_v4l2_register(dev);
@@ -909,8 +909,6 @@ static void tm6000_usb_disconnect(struct usb_interface *interface)
printk(KERN_INFO "tm6000: disconnecting %s\n", dev->name);
- mutex_lock(&dev->lock);
-
tm6000_ir_fini(dev);
if (dev->gpio.power_led) {
@@ -945,7 +943,6 @@ static void tm6000_usb_disconnect(struct usb_interface *interface)
tm6000_close_extension(dev);
tm6000_remove_from_devlist(dev);
- mutex_unlock(&dev->lock);
kfree(dev);
}
diff --git a/drivers/staging/tm6000/tm6000-core.c b/drivers/staging/tm6000/tm6000-core.c
index cded411d8bba..40a0206e2432 100644
--- a/drivers/staging/tm6000/tm6000-core.c
+++ b/drivers/staging/tm6000/tm6000-core.c
@@ -1,23 +1,23 @@
/*
- tm6000-core.c - driver for TM5600/TM6000/TM6010 USB video capture devices
-
- Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
-
- Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
- - DVB-T support
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation version 2
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * tm6000-core.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ * Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
+ * - DVB-T support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
@@ -30,14 +30,13 @@
#include <media/v4l2-common.h>
#include <media/tuner.h>
-#define USB_TIMEOUT 5*HZ /* ms */
+#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;
- static int ini = 0, last = 0, n = 0;
u8 *data = NULL;
if (len)
@@ -52,19 +51,12 @@ int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req,
}
if (tm6000_debug & V4L2_DEBUG_I2C) {
- if (!ini)
- last = ini = jiffies;
-
- printk("%06i (dev %p, pipe %08x): ", n, dev->udev, pipe);
+ printk("(dev %p, pipe %08x): ", dev->udev, pipe);
- printk("%s: %06u ms %06u ms %02x %02x %02x %02x %02x %02x %02x %02x ",
+ printk("%s: %02x %02x %02x %02x %02x %02x %02x %02x ",
(req_type & USB_DIR_IN) ? " IN" : "OUT",
- jiffies_to_msecs(jiffies-last),
- jiffies_to_msecs(jiffies-ini),
req_type, req, value&0xff, value>>8, index&0xff,
index>>8, len&0xff, len>>8);
- last = jiffies;
- n++;
if (!(req_type & USB_DIR_IN)) {
printk(">>> ");
@@ -186,21 +178,17 @@ void tm6000_set_fourcc_format(struct tm6000_core *dev)
}
}
-int tm6000_init_analog_mode(struct tm6000_core *dev)
+static void tm6000_set_vbi(struct tm6000_core *dev)
{
- if (dev->dev_type == TM6010) {
- int val;
-
- /* Enable video */
- val = tm6000_get_reg(dev, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, 0);
- val |= 0x60;
- tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, val);
- val = tm6000_get_reg(dev,
- TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0);
- val &= ~0x40;
- tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, val);
+ /*
+ * 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)
+ */
- /* Init teletext */
+ 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);
@@ -249,44 +237,26 @@ int tm6000_init_analog_mode(struct tm6000_core *dev)
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;
- /* Init audio */
- 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, 0xa0);
- tm6000_set_reg(dev, TM6010_REQ08_R05_A_STANDARD_MOD, 0x05);
- tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x06);
- 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_RE4_ADC_IN2_SEL, 0xf3);
- tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x00);
- tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x80);
+ if (dev->dev_type == TM6010) {
+ int val;
+
+ /* Enable video */
+ val = tm6000_get_reg(dev, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, 0);
+ val |= 0x60;
+ tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, val);
+ val = tm6000_get_reg(dev,
+ TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0);
+ val &= ~0x40;
+ tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, val);
+
+ tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc);
} else {
/* Enables soft reset */
@@ -325,15 +295,22 @@ int tm6000_init_analog_mode(struct tm6000_core *dev)
/* Tuner firmware can now be loaded */
- /*FIXME: Hack!!! */
- struct v4l2_frequency f;
- mutex_lock(&dev->lock);
+ /*
+ * 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);
- mutex_unlock(&dev->lock);
msleep(100);
tm6000_set_standard(dev, &dev->norm);
+ tm6000_set_vbi(dev);
tm6000_set_audio_bitrate(dev, 48000);
/* switch dvb led off */
@@ -361,7 +338,6 @@ int tm6000_init_digital_mode(struct tm6000_core *dev)
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);
- tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfe);
tm6000_read_write_usb(dev, 0xc0, 0x0e, 0x00c2, 0x0008, buf, 2);
printk(KERN_INFO"buf %#x %#x\n", buf[0], buf[1]);
} else {
@@ -660,7 +636,6 @@ void tm6000_add_into_devlist(struct tm6000_core *dev)
*/
static LIST_HEAD(tm6000_extension_devlist);
-static DEFINE_MUTEX(tm6000_extension_devlist_lock);
int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type,
char *buf, int size)
@@ -684,14 +659,12 @@ int tm6000_register_extension(struct tm6000_ops *ops)
struct tm6000_core *dev = NULL;
mutex_lock(&tm6000_devlist_mutex);
- mutex_lock(&tm6000_extension_devlist_lock);
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_extension_devlist_lock);
mutex_unlock(&tm6000_devlist_mutex);
return 0;
}
@@ -702,15 +675,11 @@ 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) {
- if (dev)
- ops->fini(dev);
- }
+ list_for_each_entry(dev, &tm6000_devlist, devlist)
+ ops->fini(dev);
- mutex_lock(&tm6000_extension_devlist_lock);
printk(KERN_INFO "tm6000: Remove (%s) extension\n", ops->name);
list_del(&ops->next);
- mutex_unlock(&tm6000_extension_devlist_lock);
mutex_unlock(&tm6000_devlist_mutex);
}
EXPORT_SYMBOL(tm6000_unregister_extension);
@@ -719,26 +688,26 @@ void tm6000_init_extension(struct tm6000_core *dev)
{
struct tm6000_ops *ops = NULL;
- mutex_lock(&tm6000_extension_devlist_lock);
+ mutex_lock(&tm6000_devlist_mutex);
if (!list_empty(&tm6000_extension_devlist)) {
list_for_each_entry(ops, &tm6000_extension_devlist, next) {
if (ops->init)
ops->init(dev);
}
}
- mutex_unlock(&tm6000_extension_devlist_lock);
+ mutex_unlock(&tm6000_devlist_mutex);
}
void tm6000_close_extension(struct tm6000_core *dev)
{
struct tm6000_ops *ops = NULL;
- mutex_lock(&tm6000_extension_devlist_lock);
+ mutex_lock(&tm6000_devlist_mutex);
if (!list_empty(&tm6000_extension_devlist)) {
list_for_each_entry(ops, &tm6000_extension_devlist, next) {
if (ops->fini)
ops->fini(dev);
}
}
- mutex_unlock(&tm6000_extension_devlist_lock);
+ mutex_lock(&tm6000_devlist_mutex);
}
diff --git a/drivers/staging/tm6000/tm6000-dvb.c b/drivers/staging/tm6000/tm6000-dvb.c
index f501edccf9c4..ff04c89e45a3 100644
--- a/drivers/staging/tm6000/tm6000-dvb.c
+++ b/drivers/staging/tm6000/tm6000-dvb.c
@@ -1,20 +1,20 @@
/*
- tm6000-dvb.c - dvb-t support for TM5600/TM6000/TM6010 USB video capture devices
-
- Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation version 2
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * tm6000-dvb.c - dvb-t support for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ * Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/kernel.h>
diff --git a/drivers/staging/tm6000/tm6000-i2c.c b/drivers/staging/tm6000/tm6000-i2c.c
index 79bc67f0311f..3e46866dd279 100644
--- a/drivers/staging/tm6000/tm6000-i2c.c
+++ b/drivers/staging/tm6000/tm6000-i2c.c
@@ -1,23 +1,23 @@
/*
- tm6000-i2c.c - driver for TM5600/TM6000/TM6010 USB video capture devices
-
- Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
-
- Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
- - Fix SMBus Read Byte command
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation version 2
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * tm6000-i2c.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ * Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
+ * - Fix SMBus Read Byte command
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
@@ -32,11 +32,9 @@
#include "tuner-xc2028.h"
-/*FIXME: Hack to avoid needing to patch i2c-id.h */
-#define I2C_HW_B_TM6000 I2C_HW_B_EM28XX
/* ----------------------------------------------------------- */
-static unsigned int i2c_debug = 0;
+static unsigned int i2c_debug;
module_param(i2c_debug, int, 0644);
MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
@@ -324,7 +322,6 @@ static struct i2c_adapter tm6000_adap_template = {
.owner = THIS_MODULE,
.class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL,
.name = "tm6000",
- .id = I2C_HW_B_TM6000,
.algo = &tm6000_algo,
};
diff --git a/drivers/staging/tm6000/tm6000-input.c b/drivers/staging/tm6000/tm6000-input.c
index 54f7667cc706..6022caaa739b 100644
--- a/drivers/staging/tm6000/tm6000-input.c
+++ b/drivers/staging/tm6000/tm6000-input.c
@@ -1,20 +1,20 @@
/*
- tm6000-input.c - driver for TM5600/TM6000/TM6010 USB video capture devices
-
- Copyright (C) 2010 Stefan Ringel <stefan.ringel@arcor.de>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation version 2
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * tm6000-input.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ * Copyright (C) 2010 Stefan Ringel <stefan.ringel@arcor.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
@@ -36,7 +36,7 @@ MODULE_PARM_DESC(ir_debug, "enable debug message [IR]");
static unsigned int enable_ir = 1;
module_param(enable_ir, int, 0644);
-MODULE_PARM_DESC(enable_ir, "enable ir (default is enable");
+MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)");
#undef dprintk
diff --git a/drivers/staging/tm6000/tm6000-regs.h b/drivers/staging/tm6000/tm6000-regs.h
index 1c5289c971fa..1f0ced8fa20f 100644
--- a/drivers/staging/tm6000/tm6000-regs.h
+++ b/drivers/staging/tm6000/tm6000-regs.h
@@ -1,20 +1,20 @@
/*
- tm6000-regs.h - driver for TM5600/TM6000/TM6010 USB video capture devices
-
- Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation version 2
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * tm6000-regs.h - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
diff --git a/drivers/staging/tm6000/tm6000-stds.c b/drivers/staging/tm6000/tm6000-stds.c
index 6bf4a73b320d..cc7b8664fc20 100644
--- a/drivers/staging/tm6000/tm6000-stds.c
+++ b/drivers/staging/tm6000/tm6000-stds.c
@@ -1,20 +1,20 @@
/*
- tm6000-stds.c - driver for TM5600/TM6000/TM6010 USB video capture devices
-
- Copyright (C) 2007 Mauro Carvalho Chehab <mchehab@redhat.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation version 2
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * tm6000-stds.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ * Copyright (C) 2007 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
@@ -28,21 +28,37 @@ struct tm6000_reg_settings {
unsigned char value;
};
+enum tm6000_audio_std {
+ BG_NICAM,
+ BTSC,
+ BG_A2,
+ DK_NICAM,
+ EIAJ,
+ FM_RADIO,
+ I_NICAM,
+ KOREA_A2,
+ L_NICAM,
+};
+
struct tm6000_std_tv_settings {
v4l2_std_id id;
+ enum tm6000_audio_std audio_default_std;
+
struct tm6000_reg_settings sif[12];
struct tm6000_reg_settings nosif[12];
- struct tm6000_reg_settings common[25];
+ struct tm6000_reg_settings common[26];
};
struct tm6000_std_settings {
v4l2_std_id id;
+ enum tm6000_audio_std audio_default_std;
struct tm6000_reg_settings common[37];
};
static struct tm6000_std_tv_settings tv_stds[] = {
{
.id = V4L2_STD_PAL_M,
+ .audio_default_std = BTSC,
.sif = {
{TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf2},
{TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8},
@@ -96,11 +112,14 @@ static struct tm6000_std_tv_settings tv_stds[] = {
{TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc},
{TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07},
+
{TM6010_REQ07_R3F_RESET, 0x00},
+
{0, 0, 0},
},
}, {
.id = V4L2_STD_PAL_Nc,
+ .audio_default_std = BTSC,
.sif = {
{TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf2},
{TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8},
@@ -154,11 +173,14 @@ static struct tm6000_std_tv_settings tv_stds[] = {
{TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc},
{TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07},
+
{TM6010_REQ07_R3F_RESET, 0x00},
+
{0, 0, 0},
},
}, {
.id = V4L2_STD_PAL,
+ .audio_default_std = BG_A2,
.sif = {
{TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf2},
{TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8},
@@ -212,11 +234,73 @@ static struct tm6000_std_tv_settings tv_stds[] = {
{TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc},
{TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07},
+
{TM6010_REQ07_R3F_RESET, 0x00},
+
{0, 0, 0},
},
}, {
- .id = V4L2_STD_SECAM,
+ .id = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G,
+ .audio_default_std = BG_NICAM,
+ .sif = {
+ {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf2},
+ {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8},
+ {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3},
+ {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x08},
+ {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1},
+ {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0},
+ {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2},
+ {TM6010_REQ08_RED_GAIN_SEL, 0xe8},
+ {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x62},
+ {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfe},
+ {TM6010_REQ07_RFE_POWER_DOWN, 0xcb},
+ {0, 0, 0},
+ },
+ .nosif = {
+ {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0},
+ {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8},
+ {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3},
+ {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x0f},
+ {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1},
+ {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0},
+ {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2},
+ {TM6010_REQ08_RED_GAIN_SEL, 0xe8},
+ {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x60},
+ {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc},
+ {TM6010_REQ07_RFE_POWER_DOWN, 0x8b},
+ {0, 0, 0},
+ },
+ .common = {
+ {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},
+ },
+ }, {
+ .id = V4L2_STD_SECAM_DK,
+ .audio_default_std = DK_NICAM,
.sif = {
{TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf2},
{TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8},
@@ -269,11 +353,13 @@ static struct tm6000_std_tv_settings tv_stds[] = {
{TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xFF},
{TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07},
+
{TM6010_REQ07_R3F_RESET, 0x00},
{0, 0, 0},
},
}, {
.id = V4L2_STD_NTSC,
+ .audio_default_std = BTSC,
.sif = {
{TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf2},
{TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8},
@@ -327,7 +413,9 @@ static struct tm6000_std_tv_settings tv_stds[] = {
{TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd},
{TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07},
+
{TM6010_REQ07_R3F_RESET, 0x00},
+
{0, 0, 0},
},
},
@@ -336,6 +424,7 @@ static struct tm6000_std_tv_settings tv_stds[] = {
static struct tm6000_std_settings composite_stds[] = {
{
.id = V4L2_STD_PAL_M,
+ .audio_default_std = BTSC,
.common = {
{TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0},
{TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4},
@@ -378,6 +467,7 @@ static struct tm6000_std_settings composite_stds[] = {
},
}, {
.id = V4L2_STD_PAL_Nc,
+ .audio_default_std = BTSC,
.common = {
{TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0},
{TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4},
@@ -420,6 +510,7 @@ static struct tm6000_std_settings composite_stds[] = {
},
}, {
.id = V4L2_STD_PAL,
+ .audio_default_std = BG_A2,
.common = {
{TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0},
{TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4},
@@ -462,6 +553,49 @@ static struct tm6000_std_settings composite_stds[] = {
},
}, {
.id = V4L2_STD_SECAM,
+ .audio_default_std = BG_NICAM,
+ .common = {
+ {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0},
+ {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4},
+ {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3},
+ {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x0f},
+ {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1},
+ {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0},
+ {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2},
+ {TM6010_REQ08_RED_GAIN_SEL, 0xe8},
+ {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x68},
+ {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc},
+ {TM6010_REQ07_RFE_POWER_DOWN, 0x8b},
+
+ {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},
+ },
+ }, {
+ .id = V4L2_STD_SECAM_DK,
+ .audio_default_std = DK_NICAM,
.common = {
{TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0},
{TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4},
@@ -503,6 +637,7 @@ static struct tm6000_std_settings composite_stds[] = {
},
}, {
.id = V4L2_STD_NTSC,
+ .audio_default_std = BTSC,
.common = {
{TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0},
{TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4},
@@ -549,6 +684,7 @@ static struct tm6000_std_settings composite_stds[] = {
static struct tm6000_std_settings svideo_stds[] = {
{
.id = V4L2_STD_PAL_M,
+ .audio_default_std = BTSC,
.common = {
{TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0},
{TM6010_REQ08_RE3_ADC_IN1_SEL, 0xfc},
@@ -591,6 +727,7 @@ static struct tm6000_std_settings svideo_stds[] = {
},
}, {
.id = V4L2_STD_PAL_Nc,
+ .audio_default_std = BTSC,
.common = {
{TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0},
{TM6010_REQ08_RE3_ADC_IN1_SEL, 0xfc},
@@ -633,6 +770,7 @@ static struct tm6000_std_settings svideo_stds[] = {
},
}, {
.id = V4L2_STD_PAL,
+ .audio_default_std = BG_A2,
.common = {
{TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0},
{TM6010_REQ08_RE3_ADC_IN1_SEL, 0xfc},
@@ -675,6 +813,49 @@ static struct tm6000_std_settings svideo_stds[] = {
},
}, {
.id = V4L2_STD_SECAM,
+ .audio_default_std = BG_NICAM,
+ .common = {
+ {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0},
+ {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xfc},
+ {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_RED_GAIN_SEL, 0xe0},
+ {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x68},
+ {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc},
+ {TM6010_REQ07_RFE_POWER_DOWN, 0x8a},
+
+ {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},
+ },
+ }, {
+ .id = V4L2_STD_SECAM_DK,
+ .audio_default_std = DK_NICAM,
.common = {
{TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0},
{TM6010_REQ08_RE3_ADC_IN1_SEL, 0xfc},
@@ -716,6 +897,7 @@ static struct tm6000_std_settings svideo_stds[] = {
},
}, {
.id = V4L2_STD_NTSC,
+ .audio_default_std = BTSC,
.common = {
{TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0},
{TM6010_REQ08_RE3_ADC_IN1_SEL, 0xfc},
@@ -760,6 +942,133 @@ static struct tm6000_std_settings svideo_stds[] = {
},
};
+
+static int tm6000_set_audio_std(struct tm6000_core *dev,
+ enum tm6000_audio_std std)
+{
+ uint8_t areg_02 = 0x04; /* GC1 Fixed gain 0dB */
+ uint8_t areg_05 = 0x09; /* Auto 4.5 = M Japan, Auto 6.5 = DK */
+ uint8_t areg_06 = 0x02; /* Auto de-emphasis, mannual channel mode */
+ uint8_t mono_flag = 0; /* No mono */
+ uint8_t nicam_flag = 0; /* No NICAM */
+
+ switch (std) {
+#if 0
+ case DK_MONO:
+ mono_flag = 1;
+ break;
+ case DK_A2_1:
+ break;
+ case DK_A2_3:
+ areg_05 = 0x0b;
+ break;
+ case BG_MONO:
+ mono_flag = 1;
+ areg_05 = 0x05;
+ break;
+#endif
+ case BG_NICAM:
+ areg_05 = 0x07;
+ nicam_flag = 1;
+ break;
+ case BTSC:
+ areg_05 = 0x02;
+ break;
+ case BG_A2:
+ areg_05 = 0x05;
+ break;
+ case DK_NICAM:
+ areg_05 = 0x06;
+ nicam_flag = 1;
+ break;
+ case EIAJ:
+ areg_05 = 0x02;
+ break;
+ case FM_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_R05_A_STANDARD_MOD, 0x0c);
+ tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x00);
+ tm6000_set_reg(dev, TM6010_REQ08_R09_A_MAIN_VOL, 0x18);
+ tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, 0x91);
+ 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_R1E_A_GAIN_DEEMPH_OUT, 0x13);
+ tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x80);
+ return 0;
+ break;
+ case I_NICAM:
+ areg_05 = 0x08;
+ nicam_flag = 1;
+ break;
+ case KOREA_A2:
+ areg_05 = 0x04;
+ break;
+ case L_NICAM:
+ areg_02 = 0x02; /* GC1 Fixed gain +12dB */
+ areg_05 = 0x0a;
+ nicam_flag = 1;
+ break;
+ }
+
+#if 0
+ switch (tv_audio_mode) {
+ case TV_MONO:
+ areg_06 = (nicam_flag) ? 0x03 : 0x00;
+ break;
+ case TV_LANG_A:
+ areg_06 = 0x00;
+ break;
+ case TV_LANG_B:
+ areg_06 = 0x01;
+ break;
+ }
+#endif
+
+ if (mono_flag)
+ areg_06 = 0x00;
+
+ 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_RE4_ADC_IN2_SEL, 0xf3);
+ tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x00);
+ tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc);
+ 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 */
@@ -820,6 +1129,8 @@ static int tm6000_set_tv(struct tm6000_core *dev, int pos)
rc = tm6000_load_std(dev, tv_stds[pos].common,
sizeof(tv_stds[pos].common));
+ tm6000_set_audio_std(dev, tv_stds[pos].audio_default_std);
+
return rc;
}
@@ -845,6 +1156,8 @@ int tm6000_set_standard(struct tm6000_core *dev, v4l2_std_id * norm)
rc = tm6000_load_std(dev, svideo_stds[i].common,
sizeof(svideo_stds[i].
common));
+ tm6000_set_audio_std(dev, svideo_stds[i].audio_default_std);
+
goto ret;
}
}
@@ -856,6 +1169,7 @@ int tm6000_set_standard(struct tm6000_core *dev, v4l2_std_id * norm)
composite_stds[i].common,
sizeof(composite_stds[i].
common));
+ tm6000_set_audio_std(dev, composite_stds[i].audio_default_std);
goto ret;
}
}
diff --git a/drivers/staging/tm6000/tm6000-usb-isoc.h b/drivers/staging/tm6000/tm6000-usb-isoc.h
index 138716a8f056..a9e61d95a9b2 100644
--- a/drivers/staging/tm6000/tm6000-usb-isoc.h
+++ b/drivers/staging/tm6000/tm6000-usb-isoc.h
@@ -1,20 +1,20 @@
/*
- tm6000-buf.c - driver for TM5600/TM6000/TM6010 USB video capture devices
-
- Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation version 2
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * tm6000-buf.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/videodev2.h>
diff --git a/drivers/staging/tm6000/tm6000-video.c b/drivers/staging/tm6000/tm6000-video.c
index ce0a089a0771..9ec82796634e 100644
--- a/drivers/staging/tm6000/tm6000-video.c
+++ b/drivers/staging/tm6000/tm6000-video.c
@@ -1,23 +1,23 @@
/*
- tm6000-video.c - driver for TM5600/TM6000/TM6010 USB video capture devices
-
- Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
-
- Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
- - Fixed module load/unload
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation version 2
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * tm6000-video.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ * Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
+ * - Fixed module load/unload
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/delay.h>
@@ -118,8 +118,9 @@ static struct tm6000_fmt format[] = {
};
/* ------------------------------------------------------------------
- DMA and thread functions
- ------------------------------------------------------------------*/
+ * DMA and thread functions
+ * ------------------------------------------------------------------
+ */
#define norm_maxw(a) 720
#define norm_maxh(a) 576
@@ -189,17 +190,17 @@ static int copy_streams(u8 *data, unsigned long len,
struct urb *urb)
{
struct tm6000_dmaqueue *dma_q = urb->context;
- struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq);
- u8 *ptr=data, *endp=data+len, c;
- unsigned long header=0;
- int rc=0;
+ struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
+ u8 *ptr = data, *endp = data+len, c;
+ unsigned long header = 0;
+ int rc = 0;
unsigned int cmd, cpysize, pktsize, size, field, block, line, pos = 0;
struct tm6000_buffer *vbuf;
char *voutp = NULL;
unsigned int linewidth;
/* get video buffer */
- get_next_buf (dma_q, &vbuf);
+ get_next_buf(dma_q, &vbuf);
if (!vbuf)
return rc;
voutp = videobuf_to_vmalloc(&vbuf->vb);
@@ -213,7 +214,7 @@ static int copy_streams(u8 *data, unsigned long len,
/* from last urb or packet */
header = dev->isoc_ctl.tmp_buf;
if (4 - dev->isoc_ctl.tmp_buf_len > 0) {
- memcpy ((u8 *)&header +
+ memcpy((u8 *)&header +
dev->isoc_ctl.tmp_buf_len,
ptr,
4 - dev->isoc_ctl.tmp_buf_len);
@@ -224,7 +225,7 @@ static int copy_streams(u8 *data, unsigned long len,
if (ptr + 3 >= endp) {
/* have incomplete header */
dev->isoc_ctl.tmp_buf_len = endp - ptr;
- memcpy (&dev->isoc_ctl.tmp_buf, ptr,
+ memcpy(&dev->isoc_ctl.tmp_buf, ptr,
dev->isoc_ctl.tmp_buf_len);
return rc;
}
@@ -261,13 +262,13 @@ static int copy_streams(u8 *data, unsigned long len,
/* Announces that a new buffer
* were filled
*/
- buffer_filled (dev, dma_q, vbuf);
- dprintk (dev, V4L2_DEBUG_ISOC,
+ buffer_filled(dev, dma_q, vbuf);
+ dprintk(dev, V4L2_DEBUG_ISOC,
"new buffer filled\n");
- get_next_buf (dma_q, &vbuf);
+ get_next_buf(dma_q, &vbuf);
if (!vbuf)
return rc;
- voutp = videobuf_to_vmalloc (&vbuf->vb);
+ voutp = videobuf_to_vmalloc(&vbuf->vb);
if (!voutp)
return rc;
memset(voutp, 0, vbuf->vb.size);
@@ -301,9 +302,17 @@ static int copy_streams(u8 *data, unsigned long len,
case TM6000_URB_MSG_VIDEO:
/* Fills video buffer */
if (vbuf)
- memcpy (&voutp[pos], ptr, cpysize);
+ memcpy(&voutp[pos], ptr, cpysize);
break;
case TM6000_URB_MSG_AUDIO:
+ /* Need some code to copy audio buffer */
+ if (dev->fourcc == V4L2_PIX_FMT_YUYV) {
+ /* Swap word bytes */
+ int i;
+
+ for (i = 0; i < cpysize; i += 2)
+ swab16s((u16 *)(ptr + i));
+ }
tm6000_call_fillbuf(dev, TM6000_AUDIO, ptr, cpysize);
break;
case TM6000_URB_MSG_VBI:
@@ -338,9 +347,9 @@ static int copy_multiplexed(u8 *ptr, unsigned long len,
struct urb *urb)
{
struct tm6000_dmaqueue *dma_q = urb->context;
- struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq);
- unsigned int pos=dev->isoc_ctl.pos,cpysize;
- int rc=1;
+ struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
+ unsigned int pos = dev->isoc_ctl.pos, cpysize;
+ int rc = 1;
struct tm6000_buffer *buf;
char *outp = NULL;
@@ -351,19 +360,18 @@ static int copy_multiplexed(u8 *ptr, unsigned long len,
if (!outp)
return 0;
- while (len>0) {
- cpysize=min(len,buf->vb.size-pos);
- //printk("Copying %d bytes (max=%lu) from %p to %p[%u]\n",cpysize,(*buf)->vb.size,ptr,out_p,pos);
+ while (len > 0) {
+ cpysize = min(len, buf->vb.size-pos);
memcpy(&outp[pos], ptr, cpysize);
- pos+=cpysize;
- ptr+=cpysize;
- len-=cpysize;
+ pos += cpysize;
+ ptr += cpysize;
+ len -= cpysize;
if (pos >= buf->vb.size) {
- pos=0;
+ pos = 0;
/* Announces that a new buffer were filled */
- buffer_filled (dev, dma_q, buf);
+ buffer_filled(dev, dma_q, buf);
dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n");
- get_next_buf (dma_q, &buf);
+ get_next_buf(dma_q, &buf);
if (!buf)
break;
outp = videobuf_to_vmalloc(&(buf->vb));
@@ -373,16 +381,16 @@ static int copy_multiplexed(u8 *ptr, unsigned long len,
}
}
- dev->isoc_ctl.pos=pos;
+ dev->isoc_ctl.pos = pos;
return rc;
}
-static void inline print_err_status (struct tm6000_core *dev,
+static inline void print_err_status(struct tm6000_core *dev,
int packet, int status)
{
char *errmsg = "Unknown";
- switch(status) {
+ switch (status) {
case -ENOENT:
errmsg = "unlinked synchronuously";
break;
@@ -408,7 +416,7 @@ static void inline print_err_status (struct tm6000_core *dev,
errmsg = "Device does not respond";
break;
}
- if (packet<0) {
+ if (packet < 0) {
dprintk(dev, V4L2_DEBUG_QUEUE, "URB status %d [%s].\n",
status, errmsg);
} else {
@@ -424,20 +432,20 @@ static void inline print_err_status (struct tm6000_core *dev,
static inline int tm6000_isoc_copy(struct urb *urb)
{
struct tm6000_dmaqueue *dma_q = urb->context;
- struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq);
- int i, len=0, rc=1, status;
+ struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
+ int i, len = 0, rc = 1, status;
char *p;
if (urb->status < 0) {
- print_err_status (dev, -1, urb->status);
+ print_err_status(dev, -1, urb->status);
return 0;
}
for (i = 0; i < urb->number_of_packets; i++) {
status = urb->iso_frame_desc[i].status;
- if (status<0) {
- print_err_status (dev,i,status);
+ if (status < 0) {
+ print_err_status(dev, i, status);
continue;
}
@@ -446,9 +454,9 @@ static inline int tm6000_isoc_copy(struct urb *urb)
if (len > 0) {
p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
if (!urb->iso_frame_desc[i].status) {
- if ((dev->fourcc)==V4L2_PIX_FMT_TM6000) {
- rc=copy_multiplexed(p, len, urb);
- if (rc<=0)
+ if ((dev->fourcc) == V4L2_PIX_FMT_TM6000) {
+ rc = copy_multiplexed(p, len, urb);
+ if (rc <= 0)
return rc;
} else {
copy_streams(p, len, urb);
@@ -460,8 +468,9 @@ static inline int tm6000_isoc_copy(struct urb *urb)
}
/* ------------------------------------------------------------------
- URB control
- ------------------------------------------------------------------*/
+ * URB control
+ * ------------------------------------------------------------------
+ */
/*
* IRQ callback, called by URB callback
@@ -501,7 +510,7 @@ static void tm6000_uninit_isoc(struct tm6000_core *dev)
dev->isoc_ctl.buf = NULL;
for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
- urb=dev->isoc_ctl.urb[i];
+ urb = dev->isoc_ctl.urb[i];
if (urb) {
usb_kill_urb(urb);
usb_unlink_urb(urb);
@@ -517,11 +526,11 @@ static void tm6000_uninit_isoc(struct tm6000_core *dev)
dev->isoc_ctl.transfer_buffer[i] = NULL;
}
- kfree (dev->isoc_ctl.urb);
- kfree (dev->isoc_ctl.transfer_buffer);
+ kfree(dev->isoc_ctl.urb);
+ kfree(dev->isoc_ctl.transfer_buffer);
- dev->isoc_ctl.urb=NULL;
- dev->isoc_ctl.transfer_buffer=NULL;
+ dev->isoc_ctl.urb = NULL;
+ dev->isoc_ctl.transfer_buffer = NULL;
dev->isoc_ctl.num_bufs = 0;
}
@@ -552,7 +561,7 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev, unsigned int framesize)
dev->isoc_ctl.max_pkt_size = size;
- max_packets = ( framesize + size - 1) / size;
+ max_packets = (framesize + size - 1) / size;
if (max_packets > TM6000_MAX_ISO_PACKETS)
max_packets = TM6000_MAX_ISO_PACKETS;
@@ -594,10 +603,10 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev, unsigned int framesize)
dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev,
sb_size, GFP_KERNEL, &urb->transfer_dma);
if (!dev->isoc_ctl.transfer_buffer[i]) {
- tm6000_err ("unable to allocate %i bytes for transfer"
+ tm6000_err("unable to allocate %i bytes for transfer"
" buffer %i%s\n",
sb_size, i,
- in_interrupt()?" while in int":"");
+ in_interrupt() ? " while in int" : "");
tm6000_uninit_isoc(dev);
return -ENOMEM;
}
@@ -619,13 +628,13 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev, unsigned int framesize)
return 0;
}
-static int tm6000_start_thread( struct tm6000_core *dev)
+static int tm6000_start_thread(struct tm6000_core *dev)
{
struct tm6000_dmaqueue *dma_q = &dev->vidq;
int i;
- dma_q->frame=0;
- dma_q->ini_jiffies=jiffies;
+ dma_q->frame = 0;
+ dma_q->ini_jiffies = jiffies;
init_waitqueue_head(&dma_q->wq);
@@ -644,8 +653,9 @@ static int tm6000_start_thread( struct tm6000_core *dev)
}
/* ------------------------------------------------------------------
- Videobuf operations
- ------------------------------------------------------------------*/
+ * Videobuf operations
+ * ------------------------------------------------------------------
+ */
static int
buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
@@ -656,9 +666,8 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
if (0 == *count)
*count = TM6000_DEF_BUF;
- if (*count < TM6000_MIN_BUF) {
- *count=TM6000_MIN_BUF;
- }
+ if (*count < TM6000_MIN_BUF)
+ *count = TM6000_MIN_BUF;
while (*size * *count > vid_limit * 1024 * 1024)
(*count)--;
@@ -698,7 +707,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
enum v4l2_field field)
{
struct tm6000_fh *fh = vq->priv_data;
- struct tm6000_buffer *buf = container_of(vb,struct tm6000_buffer,vb);
+ struct tm6000_buffer *buf = container_of(vb, struct tm6000_buffer, vb);
struct tm6000_core *dev = fh->dev;
int rc = 0, urb_init = 0;
@@ -753,7 +762,7 @@ fail:
static void
buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
{
- struct tm6000_buffer *buf = container_of(vb,struct tm6000_buffer,vb);
+ struct tm6000_buffer *buf = container_of(vb, struct tm6000_buffer, vb);
struct tm6000_fh *fh = vq->priv_data;
struct tm6000_core *dev = fh->dev;
struct tm6000_dmaqueue *vidq = &dev->vidq;
@@ -764,9 +773,9 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb)
{
- struct tm6000_buffer *buf = container_of(vb,struct tm6000_buffer,vb);
+ struct tm6000_buffer *buf = container_of(vb, struct tm6000_buffer, vb);
- free_buffer(vq,buf);
+ free_buffer(vq, buf);
}
static struct videobuf_queue_ops tm6000_video_qops = {
@@ -777,49 +786,66 @@ static struct videobuf_queue_ops tm6000_video_qops = {
};
/* ------------------------------------------------------------------
- IOCTL handling
- ------------------------------------------------------------------*/
+ * IOCTL handling
+ * ------------------------------------------------------------------
+ */
-static int res_get(struct tm6000_core *dev, struct tm6000_fh *fh)
+static bool is_res_read(struct tm6000_core *dev, struct tm6000_fh *fh)
{
- /* is it free? */
- mutex_lock(&dev->lock);
- if (dev->resources) {
- /* no, someone else uses it */
- mutex_unlock(&dev->lock);
- return 0;
- }
- /* it's free, grab it */
- dev->resources =1;
- dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: get\n");
- mutex_unlock(&dev->lock);
- return 1;
+ /* Is the current fh handling it? if so, that's OK */
+ if (dev->resources == fh && dev->is_res_read)
+ return true;
+
+ return false;
+}
+
+static bool is_res_streaming(struct tm6000_core *dev, struct tm6000_fh *fh)
+{
+ /* Is the current fh handling it? if so, that's OK */
+ if (dev->resources == fh)
+ return true;
+
+ return false;
}
-static int res_locked(struct tm6000_core *dev)
+static bool res_get(struct tm6000_core *dev, struct tm6000_fh *fh,
+ bool is_res_read)
{
- return (dev->resources);
+ /* Is the current fh handling it? if so, that's OK */
+ if (dev->resources == fh && dev->is_res_read == is_res_read)
+ return true;
+
+ /* is it free? */
+ if (dev->resources)
+ return false;
+
+ /* grab it */
+ dev->resources = fh;
+ dev->is_res_read = is_res_read;
+ dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: get\n");
+ return true;
}
static void res_free(struct tm6000_core *dev, struct tm6000_fh *fh)
{
- mutex_lock(&dev->lock);
- dev->resources = 0;
+ /* Is the current fh handling it? if so, that's OK */
+ if (dev->resources != fh)
+ return;
+
+ dev->resources = NULL;
dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: put\n");
- mutex_unlock(&dev->lock);
}
/* ------------------------------------------------------------------
- IOCTL vidioc handling
- ------------------------------------------------------------------*/
-static int vidioc_querycap (struct file *file, void *priv,
+ * IOCTL vidioc handling
+ * ------------------------------------------------------------------
+ */
+static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- // struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev;
strlcpy(cap->driver, "tm6000", sizeof(cap->driver));
- strlcpy(cap->card,"Trident TVMaster TM5600/6000/6010", sizeof(cap->card));
- // strlcpy(cap->bus_info, dev->udev->dev.bus_id, sizeof(cap->bus_info));
+ strlcpy(cap->card, "Trident TVMaster TM5600/6000/6010", sizeof(cap->card));
cap->version = TM6000_VERSION;
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_STREAMING |
@@ -828,21 +854,21 @@ static int vidioc_querycap (struct file *file, void *priv,
return 0;
}
-static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv,
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
if (unlikely(f->index >= ARRAY_SIZE(format)))
return -EINVAL;
- strlcpy(f->description,format[f->index].name,sizeof(f->description));
+ strlcpy(f->description, format[f->index].name, sizeof(f->description));
f->pixelformat = format[f->index].fourcc;
return 0;
}
-static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct tm6000_fh *fh=priv;
+ struct tm6000_fh *fh = priv;
f->fmt.pix.width = fh->width;
f->fmt.pix.height = fh->height;
@@ -853,10 +879,10 @@ static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
f->fmt.pix.sizeimage =
f->fmt.pix.height * f->fmt.pix.bytesperline;
- return (0);
+ return 0;
}
-static struct tm6000_fmt* format_by_fourcc(unsigned int fourcc)
+static struct tm6000_fmt *format_by_fourcc(unsigned int fourcc)
{
unsigned int i;
@@ -866,7 +892,7 @@ static struct tm6000_fmt* format_by_fourcc(unsigned int fourcc)
return NULL;
}
-static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev;
@@ -882,15 +908,14 @@ static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
field = f->fmt.pix.field;
- if (field == V4L2_FIELD_ANY) {
-// field=V4L2_FIELD_INTERLACED;
- field=V4L2_FIELD_SEQ_TB;
- } else if (V4L2_FIELD_INTERLACED != field) {
+ if (field == V4L2_FIELD_ANY)
+ field = V4L2_FIELD_SEQ_TB;
+ else if (V4L2_FIELD_INTERLACED != field) {
dprintk(dev, V4L2_DEBUG_IOCTL_ARG, "Field type invalid.\n");
return -EINVAL;
}
- tm6000_get_std_res (dev);
+ tm6000_get_std_res(dev);
f->fmt.pix.width = dev->width;
f->fmt.pix.height = dev->height;
@@ -908,14 +933,14 @@ static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
}
/*FIXME: This seems to be generic enough to be at videodev2 */
-static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct tm6000_fh *fh=priv;
+ struct tm6000_fh *fh = priv;
struct tm6000_core *dev = fh->dev;
- int ret = vidioc_try_fmt_vid_cap(file,fh,f);
+ int ret = vidioc_try_fmt_vid_cap(file, fh, f);
if (ret < 0)
- return (ret);
+ return ret;
fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
fh->width = f->fmt.pix.width;
@@ -927,52 +952,52 @@ static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
tm6000_set_fourcc_format(dev);
- return (0);
+ return 0;
}
-static int vidioc_reqbufs (struct file *file, void *priv,
+static int vidioc_reqbufs(struct file *file, void *priv,
struct v4l2_requestbuffers *p)
{
- struct tm6000_fh *fh=priv;
+ struct tm6000_fh *fh = priv;
- return (videobuf_reqbufs(&fh->vb_vidq, p));
+ return videobuf_reqbufs(&fh->vb_vidq, p);
}
-static int vidioc_querybuf (struct file *file, void *priv,
+static int vidioc_querybuf(struct file *file, void *priv,
struct v4l2_buffer *p)
{
- struct tm6000_fh *fh=priv;
+ struct tm6000_fh *fh = priv;
- return (videobuf_querybuf(&fh->vb_vidq, p));
+ return videobuf_querybuf(&fh->vb_vidq, p);
}
-static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
{
- struct tm6000_fh *fh=priv;
+ struct tm6000_fh *fh = priv;
- return (videobuf_qbuf(&fh->vb_vidq, p));
+ return videobuf_qbuf(&fh->vb_vidq, p);
}
-static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
{
- struct tm6000_fh *fh=priv;
+ struct tm6000_fh *fh = priv;
- return (videobuf_dqbuf(&fh->vb_vidq, p,
- file->f_flags & O_NONBLOCK));
+ return videobuf_dqbuf(&fh->vb_vidq, p,
+ file->f_flags & O_NONBLOCK);
}
#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf)
+static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
{
- struct tm6000_fh *fh=priv;
+ struct tm6000_fh *fh = priv;
- return videobuf_cgmbuf (&fh->vb_vidq, mbuf, 8);
+ return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
}
#endif
static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
{
- struct tm6000_fh *fh=priv;
+ struct tm6000_fh *fh = priv;
struct tm6000_core *dev = fh->dev;
if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
@@ -980,7 +1005,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
if (i != fh->type)
return -EINVAL;
- if (!res_get(dev,fh))
+ if (!res_get(dev, fh, false))
return -EBUSY;
return (videobuf_streamon(&fh->vb_vidq));
}
@@ -1007,7 +1032,7 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *norm)
struct tm6000_fh *fh=priv;
struct tm6000_core *dev = fh->dev;
- rc=tm6000_set_standard (dev, norm);
+ rc = tm6000_init_analog_mode(dev);
fh->width = dev->width;
fh->height = dev->height;
@@ -1020,21 +1045,21 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *norm)
return 0;
}
-static int vidioc_enum_input (struct file *file, void *priv,
+static int vidioc_enum_input(struct file *file, void *priv,
struct v4l2_input *inp)
{
switch (inp->index) {
case TM6000_INPUT_TV:
inp->type = V4L2_INPUT_TYPE_TUNER;
- strcpy(inp->name,"Television");
+ strcpy(inp->name, "Television");
break;
case TM6000_INPUT_COMPOSITE:
inp->type = V4L2_INPUT_TYPE_CAMERA;
- strcpy(inp->name,"Composite");
+ strcpy(inp->name, "Composite");
break;
case TM6000_INPUT_SVIDEO:
inp->type = V4L2_INPUT_TYPE_CAMERA;
- strcpy(inp->name,"S-Video");
+ strcpy(inp->name, "S-Video");
break;
default:
return -EINVAL;
@@ -1044,48 +1069,48 @@ static int vidioc_enum_input (struct file *file, void *priv,
return 0;
}
-static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
{
- struct tm6000_fh *fh=priv;
+ struct tm6000_fh *fh = priv;
struct tm6000_core *dev = fh->dev;
- *i=dev->input;
+ *i = dev->input;
return 0;
}
-static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
{
- struct tm6000_fh *fh=priv;
+ struct tm6000_fh *fh = priv;
struct tm6000_core *dev = fh->dev;
- int rc=0;
+ int rc = 0;
char buf[1];
switch (i) {
case TM6000_INPUT_TV:
- dev->input=i;
- *buf=0;
+ dev->input = i;
+ *buf = 0;
break;
case TM6000_INPUT_COMPOSITE:
case TM6000_INPUT_SVIDEO:
- dev->input=i;
- *buf=1;
+ dev->input = i;
+ *buf = 1;
break;
default:
return -EINVAL;
}
- rc=tm6000_read_write_usb (dev, USB_DIR_OUT | USB_TYPE_VENDOR,
+ rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR,
REQ_03_SET_GET_MCU_PIN, 0x03, 1, buf, 1);
if (!rc) {
- dev->input=i;
- rc=vidioc_s_std (file, priv, &dev->vfd->current_norm);
+ dev->input = i;
+ rc = vidioc_s_std(file, priv, &dev->vfd->current_norm);
}
- return (rc);
+ return rc;
}
/* --- controls ---------------------------------------------- */
-static int vidioc_queryctrl (struct file *file, void *priv,
+static int vidioc_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *qc)
{
int i;
@@ -1094,16 +1119,16 @@ static int vidioc_queryctrl (struct file *file, void *priv,
if (qc->id && qc->id == tm6000_qctrl[i].id) {
memcpy(qc, &(tm6000_qctrl[i]),
sizeof(*qc));
- return (0);
+ return 0;
}
return -EINVAL;
}
-static int vidioc_g_ctrl (struct file *file, void *priv,
+static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct tm6000_fh *fh=priv;
+ struct tm6000_fh *fh = priv;
struct tm6000_core *dev = fh->dev;
int val;
@@ -1125,41 +1150,41 @@ static int vidioc_g_ctrl (struct file *file, void *priv,
return -EINVAL;
}
- if (val<0)
+ if (val < 0)
return val;
- ctrl->value=val;
+ ctrl->value = val;
return 0;
}
-static int vidioc_s_ctrl (struct file *file, void *priv,
+static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct tm6000_fh *fh =priv;
+ struct tm6000_fh *fh = priv;
struct tm6000_core *dev = fh->dev;
- u8 val=ctrl->value;
+ u8 val = ctrl->value;
switch (ctrl->id) {
case V4L2_CID_CONTRAST:
- tm6000_set_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, val);
+ tm6000_set_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, val);
return 0;
case V4L2_CID_BRIGHTNESS:
- tm6000_set_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, val);
+ tm6000_set_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, val);
return 0;
case V4L2_CID_SATURATION:
- tm6000_set_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, val);
+ tm6000_set_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, val);
return 0;
case V4L2_CID_HUE:
- tm6000_set_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, val);
+ tm6000_set_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, val);
return 0;
}
return -EINVAL;
}
-static int vidioc_g_tuner (struct file *file, void *priv,
+static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *t)
{
- struct tm6000_fh *fh =priv;
+ struct tm6000_fh *fh = priv;
struct tm6000_core *dev = fh->dev;
if (unlikely(UNSET == dev->tuner_type))
@@ -1176,10 +1201,10 @@ static int vidioc_g_tuner (struct file *file, void *priv,
return 0;
}
-static int vidioc_s_tuner (struct file *file, void *priv,
+static int vidioc_s_tuner(struct file *file, void *priv,
struct v4l2_tuner *t)
{
- struct tm6000_fh *fh =priv;
+ struct tm6000_fh *fh = priv;
struct tm6000_core *dev = fh->dev;
if (UNSET == dev->tuner_type)
@@ -1190,10 +1215,10 @@ static int vidioc_s_tuner (struct file *file, void *priv,
return 0;
}
-static int vidioc_g_frequency (struct file *file, void *priv,
+static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct tm6000_fh *fh =priv;
+ struct tm6000_fh *fh = priv;
struct tm6000_core *dev = fh->dev;
if (unlikely(UNSET == dev->tuner_type))
@@ -1207,10 +1232,10 @@ static int vidioc_g_frequency (struct file *file, void *priv,
return 0;
}
-static int vidioc_s_frequency (struct file *file, void *priv,
+static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct tm6000_fh *fh =priv;
+ struct tm6000_fh *fh = priv;
struct tm6000_core *dev = fh->dev;
if (unlikely(f->type != V4L2_TUNER_ANALOG_TV))
@@ -1221,10 +1246,8 @@ static int vidioc_s_frequency (struct file *file, void *priv,
if (unlikely(f->tuner != 0))
return -EINVAL;
-// mutex_lock(&dev->lock);
dev->freq = f->frequency;
v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f);
-// mutex_unlock(&dev->lock);
return 0;
}
@@ -1239,7 +1262,7 @@ static int tm6000_open(struct file *file)
struct tm6000_core *dev = video_drvdata(file);
struct tm6000_fh *fh;
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- int i,rc;
+ int i, rc;
printk(KERN_INFO "tm6000: open called (dev=%s)\n",
video_device_node_name(vdev));
@@ -1256,7 +1279,7 @@ static int tm6000_open(struct file *file)
dev->users);
/* allocate + initialize per filehandle data */
- fh = kzalloc(sizeof(*fh),GFP_KERNEL);
+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
if (NULL == fh) {
dev->users--;
return -ENOMEM;
@@ -1284,23 +1307,23 @@ static int tm6000_open(struct file *file)
"active=%d\n",list_empty(&dev->vidq.active));
/* initialize hardware on analog mode */
- if (dev->mode!=TM6000_MODE_ANALOG) {
- rc=tm6000_init_analog_mode (dev);
- if (rc<0)
- return rc;
+ rc = tm6000_init_analog_mode(dev);
+ if (rc < 0)
+ return rc;
+ if (dev->mode != TM6000_MODE_ANALOG) {
/* Put all controls at a sane state */
for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++)
- qctl_regs[i] =tm6000_qctrl[i].default_value;
+ qctl_regs[i] = tm6000_qctrl[i].default_value;
- dev->mode=TM6000_MODE_ANALOG;
+ dev->mode = TM6000_MODE_ANALOG;
}
videobuf_queue_vmalloc_init(&fh->vb_vidq, &tm6000_video_qops,
NULL, &dev->slock,
fh->type,
V4L2_FIELD_INTERLACED,
- sizeof(struct tm6000_buffer),fh);
+ sizeof(struct tm6000_buffer), fh, &dev->lock);
return 0;
}
@@ -1311,7 +1334,7 @@ tm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos)
struct tm6000_fh *fh = file->private_data;
if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- if (res_locked(fh->dev))
+ if (!res_get(fh->dev, fh, true))
return -EBUSY;
return videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0,
@@ -1329,7 +1352,10 @@ tm6000_poll(struct file *file, struct poll_table_struct *wait)
if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
return POLLERR;
- if (res_get(fh->dev,fh)) {
+ if (!!is_res_streaming(fh->dev, fh))
+ return POLLERR;
+
+ if (!is_res_read(fh->dev, fh)) {
/* streaming capture */
if (list_empty(&fh->vb_vidq.stream))
return POLLERR;
@@ -1342,7 +1368,7 @@ tm6000_poll(struct file *file, struct poll_table_struct *wait)
poll_wait(file, &buf->vb.done, wait);
if (buf->vb.state == VIDEOBUF_DONE ||
buf->vb.state == VIDEOBUF_ERROR)
- return POLLIN|POLLRDNORM;
+ return POLLIN | POLLRDNORM;
return 0;
}
@@ -1357,12 +1383,13 @@ static int tm6000_release(struct file *file)
dev->users--;
+ res_free(dev, fh);
if (!dev->users) {
tm6000_uninit_isoc(dev);
videobuf_mmap_free(&fh->vb_vidq);
}
- kfree (fh);
+ kfree(fh);
return 0;
}
@@ -1372,7 +1399,7 @@ static int tm6000_mmap(struct file *file, struct vm_area_struct * vma)
struct tm6000_fh *fh = file->private_data;
int ret;
- ret=videobuf_mmap_mapper(&fh->vb_vidq, vma);
+ ret = videobuf_mmap_mapper(&fh->vb_vidq, vma);
return ret;
}
@@ -1381,7 +1408,7 @@ static struct v4l2_file_operations tm6000_fops = {
.owner = THIS_MODULE,
.open = tm6000_open,
.release = tm6000_release,
- .ioctl = video_ioctl2, /* V4L2 ioctl handler */
+ .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
.read = tm6000_read,
.poll = tm6000_poll,
.mmap = tm6000_mmap,
@@ -1425,8 +1452,9 @@ static struct video_device tm6000_template = {
};
/* -----------------------------------------------------------------
- Initialization and module stuff
- ------------------------------------------------------------------*/
+ * Initialization and module stuff
+ * ------------------------------------------------------------------
+ */
int tm6000_v4l2_register(struct tm6000_core *dev)
{
@@ -1443,8 +1471,10 @@ int tm6000_v4l2_register(struct tm6000_core *dev)
INIT_LIST_HEAD(&dev->vidq.active);
INIT_LIST_HEAD(&dev->vidq.queued);
- memcpy (dev->vfd, &tm6000_template, sizeof(*(dev->vfd)));
- dev->vfd->debug=tm6000_debug;
+ memcpy(dev->vfd, &tm6000_template, sizeof(*(dev->vfd)));
+ dev->vfd->debug = tm6000_debug;
+ dev->vfd->lock = &dev->lock;
+
vfd->v4l2_dev = &dev->v4l2_dev;
video_set_drvdata(vfd, dev);
@@ -1466,11 +1496,11 @@ int tm6000_v4l2_exit(void)
}
module_param(video_nr, int, 0);
-MODULE_PARM_DESC(video_nr,"Allow changing video device number");
+MODULE_PARM_DESC(video_nr, "Allow changing video device number");
-module_param_named (debug, tm6000_debug, int, 0444);
-MODULE_PARM_DESC(debug,"activates debug info");
+module_param_named(debug, tm6000_debug, int, 0444);
+MODULE_PARM_DESC(debug, "activates debug info");
-module_param(vid_limit,int,0644);
-MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");
+module_param(vid_limit, int, 0644);
+MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
diff --git a/drivers/staging/tm6000/tm6000.h b/drivers/staging/tm6000/tm6000.h
index 1ec1bff9b294..46017b603190 100644
--- a/drivers/staging/tm6000/tm6000.h
+++ b/drivers/staging/tm6000/tm6000.h
@@ -1,23 +1,23 @@
/*
- tm6000.h - driver for TM5600/TM6000/TM6010 USB video capture devices
-
- Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
-
- Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
- - DVB-T support
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation version 2
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * tm6000.h - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ * Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
+ * - DVB-T support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Use the tm6000-hack, instead of the proper initialization code i*/
@@ -54,8 +54,9 @@ enum tm6000_devtype {
};
/* ------------------------------------------------------------------
- Basic structures
- ------------------------------------------------------------------*/
+ * Basic structures
+ * ------------------------------------------------------------------
+ */
struct tm6000_fmt {
char *name;
@@ -189,7 +190,9 @@ struct tm6000_core {
int users;
/* various device info */
- unsigned int resources;
+ struct tm6000_fh *resources; /* Points to fh that is streaming */
+ bool is_res_read;
+
struct video_device *vfd;
struct tm6000_dmaqueue vidq;
struct v4l2_device v4l2_dev;
@@ -205,6 +208,9 @@ struct tm6000_core {
/* 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;
@@ -251,9 +257,9 @@ struct tm6000_fh {
enum v4l2_buf_type type;
};
-#define TM6000_STD V4L2_STD_PAL|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc| \
+#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
+ V4L2_STD_NTSC_M_JP|V4L2_STD_SECAM)
/* In tm6000-cards.c */