summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video/cx18
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/video/cx18')
-rw-r--r--linux/drivers/media/video/cx18/Kconfig2
-rw-r--r--linux/drivers/media/video/cx18/cx18-av-audio.c111
-rw-r--r--linux/drivers/media/video/cx18/cx18-ioctl.c92
-rw-r--r--linux/drivers/media/video/cx18/cx18-irq.c2
-rw-r--r--linux/drivers/media/video/cx18/cx18-queue.c23
-rw-r--r--linux/drivers/media/video/cx18/cx18-queue.h2
-rw-r--r--linux/drivers/media/video/cx18/cx18-streams.c3
7 files changed, 157 insertions, 78 deletions
diff --git a/linux/drivers/media/video/cx18/Kconfig b/linux/drivers/media/video/cx18/Kconfig
index 9aefdc5ea..ef48565de 100644
--- a/linux/drivers/media/video/cx18/Kconfig
+++ b/linux/drivers/media/video/cx18/Kconfig
@@ -2,9 +2,7 @@ config VIDEO_CX18
tristate "Conexant cx23418 MPEG encoder support"
depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL
depends on INPUT # due to VIDEO_IR
- depends on HOTPLUG # due to FW_LOADER
select I2C_ALGOBIT
- select FW_LOADER
select VIDEO_IR
select VIDEO_TUNER
select VIDEO_TVEEPROM
diff --git a/linux/drivers/media/video/cx18/cx18-av-audio.c b/linux/drivers/media/video/cx18/cx18-av-audio.c
index c40a286de..0b5583788 100644
--- a/linux/drivers/media/video/cx18/cx18-av-audio.c
+++ b/linux/drivers/media/video/cx18/cx18-av-audio.c
@@ -30,7 +30,6 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
if (freq != 32000 && freq != 44100 && freq != 48000)
return -EINVAL;
- /* common for all inputs and rates */
/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */
cx18_av_write(cx, 0x127, 0x50);
@@ -38,15 +37,30 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
switch (freq) {
case 32000:
/* VID_PLL and AUX_PLL */
- cx18_av_write4(cx, 0x108, 0x1006040f);
+ cx18_av_write4(cx, 0x108, 0x1408040f);
/* AUX_PLL_FRAC */
- cx18_av_write4(cx, 0x110, 0x01bb39ee);
+ /* 0x8.9504318a * 28,636,363.636 / 0x14 = 32000 * 384 */
+ cx18_av_write4(cx, 0x110, 0x012a0863);
- /* src3/4/6_ctl = 0x0801f77f */
+ /* src3/4/6_ctl */
+ /* 0x1.f77f = (4 * 15734.26) / 32000 */
cx18_av_write4(cx, 0x900, 0x0801f77f);
cx18_av_write4(cx, 0x904, 0x0801f77f);
cx18_av_write4(cx, 0x90c, 0x0801f77f);
+
+ /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */
+ cx18_av_write(cx, 0x127, 0x54);
+
+ /* AUD_COUNT = 0x2fff = 8 samples * 4 * 384 - 1 */
+ cx18_av_write4(cx, 0x12c, 0x11202fff);
+
+ /*
+ * EN_AV_LOCK = 1
+ * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
+ * ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
+ */
+ cx18_av_write4(cx, 0x128, 0xa10d2ef8);
break;
case 44100:
@@ -54,12 +68,24 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
cx18_av_write4(cx, 0x108, 0x1009040f);
/* AUX_PLL_FRAC */
- cx18_av_write4(cx, 0x110, 0x00ec6bd6);
+ /* 0x9.7635e7 * 28,636,363.63 / 0x10 = 44100 * 384 */
+ cx18_av_write4(cx, 0x110, 0x00ec6bce);
- /* src3/4/6_ctl = 0x08016d59 */
+ /* src3/4/6_ctl */
+ /* 0x1.6d59 = (4 * 15734.26) / 44100 */
cx18_av_write4(cx, 0x900, 0x08016d59);
cx18_av_write4(cx, 0x904, 0x08016d59);
cx18_av_write4(cx, 0x90c, 0x08016d59);
+
+ /* AUD_COUNT = 0x92ff = 49 samples * 2 * 384 - 1 */
+ cx18_av_write4(cx, 0x12c, 0x112092ff);
+
+ /*
+ * EN_AV_LOCK = 1
+ * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
+ * ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
+ */
+ cx18_av_write4(cx, 0x128, 0xa11d4bf8);
break;
case 48000:
@@ -67,12 +93,24 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
cx18_av_write4(cx, 0x108, 0x100a040f);
/* AUX_PLL_FRAC */
- cx18_av_write4(cx, 0x110, 0x0098d6e5);
+ /* 0xa.4c6b6ea * 28,636,363.63 / 0x10 = 48000 * 384 */
+ cx18_av_write4(cx, 0x110, 0x0098d6dd);
- /* src3/4/6_ctl = 0x08014faa */
+ /* src3/4/6_ctl */
+ /* 0x1.4faa = (4 * 15734.26) / 48000 */
cx18_av_write4(cx, 0x900, 0x08014faa);
cx18_av_write4(cx, 0x904, 0x08014faa);
cx18_av_write4(cx, 0x90c, 0x08014faa);
+
+ /* AUD_COUNT = 0x5fff = 4 samples * 16 * 384 - 1 */
+ cx18_av_write4(cx, 0x12c, 0x11205fff);
+
+ /*
+ * EN_AV_LOCK = 1
+ * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
+ * ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
+ */
+ cx18_av_write4(cx, 0x128, 0xa11193f8);
break;
}
} else {
@@ -82,18 +120,31 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
cx18_av_write4(cx, 0x108, 0x1e08040f);
/* AUX_PLL_FRAC */
- cx18_av_write4(cx, 0x110, 0x012a0869);
+ /* 0x8.9504318 * 28,636,363.63 / 0x1e = 32000 * 256 */
+ cx18_av_write4(cx, 0x110, 0x012a0863);
- /* src1_ctl = 0x08010000 */
+ /* src1_ctl */
+ /* 0x1.0000 = 32000/32000 */
cx18_av_write4(cx, 0x8f8, 0x08010000);
- /* src3/4/6_ctl = 0x08020000 */
+ /* src3/4/6_ctl */
+ /* 0x2.0000 = 2 * (32000/32000) */
cx18_av_write4(cx, 0x900, 0x08020000);
cx18_av_write4(cx, 0x904, 0x08020000);
cx18_av_write4(cx, 0x90c, 0x08020000);
/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */
cx18_av_write(cx, 0x127, 0x54);
+
+ /* AUD_COUNT = 0x1fff = 8 samples * 4 * 256 - 1 */
+ cx18_av_write4(cx, 0x12c, 0x11201fff);
+
+ /*
+ * EN_AV_LOCK = 1
+ * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
+ * ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
+ */
+ cx18_av_write4(cx, 0x128, 0xa10d2ef8);
break;
case 44100:
@@ -101,15 +152,28 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
cx18_av_write4(cx, 0x108, 0x1809040f);
/* AUX_PLL_FRAC */
- cx18_av_write4(cx, 0x110, 0x00ec6bd6);
+ /* 0x9.7635e74 * 28,636,363.63 / 0x18 = 44100 * 256 */
+ cx18_av_write4(cx, 0x110, 0x00ec6bce);
- /* src1_ctl = 0x08010000 */
+ /* src1_ctl */
+ /* 0x1.60cd = 44100/32000 */
cx18_av_write4(cx, 0x8f8, 0x080160cd);
- /* src3/4/6_ctl = 0x08020000 */
+ /* src3/4/6_ctl */
+ /* 0x1.7385 = 2 * (32000/44100) */
cx18_av_write4(cx, 0x900, 0x08017385);
cx18_av_write4(cx, 0x904, 0x08017385);
cx18_av_write4(cx, 0x90c, 0x08017385);
+
+ /* AUD_COUNT = 0x61ff = 49 samples * 2 * 256 - 1 */
+ cx18_av_write4(cx, 0x12c, 0x112061ff);
+
+ /*
+ * EN_AV_LOCK = 1
+ * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
+ * ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
+ */
+ cx18_av_write4(cx, 0x128, 0xa11d4bf8);
break;
case 48000:
@@ -117,15 +181,28 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
cx18_av_write4(cx, 0x108, 0x180a040f);
/* AUX_PLL_FRAC */
- cx18_av_write4(cx, 0x110, 0x0098d6e5);
+ /* 0xa.4c6b6ea * 28,636,363.63 / 0x18 = 48000 * 256 */
+ cx18_av_write4(cx, 0x110, 0x0098d6dd);
- /* src1_ctl = 0x08010000 */
+ /* src1_ctl */
+ /* 0x1.8000 = 48000/32000 */
cx18_av_write4(cx, 0x8f8, 0x08018000);
- /* src3/4/6_ctl = 0x08020000 */
+ /* src3/4/6_ctl */
+ /* 0x1.5555 = 2 * (32000/48000) */
cx18_av_write4(cx, 0x900, 0x08015555);
cx18_av_write4(cx, 0x904, 0x08015555);
cx18_av_write4(cx, 0x90c, 0x08015555);
+
+ /* AUD_COUNT = 0x3fff = 4 samples * 16 * 256 - 1 */
+ cx18_av_write4(cx, 0x12c, 0x11203fff);
+
+ /*
+ * EN_AV_LOCK = 1
+ * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
+ * ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
+ */
+ cx18_av_write4(cx, 0x128, 0xa11193f8);
break;
}
}
diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.c b/linux/drivers/media/video/cx18/cx18-ioctl.c
index 0221a67aa..e6c2bfa5d 100644
--- a/linux/drivers/media/video/cx18/cx18-ioctl.c
+++ b/linux/drivers/media/video/cx18/cx18-ioctl.c
@@ -892,50 +892,54 @@ int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
return res;
}
-void cx18_set_funcs(struct video_device *vdev)
-{
- vdev->vidioc_querycap = cx18_querycap;
- vdev->vidioc_g_priority = cx18_g_priority;
- vdev->vidioc_s_priority = cx18_s_priority;
- vdev->vidioc_s_audio = cx18_s_audio;
- vdev->vidioc_g_audio = cx18_g_audio;
- vdev->vidioc_enumaudio = cx18_enumaudio;
- vdev->vidioc_enum_input = cx18_enum_input;
- vdev->vidioc_cropcap = cx18_cropcap;
- vdev->vidioc_s_crop = cx18_s_crop;
- vdev->vidioc_g_crop = cx18_g_crop;
- vdev->vidioc_g_input = cx18_g_input;
- vdev->vidioc_s_input = cx18_s_input;
- vdev->vidioc_g_frequency = cx18_g_frequency;
- vdev->vidioc_s_frequency = cx18_s_frequency;
- vdev->vidioc_s_tuner = cx18_s_tuner;
- vdev->vidioc_g_tuner = cx18_g_tuner;
- vdev->vidioc_g_enc_index = cx18_g_enc_index;
- vdev->vidioc_g_std = cx18_g_std;
- vdev->vidioc_s_std = cx18_s_std;
- vdev->vidioc_log_status = cx18_log_status;
- vdev->vidioc_enum_fmt_vid_cap = cx18_enum_fmt_vid_cap;
- vdev->vidioc_encoder_cmd = cx18_encoder_cmd;
- vdev->vidioc_try_encoder_cmd = cx18_try_encoder_cmd;
- vdev->vidioc_g_fmt_vid_cap = cx18_g_fmt_vid_cap;
- vdev->vidioc_g_fmt_vbi_cap = cx18_g_fmt_vbi_cap;
- vdev->vidioc_g_fmt_sliced_vbi_cap = cx18_g_fmt_sliced_vbi_cap;
- vdev->vidioc_s_fmt_vid_cap = cx18_s_fmt_vid_cap;
- vdev->vidioc_s_fmt_vbi_cap = cx18_s_fmt_vbi_cap;
- vdev->vidioc_s_fmt_sliced_vbi_cap = cx18_s_fmt_sliced_vbi_cap;
- vdev->vidioc_try_fmt_vid_cap = cx18_try_fmt_vid_cap;
- vdev->vidioc_try_fmt_vbi_cap = cx18_try_fmt_vbi_cap;
- vdev->vidioc_try_fmt_sliced_vbi_cap = cx18_try_fmt_sliced_vbi_cap;
- vdev->vidioc_g_sliced_vbi_cap = cx18_g_sliced_vbi_cap;
- vdev->vidioc_g_chip_ident = cx18_g_chip_ident;
+static const struct v4l2_ioctl_ops cx18_ioctl_ops = {
+ .vidioc_querycap = cx18_querycap,
+ .vidioc_g_priority = cx18_g_priority,
+ .vidioc_s_priority = cx18_s_priority,
+ .vidioc_s_audio = cx18_s_audio,
+ .vidioc_g_audio = cx18_g_audio,
+ .vidioc_enumaudio = cx18_enumaudio,
+ .vidioc_enum_input = cx18_enum_input,
+ .vidioc_cropcap = cx18_cropcap,
+ .vidioc_s_crop = cx18_s_crop,
+ .vidioc_g_crop = cx18_g_crop,
+ .vidioc_g_input = cx18_g_input,
+ .vidioc_s_input = cx18_s_input,
+ .vidioc_g_frequency = cx18_g_frequency,
+ .vidioc_s_frequency = cx18_s_frequency,
+ .vidioc_s_tuner = cx18_s_tuner,
+ .vidioc_g_tuner = cx18_g_tuner,
+ .vidioc_g_enc_index = cx18_g_enc_index,
+ .vidioc_g_std = cx18_g_std,
+ .vidioc_s_std = cx18_s_std,
+ .vidioc_log_status = cx18_log_status,
+ .vidioc_enum_fmt_vid_cap = cx18_enum_fmt_vid_cap,
+ .vidioc_encoder_cmd = cx18_encoder_cmd,
+ .vidioc_try_encoder_cmd = cx18_try_encoder_cmd,
+ .vidioc_g_fmt_vid_cap = cx18_g_fmt_vid_cap,
+ .vidioc_g_fmt_vbi_cap = cx18_g_fmt_vbi_cap,
+ .vidioc_g_fmt_sliced_vbi_cap = cx18_g_fmt_sliced_vbi_cap,
+ .vidioc_s_fmt_vid_cap = cx18_s_fmt_vid_cap,
+ .vidioc_s_fmt_vbi_cap = cx18_s_fmt_vbi_cap,
+ .vidioc_s_fmt_sliced_vbi_cap = cx18_s_fmt_sliced_vbi_cap,
+ .vidioc_try_fmt_vid_cap = cx18_try_fmt_vid_cap,
+ .vidioc_try_fmt_vbi_cap = cx18_try_fmt_vbi_cap,
+ .vidioc_try_fmt_sliced_vbi_cap = cx18_try_fmt_sliced_vbi_cap,
+ .vidioc_g_sliced_vbi_cap = cx18_g_sliced_vbi_cap,
+ .vidioc_g_chip_ident = cx18_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG
- vdev->vidioc_g_register = cx18_g_register;
- vdev->vidioc_s_register = cx18_s_register;
+ .vidioc_g_register = cx18_g_register,
+ .vidioc_s_register = cx18_s_register,
#endif
- vdev->vidioc_default = cx18_default;
- vdev->vidioc_queryctrl = cx18_queryctrl;
- vdev->vidioc_querymenu = cx18_querymenu;
- vdev->vidioc_g_ext_ctrls = cx18_g_ext_ctrls;
- vdev->vidioc_s_ext_ctrls = cx18_s_ext_ctrls;
- vdev->vidioc_try_ext_ctrls = cx18_try_ext_ctrls;
+ .vidioc_default = cx18_default,
+ .vidioc_queryctrl = cx18_queryctrl,
+ .vidioc_querymenu = cx18_querymenu,
+ .vidioc_g_ext_ctrls = cx18_g_ext_ctrls,
+ .vidioc_s_ext_ctrls = cx18_s_ext_ctrls,
+ .vidioc_try_ext_ctrls = cx18_try_ext_ctrls,
+};
+
+void cx18_set_funcs(struct video_device *vdev)
+{
+ vdev->ioctl_ops = &cx18_ioctl_ops;
}
diff --git a/linux/drivers/media/video/cx18/cx18-irq.c b/linux/drivers/media/video/cx18/cx18-irq.c
index 654664783..b9cf609ee 100644
--- a/linux/drivers/media/video/cx18/cx18-irq.c
+++ b/linux/drivers/media/video/cx18/cx18-irq.c
@@ -61,7 +61,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
CX18_WARN("Ack struct = %d for %s\n",
mb->args[2], s->name);
id = read_enc(off);
- buf = cx18_queue_find_buf(s, id, read_enc(off + 4));
+ buf = cx18_queue_get_buf_irq(s, id, read_enc(off + 4));
CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id);
if (buf) {
cx18_buf_sync_for_cpu(s, buf);
diff --git a/linux/drivers/media/video/cx18/cx18-queue.c b/linux/drivers/media/video/cx18/cx18-queue.c
index 6990b77c6..8a4dd821f 100644
--- a/linux/drivers/media/video/cx18/cx18-queue.c
+++ b/linux/drivers/media/video/cx18/cx18-queue.c
@@ -78,12 +78,13 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q)
return buf;
}
-struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id,
+struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id,
u32 bytesused)
{
struct cx18 *cx = s->cx;
struct list_head *p;
+ spin_lock(&s->qlock);
list_for_each(p, &s->q_free.list) {
struct cx18_buffer *buf =
list_entry(p, struct cx18_buffer, list);
@@ -92,17 +93,19 @@ struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id,
continue;
buf->bytesused = bytesused;
/* the transport buffers are handled differently,
- so there is no need to move them to the full queue */
- if (s->type == CX18_ENC_STREAM_TYPE_TS)
- return buf;
- s->q_free.buffers--;
- s->q_free.length -= s->buf_size;
- s->q_full.buffers++;
- s->q_full.length += s->buf_size;
- s->q_full.bytesused += buf->bytesused;
- list_move_tail(&buf->list, &s->q_full.list);
+ they are not moved to the full queue */
+ if (s->type != CX18_ENC_STREAM_TYPE_TS) {
+ s->q_free.buffers--;
+ s->q_free.length -= s->buf_size;
+ s->q_full.buffers++;
+ s->q_full.length += s->buf_size;
+ s->q_full.bytesused += buf->bytesused;
+ list_move_tail(&buf->list, &s->q_full.list);
+ }
+ spin_unlock(&s->qlock);
return buf;
}
+ spin_unlock(&s->qlock);
CX18_ERR("Cannot find buffer %d for stream %s\n", id, s->name);
return NULL;
}
diff --git a/linux/drivers/media/video/cx18/cx18-queue.h b/linux/drivers/media/video/cx18/cx18-queue.h
index 91423b986..7f93bb13c 100644
--- a/linux/drivers/media/video/cx18/cx18-queue.h
+++ b/linux/drivers/media/video/cx18/cx18-queue.h
@@ -46,7 +46,7 @@ void cx18_queue_init(struct cx18_queue *q);
void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf,
struct cx18_queue *q);
struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q);
-struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id,
+struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id,
u32 bytesused);
void cx18_flush_queues(struct cx18_stream *s);
diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c
index 3eedae726..911a97ce3 100644
--- a/linux/drivers/media/video/cx18/cx18-streams.c
+++ b/linux/drivers/media/video/cx18/cx18-streams.c
@@ -187,9 +187,6 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
return -ENOMEM;
}
- s->v4l2dev->type =
- VID_TYPE_CAPTURE | VID_TYPE_TUNER | VID_TYPE_TELETEXT |
- VID_TYPE_CLIPPING | VID_TYPE_SCALES | VID_TYPE_MPEG_ENCODER;
snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "cx18-%d",
cx->num);