Commit 7cf901b3 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'media/v4.16-3' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

Pull media fixes from Mauro Carvalho Chehab:

  - some build fixes with randconfigs

  - an m88ds3103 fix to prevent an OOPS if the chip doesn't provide the
    right version during probe (with can happen if the hardware hangs)

  - a potential out of array bounds reference in tvp5150

  - some fixes and improvements in the DVB memory mapped API (added for
    kernel 4.16)

* tag 'media/v4.16-3' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media:
  media: vb2: Makefile: place vb2-trace together with vb2-core
  media: Don't let tvp5150_get_vbi() go out of vbi_ram_default array
  media: dvb: update buffer mmaped flags and frame counter
  media: dvb: add continuity error indicators for memory mapped buffers
  media: dmxdev: Fix the logic that enables DMA mmap support
  media: dmxdev: fix error code for invalid ioctls
  media: m88ds3103: don't call a non-initalized function
  media: au0828: add VIDEO_V4L2 dependency
  media: dvb: fix DVB_MMAP dependency
  media: dvb: fix DVB_MMAP symbol name
  media: videobuf2: fix build issues with vb2-trace
  media: videobuf2: Add VIDEOBUF2_V4L2 Kconfig option for VB2 V4L2 part
parents d6d0972a 7dbdd16a
...@@ -50,9 +50,15 @@ replace typedef dmx_filter_t :c:type:`dmx_filter` ...@@ -50,9 +50,15 @@ replace typedef dmx_filter_t :c:type:`dmx_filter`
replace typedef dmx_pes_type_t :c:type:`dmx_pes_type` replace typedef dmx_pes_type_t :c:type:`dmx_pes_type`
replace typedef dmx_input_t :c:type:`dmx_input` replace typedef dmx_input_t :c:type:`dmx_input`
ignore symbol DMX_OUT_DECODER replace symbol DMX_BUFFER_FLAG_HAD_CRC32_DISCARD :c:type:`dmx_buffer_flags`
ignore symbol DMX_OUT_TAP replace symbol DMX_BUFFER_FLAG_TEI :c:type:`dmx_buffer_flags`
ignore symbol DMX_OUT_TS_TAP replace symbol DMX_BUFFER_PKT_COUNTER_MISMATCH :c:type:`dmx_buffer_flags`
ignore symbol DMX_OUT_TSDEMUX_TAP replace symbol DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED :c:type:`dmx_buffer_flags`
replace symbol DMX_BUFFER_FLAG_DISCONTINUITY_INDICATOR :c:type:`dmx_buffer_flags`
replace symbol DMX_OUT_DECODER :c:type:`dmx_output`
replace symbol DMX_OUT_TAP :c:type:`dmx_output`
replace symbol DMX_OUT_TS_TAP :c:type:`dmx_output`
replace symbol DMX_OUT_TSDEMUX_TAP :c:type:`dmx_output`
replace ioctl DMX_DQBUF dmx_qbuf replace ioctl DMX_DQBUF dmx_qbuf
...@@ -51,9 +51,10 @@ out to disk. Buffers remain locked until dequeued, until the ...@@ -51,9 +51,10 @@ out to disk. Buffers remain locked until dequeued, until the
the device is closed. the device is closed.
Applications call the ``DMX_DQBUF`` ioctl to dequeue a filled Applications call the ``DMX_DQBUF`` ioctl to dequeue a filled
(capturing) buffer from the driver's outgoing queue. They just set the ``reserved`` field array to zero. When ``DMX_DQBUF`` is called with a (capturing) buffer from the driver's outgoing queue.
pointer to this structure, the driver fills the remaining fields or They just set the ``index`` field withe the buffer ID to be queued.
returns an error code. When ``DMX_DQBUF`` is called with a pointer to struct :c:type:`dmx_buffer`,
the driver fills the remaining fields or returns an error code.
By default ``DMX_DQBUF`` blocks when no buffer is in the outgoing By default ``DMX_DQBUF`` blocks when no buffer is in the outgoing
queue. When the ``O_NONBLOCK`` flag was given to the queue. When the ``O_NONBLOCK`` flag was given to the
......
...@@ -147,6 +147,8 @@ config DVB_CORE ...@@ -147,6 +147,8 @@ config DVB_CORE
config DVB_MMAP config DVB_MMAP
bool "Enable DVB memory-mapped API (EXPERIMENTAL)" bool "Enable DVB memory-mapped API (EXPERIMENTAL)"
depends on DVB_CORE depends on DVB_CORE
depends on VIDEO_V4L2=y || VIDEO_V4L2=DVB_CORE
select VIDEOBUF2_VMALLOC
default n default n
help help
This option enables DVB experimental memory-mapped API, with This option enables DVB experimental memory-mapped API, with
......
...@@ -3,6 +3,9 @@ config VIDEOBUF2_CORE ...@@ -3,6 +3,9 @@ config VIDEOBUF2_CORE
select DMA_SHARED_BUFFER select DMA_SHARED_BUFFER
tristate tristate
config VIDEOBUF2_V4L2
tristate
config VIDEOBUF2_MEMOPS config VIDEOBUF2_MEMOPS
tristate tristate
select FRAME_VECTOR select FRAME_VECTOR
......
# SPDX-License-Identifier: GPL-2.0
videobuf2-common-objs := videobuf2-core.o
obj-$(CONFIG_VIDEOBUF2_CORE) += videobuf2-core.o videobuf2-v4l2.o ifeq ($(CONFIG_TRACEPOINTS),y)
videobuf2-common-objs += vb2-trace.o
endif
obj-$(CONFIG_VIDEOBUF2_CORE) += videobuf2-common.o
obj-$(CONFIG_VIDEOBUF2_V4L2) += videobuf2-v4l2.o
obj-$(CONFIG_VIDEOBUF2_MEMOPS) += videobuf2-memops.o obj-$(CONFIG_VIDEOBUF2_MEMOPS) += videobuf2-memops.o
obj-$(CONFIG_VIDEOBUF2_VMALLOC) += videobuf2-vmalloc.o obj-$(CONFIG_VIDEOBUF2_VMALLOC) += videobuf2-vmalloc.o
obj-$(CONFIG_VIDEOBUF2_DMA_CONTIG) += videobuf2-dma-contig.o obj-$(CONFIG_VIDEOBUF2_DMA_CONTIG) += videobuf2-dma-contig.o
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# #
dvb-net-$(CONFIG_DVB_NET) := dvb_net.o dvb-net-$(CONFIG_DVB_NET) := dvb_net.o
dvb-vb2-$(CONFIG_DVB_MMSP) := dvb_vb2.o dvb-vb2-$(CONFIG_DVB_MMAP) := dvb_vb2.o
dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o \ dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o \
dvb_ca_en50221.o dvb_frontend.o \ dvb_ca_en50221.o dvb_frontend.o \
......
...@@ -128,11 +128,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) ...@@ -128,11 +128,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
struct dmxdev *dmxdev = dvbdev->priv; struct dmxdev *dmxdev = dvbdev->priv;
struct dmx_frontend *front; struct dmx_frontend *front;
#ifndef DVB_MMAP
bool need_ringbuffer = false; bool need_ringbuffer = false;
#else
const bool need_ringbuffer = true;
#endif
dprintk("%s\n", __func__); dprintk("%s\n", __func__);
...@@ -144,17 +140,31 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) ...@@ -144,17 +140,31 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
return -ENODEV; return -ENODEV;
} }
#ifndef DVB_MMAP dmxdev->may_do_mmap = 0;
/*
* The logic here is a little tricky due to the ifdef.
*
* The ringbuffer is used for both read and mmap.
*
* It is not needed, however, on two situations:
* - Write devices (access with O_WRONLY);
* - For duplex device nodes, opened with O_RDWR.
*/
if ((file->f_flags & O_ACCMODE) == O_RDONLY) if ((file->f_flags & O_ACCMODE) == O_RDONLY)
need_ringbuffer = true; need_ringbuffer = true;
#else else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
if ((file->f_flags & O_ACCMODE) == O_RDWR) {
if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) { if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) {
#ifdef CONFIG_DVB_MMAP
dmxdev->may_do_mmap = 1;
need_ringbuffer = true;
#else
mutex_unlock(&dmxdev->mutex); mutex_unlock(&dmxdev->mutex);
return -EOPNOTSUPP; return -EOPNOTSUPP;
#endif
} }
} }
#endif
if (need_ringbuffer) { if (need_ringbuffer) {
void *mem; void *mem;
...@@ -169,6 +179,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) ...@@ -169,6 +179,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
return -ENOMEM; return -ENOMEM;
} }
dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE); dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
if (dmxdev->may_do_mmap)
dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr", dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr",
file->f_flags & O_NONBLOCK); file->f_flags & O_NONBLOCK);
dvbdev->readers--; dvbdev->readers--;
...@@ -200,11 +211,6 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) ...@@ -200,11 +211,6 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
{ {
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
struct dmxdev *dmxdev = dvbdev->priv; struct dmxdev *dmxdev = dvbdev->priv;
#ifndef DVB_MMAP
bool need_ringbuffer = false;
#else
const bool need_ringbuffer = true;
#endif
mutex_lock(&dmxdev->mutex); mutex_lock(&dmxdev->mutex);
...@@ -213,15 +219,14 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) ...@@ -213,15 +219,14 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
dmxdev->demux->connect_frontend(dmxdev->demux, dmxdev->demux->connect_frontend(dmxdev->demux,
dmxdev->dvr_orig_fe); dmxdev->dvr_orig_fe);
} }
#ifndef DVB_MMAP
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
need_ringbuffer = true;
#endif
if (need_ringbuffer) { if (((file->f_flags & O_ACCMODE) == O_RDONLY) ||
dmxdev->may_do_mmap) {
if (dmxdev->may_do_mmap) {
if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx)) if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx))
dvb_vb2_stream_off(&dmxdev->dvr_vb2_ctx); dvb_vb2_stream_off(&dmxdev->dvr_vb2_ctx);
dvb_vb2_release(&dmxdev->dvr_vb2_ctx); dvb_vb2_release(&dmxdev->dvr_vb2_ctx);
}
dvbdev->readers++; dvbdev->readers++;
if (dmxdev->dvr_buffer.data) { if (dmxdev->dvr_buffer.data) {
void *mem = dmxdev->dvr_buffer.data; void *mem = dmxdev->dvr_buffer.data;
...@@ -380,7 +385,8 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter) ...@@ -380,7 +385,8 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len, const u8 *buffer2, size_t buffer2_len,
struct dmx_section_filter *filter) struct dmx_section_filter *filter,
u32 *buffer_flags)
{ {
struct dmxdev_filter *dmxdevfilter = filter->priv; struct dmxdev_filter *dmxdevfilter = filter->priv;
int ret; int ret;
...@@ -399,10 +405,12 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, ...@@ -399,10 +405,12 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
dprintk("section callback %*ph\n", 6, buffer1); dprintk("section callback %*ph\n", 6, buffer1);
if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) { if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) {
ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx, ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx,
buffer1, buffer1_len); buffer1, buffer1_len,
buffer_flags);
if (ret == buffer1_len) if (ret == buffer1_len)
ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx, ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx,
buffer2, buffer2_len); buffer2, buffer2_len,
buffer_flags);
} else { } else {
ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer,
buffer1, buffer1_len); buffer1, buffer1_len);
...@@ -422,11 +430,12 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, ...@@ -422,11 +430,12 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len, const u8 *buffer2, size_t buffer2_len,
struct dmx_ts_feed *feed) struct dmx_ts_feed *feed,
u32 *buffer_flags)
{ {
struct dmxdev_filter *dmxdevfilter = feed->priv; struct dmxdev_filter *dmxdevfilter = feed->priv;
struct dvb_ringbuffer *buffer; struct dvb_ringbuffer *buffer;
#ifdef DVB_MMAP #ifdef CONFIG_DVB_MMAP
struct dvb_vb2_ctx *ctx; struct dvb_vb2_ctx *ctx;
#endif #endif
int ret; int ret;
...@@ -440,20 +449,22 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, ...@@ -440,20 +449,22 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
if (dmxdevfilter->params.pes.output == DMX_OUT_TAP || if (dmxdevfilter->params.pes.output == DMX_OUT_TAP ||
dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) { dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) {
buffer = &dmxdevfilter->buffer; buffer = &dmxdevfilter->buffer;
#ifdef DVB_MMAP #ifdef CONFIG_DVB_MMAP
ctx = &dmxdevfilter->vb2_ctx; ctx = &dmxdevfilter->vb2_ctx;
#endif #endif
} else { } else {
buffer = &dmxdevfilter->dev->dvr_buffer; buffer = &dmxdevfilter->dev->dvr_buffer;
#ifdef DVB_MMAP #ifdef CONFIG_DVB_MMAP
ctx = &dmxdevfilter->dev->dvr_vb2_ctx; ctx = &dmxdevfilter->dev->dvr_vb2_ctx;
#endif #endif
} }
if (dvb_vb2_is_streaming(ctx)) { if (dvb_vb2_is_streaming(ctx)) {
ret = dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len); ret = dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len,
buffer_flags);
if (ret == buffer1_len) if (ret == buffer1_len)
ret = dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len); ret = dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len,
buffer_flags);
} else { } else {
if (buffer->error) { if (buffer->error) {
spin_unlock(&dmxdevfilter->dev->lock); spin_unlock(&dmxdevfilter->dev->lock);
...@@ -802,6 +813,12 @@ static int dvb_demux_open(struct inode *inode, struct file *file) ...@@ -802,6 +813,12 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
mutex_init(&dmxdevfilter->mutex); mutex_init(&dmxdevfilter->mutex);
file->private_data = dmxdevfilter; file->private_data = dmxdevfilter;
#ifdef CONFIG_DVB_MMAP
dmxdev->may_do_mmap = 1;
#else
dmxdev->may_do_mmap = 0;
#endif
dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192); dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
dvb_vb2_init(&dmxdevfilter->vb2_ctx, "demux_filter", dvb_vb2_init(&dmxdevfilter->vb2_ctx, "demux_filter",
file->f_flags & O_NONBLOCK); file->f_flags & O_NONBLOCK);
...@@ -1111,7 +1128,7 @@ static int dvb_demux_do_ioctl(struct file *file, ...@@ -1111,7 +1128,7 @@ static int dvb_demux_do_ioctl(struct file *file,
mutex_unlock(&dmxdevfilter->mutex); mutex_unlock(&dmxdevfilter->mutex);
break; break;
#ifdef DVB_MMAP #ifdef CONFIG_DVB_MMAP
case DMX_REQBUFS: case DMX_REQBUFS:
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
mutex_unlock(&dmxdev->mutex); mutex_unlock(&dmxdev->mutex);
...@@ -1160,7 +1177,7 @@ static int dvb_demux_do_ioctl(struct file *file, ...@@ -1160,7 +1177,7 @@ static int dvb_demux_do_ioctl(struct file *file,
break; break;
#endif #endif
default: default:
ret = -EINVAL; ret = -ENOTTY;
break; break;
} }
mutex_unlock(&dmxdev->mutex); mutex_unlock(&dmxdev->mutex);
...@@ -1199,13 +1216,16 @@ static __poll_t dvb_demux_poll(struct file *file, poll_table *wait) ...@@ -1199,13 +1216,16 @@ static __poll_t dvb_demux_poll(struct file *file, poll_table *wait)
return mask; return mask;
} }
#ifdef DVB_MMAP #ifdef CONFIG_DVB_MMAP
static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma) static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma)
{ {
struct dmxdev_filter *dmxdevfilter = file->private_data; struct dmxdev_filter *dmxdevfilter = file->private_data;
struct dmxdev *dmxdev = dmxdevfilter->dev; struct dmxdev *dmxdev = dmxdevfilter->dev;
int ret; int ret;
if (!dmxdev->may_do_mmap)
return -ENOTTY;
if (mutex_lock_interruptible(&dmxdev->mutex)) if (mutex_lock_interruptible(&dmxdev->mutex))
return -ERESTARTSYS; return -ERESTARTSYS;
...@@ -1249,7 +1269,7 @@ static const struct file_operations dvb_demux_fops = { ...@@ -1249,7 +1269,7 @@ static const struct file_operations dvb_demux_fops = {
.release = dvb_demux_release, .release = dvb_demux_release,
.poll = dvb_demux_poll, .poll = dvb_demux_poll,
.llseek = default_llseek, .llseek = default_llseek,
#ifdef DVB_MMAP #ifdef CONFIG_DVB_MMAP
.mmap = dvb_demux_mmap, .mmap = dvb_demux_mmap,
#endif #endif
}; };
...@@ -1280,7 +1300,7 @@ static int dvb_dvr_do_ioctl(struct file *file, ...@@ -1280,7 +1300,7 @@ static int dvb_dvr_do_ioctl(struct file *file,
ret = dvb_dvr_set_buffer_size(dmxdev, arg); ret = dvb_dvr_set_buffer_size(dmxdev, arg);
break; break;
#ifdef DVB_MMAP #ifdef CONFIG_DVB_MMAP
case DMX_REQBUFS: case DMX_REQBUFS:
ret = dvb_vb2_reqbufs(&dmxdev->dvr_vb2_ctx, parg); ret = dvb_vb2_reqbufs(&dmxdev->dvr_vb2_ctx, parg);
break; break;
...@@ -1304,7 +1324,7 @@ static int dvb_dvr_do_ioctl(struct file *file, ...@@ -1304,7 +1324,7 @@ static int dvb_dvr_do_ioctl(struct file *file,
break; break;
#endif #endif
default: default:
ret = -EINVAL; ret = -ENOTTY;
break; break;
} }
mutex_unlock(&dmxdev->mutex); mutex_unlock(&dmxdev->mutex);
...@@ -1322,11 +1342,6 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait) ...@@ -1322,11 +1342,6 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait)
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
struct dmxdev *dmxdev = dvbdev->priv; struct dmxdev *dmxdev = dvbdev->priv;
__poll_t mask = 0; __poll_t mask = 0;
#ifndef DVB_MMAP
bool need_ringbuffer = false;
#else
const bool need_ringbuffer = true;
#endif
dprintk("%s\n", __func__); dprintk("%s\n", __func__);
...@@ -1337,11 +1352,8 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait) ...@@ -1337,11 +1352,8 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait)
poll_wait(file, &dmxdev->dvr_buffer.queue, wait); poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
#ifndef DVB_MMAP if (((file->f_flags & O_ACCMODE) == O_RDONLY) ||
if ((file->f_flags & O_ACCMODE) == O_RDONLY) dmxdev->may_do_mmap) {
need_ringbuffer = true;
#endif
if (need_ringbuffer) {
if (dmxdev->dvr_buffer.error) if (dmxdev->dvr_buffer.error)
mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI | EPOLLERR); mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI | EPOLLERR);
...@@ -1353,13 +1365,16 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait) ...@@ -1353,13 +1365,16 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait)
return mask; return mask;
} }
#ifdef DVB_MMAP #ifdef CONFIG_DVB_MMAP
static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma) static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma)
{ {
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
struct dmxdev *dmxdev = dvbdev->priv; struct dmxdev *dmxdev = dvbdev->priv;
int ret; int ret;
if (!dmxdev->may_do_mmap)
return -ENOTTY;
if (dmxdev->exit) if (dmxdev->exit)
return -ENODEV; return -ENODEV;
...@@ -1381,7 +1396,7 @@ static const struct file_operations dvb_dvr_fops = { ...@@ -1381,7 +1396,7 @@ static const struct file_operations dvb_dvr_fops = {
.release = dvb_dvr_release, .release = dvb_dvr_release,
.poll = dvb_dvr_poll, .poll = dvb_dvr_poll,
.llseek = default_llseek, .llseek = default_llseek,
#ifdef DVB_MMAP #ifdef CONFIG_DVB_MMAP
.mmap = dvb_dvr_mmap, .mmap = dvb_dvr_mmap,
#endif #endif
}; };
......
...@@ -55,6 +55,17 @@ MODULE_PARM_DESC(dvb_demux_feed_err_pkts, ...@@ -55,6 +55,17 @@ MODULE_PARM_DESC(dvb_demux_feed_err_pkts,
dprintk(x); \ dprintk(x); \
} while (0) } while (0)
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
# define dprintk_sect_loss(x...) dprintk(x)
#else
# define dprintk_sect_loss(x...)
#endif
#define set_buf_flags(__feed, __flag) \
do { \
(__feed)->buffer_flags |= (__flag); \
} while (0)
/****************************************************************************** /******************************************************************************
* static inlined helper functions * static inlined helper functions
******************************************************************************/ ******************************************************************************/
...@@ -104,31 +115,30 @@ static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed, ...@@ -104,31 +115,30 @@ static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
{ {
int count = payload(buf); int count = payload(buf);
int p; int p;
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
int ccok; int ccok;
u8 cc; u8 cc;
#endif
if (count == 0) if (count == 0)
return -1; return -1;
p = 188 - count; p = 188 - count;
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
cc = buf[3] & 0x0f; cc = buf[3] & 0x0f;
ccok = ((feed->cc + 1) & 0x0f) == cc; ccok = ((feed->cc + 1) & 0x0f) == cc;
feed->cc = cc; feed->cc = cc;
if (!ccok) if (!ccok) {
dprintk("missed packet: %d instead of %d!\n", set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
dprintk_sect_loss("missed packet: %d instead of %d!\n",
cc, (feed->cc + 1) & 0x0f); cc, (feed->cc + 1) & 0x0f);
#endif }
if (buf[1] & 0x40) // PUSI ? if (buf[1] & 0x40) // PUSI ?
feed->peslen = 0xfffa; feed->peslen = 0xfffa;
feed->peslen += count; feed->peslen += count;
return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts); return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts,
&feed->buffer_flags);
} }
static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed, static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
...@@ -150,7 +160,7 @@ static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed, ...@@ -150,7 +160,7 @@ static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
return 0; return 0;
return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen, return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen,
NULL, 0, &f->filter); NULL, 0, &f->filter, &feed->buffer_flags);
} }
static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed) static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed)
...@@ -169,9 +179,11 @@ static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed) ...@@ -169,9 +179,11 @@ static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed)
if (sec->check_crc) { if (sec->check_crc) {
section_syntax_indicator = ((sec->secbuf[1] & 0x80) != 0); section_syntax_indicator = ((sec->secbuf[1] & 0x80) != 0);
if (section_syntax_indicator && if (section_syntax_indicator &&
demux->check_crc32(feed, sec->secbuf, sec->seclen)) demux->check_crc32(feed, sec->secbuf, sec->seclen)) {
set_buf_flags(feed, DMX_BUFFER_FLAG_HAD_CRC32_DISCARD);
return -1; return -1;
} }
}
do { do {
if (dvb_dmx_swfilter_sectionfilter(feed, f) < 0) if (dvb_dmx_swfilter_sectionfilter(feed, f) < 0)
...@@ -187,7 +199,6 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed) ...@@ -187,7 +199,6 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
{ {
struct dmx_section_feed *sec = &feed->feed.sec; struct dmx_section_feed *sec = &feed->feed.sec;
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
if (sec->secbufp < sec->tsfeedp) { if (sec->secbufp < sec->tsfeedp) {
int n = sec->tsfeedp - sec->secbufp; int n = sec->tsfeedp - sec->secbufp;
...@@ -197,12 +208,13 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed) ...@@ -197,12 +208,13 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
* but just first and last. * but just first and last.
*/ */
if (sec->secbuf[0] != 0xff || sec->secbuf[n - 1] != 0xff) { if (sec->secbuf[0] != 0xff || sec->secbuf[n - 1] != 0xff) {
dprintk("section ts padding loss: %d/%d\n", set_buf_flags(feed,
DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
dprintk_sect_loss("section ts padding loss: %d/%d\n",
n, sec->tsfeedp); n, sec->tsfeedp);
dprintk("pad data: %*ph\n", n, sec->secbuf); dprintk_sect_loss("pad data: %*ph\n", n, sec->secbuf);
} }
} }
#endif
sec->tsfeedp = sec->secbufp = sec->seclen = 0; sec->tsfeedp = sec->secbufp = sec->seclen = 0;
sec->secbuf = sec->secbuf_base; sec->secbuf = sec->secbuf_base;
...@@ -237,11 +249,10 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, ...@@ -237,11 +249,10 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
return 0; return 0;
if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) { if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) {
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
dprintk("section buffer full loss: %d/%d\n", dprintk_sect_loss("section buffer full loss: %d/%d\n",
sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE, sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE,
DMX_MAX_SECFEED_SIZE); DMX_MAX_SECFEED_SIZE);
#endif
len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp; len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp;
} }
...@@ -269,12 +280,13 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, ...@@ -269,12 +280,13 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
sec->seclen = seclen; sec->seclen = seclen;
sec->crc_val = ~0; sec->crc_val = ~0;
/* dump [secbuf .. secbuf+seclen) */ /* dump [secbuf .. secbuf+seclen) */
if (feed->pusi_seen) if (feed->pusi_seen) {
dvb_dmx_swfilter_section_feed(feed); dvb_dmx_swfilter_section_feed(feed);
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG } else {
else set_buf_flags(feed,
dprintk("pusi not seen, discarding section data\n"); DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
#endif dprintk_sect_loss("pusi not seen, discarding section data\n");
}
sec->secbufp += seclen; /* secbufp and secbuf moving together is */ sec->secbufp += seclen; /* secbufp and secbuf moving together is */
sec->secbuf += seclen; /* redundant but saves pointer arithmetic */ sec->secbuf += seclen; /* redundant but saves pointer arithmetic */
} }
...@@ -307,18 +319,22 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, ...@@ -307,18 +319,22 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
} }
if (!ccok || dc_i) { if (!ccok || dc_i) {
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG if (dc_i) {
if (dc_i) set_buf_flags(feed,
dprintk("%d frame with disconnect indicator\n", DMX_BUFFER_FLAG_DISCONTINUITY_INDICATOR);
dprintk_sect_loss("%d frame with disconnect indicator\n",
cc); cc);
else } else {
dprintk("discontinuity: %d instead of %d. %d bytes lost\n", set_buf_flags(feed,
DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
dprintk_sect_loss("discontinuity: %d instead of %d. %d bytes lost\n",
cc, (feed->cc + 1) & 0x0f, count + 4); cc, (feed->cc + 1) & 0x0f, count + 4);
}
/* /*
* those bytes under sume circumstances will again be reported * those bytes under some circumstances will again be reported
* in the following dvb_dmx_swfilter_section_new * in the following dvb_dmx_swfilter_section_new
*/ */
#endif
/* /*
* Discontinuity detected. Reset pusi_seen to * Discontinuity detected. Reset pusi_seen to
* stop feeding of suspicious data until next PUSI=1 arrives * stop feeding of suspicious data until next PUSI=1 arrives
...@@ -326,6 +342,7 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, ...@@ -326,6 +342,7 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
* FIXME: does it make sense if the MPEG-TS is the one * FIXME: does it make sense if the MPEG-TS is the one
* reporting discontinuity? * reporting discontinuity?
*/ */
feed->pusi_seen = false; feed->pusi_seen = false;
dvb_dmx_swfilter_section_new(feed); dvb_dmx_swfilter_section_new(feed);
} }
...@@ -345,11 +362,11 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, ...@@ -345,11 +362,11 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
dvb_dmx_swfilter_section_new(feed); dvb_dmx_swfilter_section_new(feed);
dvb_dmx_swfilter_section_copy_dump(feed, after, dvb_dmx_swfilter_section_copy_dump(feed, after,
after_len); after_len);
} else if (count > 0) {
set_buf_flags(feed,
DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
dprintk_sect_loss("PUSI=1 but %d bytes lost\n", count);
} }
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
else if (count > 0)
dprintk("PUSI=1 but %d bytes lost\n", count);
#endif
} else { } else {
/* PUSI=0 (is not set), no section boundary */ /* PUSI=0 (is not set), no section boundary */
dvb_dmx_swfilter_section_copy_dump(feed, &buf[p], count); dvb_dmx_swfilter_section_copy_dump(feed, &buf[p], count);
...@@ -369,7 +386,8 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, ...@@ -369,7 +386,8 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
if (feed->ts_type & TS_PAYLOAD_ONLY) if (feed->ts_type & TS_PAYLOAD_ONLY)
dvb_dmx_swfilter_payload(feed, buf); dvb_dmx_swfilter_payload(feed, buf);
else else
feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts); feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts,
&feed->buffer_flags);
} }
/* Used only on full-featured devices */ /* Used only on full-featured devices */
if (feed->ts_type & TS_DECODER) if (feed->ts_type & TS_DECODER)
...@@ -430,6 +448,11 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) ...@@ -430,6 +448,11 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
} }
if (buf[1] & 0x80) { if (buf[1] & 0x80) {
list_for_each_entry(feed, &demux->feed_list, list_head) {
if ((feed->pid != pid) && (feed->pid != 0x2000))
continue;
set_buf_flags(feed, DMX_BUFFER_FLAG_TEI);
}
dprintk_tscheck("TEI detected. PID=0x%x data1=0x%x\n", dprintk_tscheck("TEI detected. PID=0x%x data1=0x%x\n",
pid, buf[1]); pid, buf[1]);
/* data in this packet can't be trusted - drop it unless /* data in this packet can't be trusted - drop it unless
...@@ -445,6 +468,13 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) ...@@ -445,6 +468,13 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
(demux->cnt_storage[pid] + 1) & 0xf; (demux->cnt_storage[pid] + 1) & 0xf;
if ((buf[3] & 0xf) != demux->cnt_storage[pid]) { if ((buf[3] & 0xf) != demux->cnt_storage[pid]) {
list_for_each_entry(feed, &demux->feed_list, list_head) {
if ((feed->pid != pid) && (feed->pid != 0x2000))
continue;
set_buf_flags(feed,
DMX_BUFFER_PKT_COUNTER_MISMATCH);
}
dprintk_tscheck("TS packet counter mismatch. PID=0x%x expected 0x%x got 0x%x\n", dprintk_tscheck("TS packet counter mismatch. PID=0x%x expected 0x%x got 0x%x\n",
pid, demux->cnt_storage[pid], pid, demux->cnt_storage[pid],
buf[3] & 0xf); buf[3] & 0xf);
...@@ -466,7 +496,8 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) ...@@ -466,7 +496,8 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
if (feed->pid == pid) if (feed->pid == pid)
dvb_dmx_swfilter_packet_type(feed, buf); dvb_dmx_swfilter_packet_type(feed, buf);
else if (feed->pid == 0x2000) else if (feed->pid == 0x2000)
feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts); feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts,
&feed->buffer_flags);
} }
} }
...@@ -585,7 +616,8 @@ void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, size_t count) ...@@ -585,7 +616,8 @@ void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, size_t count)
spin_lock_irqsave(&demux->lock, flags); spin_lock_irqsave(&demux->lock, flags);
demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts); demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts,
&demux->feed->buffer_flags);
spin_unlock_irqrestore(&demux->lock, flags); spin_unlock_irqrestore(&demux->lock, flags);
} }
...@@ -785,6 +817,7 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx, ...@@ -785,6 +817,7 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx,
feed->demux = demux; feed->demux = demux;
feed->pid = 0xffff; feed->pid = 0xffff;
feed->peslen = 0xfffa; feed->peslen = 0xfffa;
feed->buffer_flags = 0;
(*ts_feed) = &feed->feed.ts; (*ts_feed) = &feed->feed.ts;
(*ts_feed)->parent = dmx; (*ts_feed)->parent = dmx;
...@@ -1042,6 +1075,7 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux, ...@@ -1042,6 +1075,7 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
dvbdmxfeed->cb.sec = callback; dvbdmxfeed->cb.sec = callback;
dvbdmxfeed->demux = dvbdmx; dvbdmxfeed->demux = dvbdmx;
dvbdmxfeed->pid = 0xffff; dvbdmxfeed->pid = 0xffff;
dvbdmxfeed->buffer_flags = 0;
dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base;
dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0; dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0;
dvbdmxfeed->feed.sec.tsfeedp = 0; dvbdmxfeed->feed.sec.tsfeedp = 0;
......
...@@ -883,7 +883,8 @@ static void dvb_net_ule(struct net_device *dev, const u8 *buf, size_t buf_len) ...@@ -883,7 +883,8 @@ static void dvb_net_ule(struct net_device *dev, const u8 *buf, size_t buf_len)
static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len, static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len, const u8 *buffer2, size_t buffer2_len,
struct dmx_ts_feed *feed) struct dmx_ts_feed *feed,
u32 *buffer_flags)
{ {
struct net_device *dev = feed->priv; struct net_device *dev = feed->priv;
...@@ -992,7 +993,7 @@ static void dvb_net_sec(struct net_device *dev, ...@@ -992,7 +993,7 @@ static void dvb_net_sec(struct net_device *dev,
static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len, static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len, const u8 *buffer2, size_t buffer2_len,
struct dmx_section_filter *filter) struct dmx_section_filter *filter, u32 *buffer_flags)
{ {
struct net_device *dev = filter->priv; struct net_device *dev = filter->priv;
......
...@@ -256,7 +256,8 @@ int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx) ...@@ -256,7 +256,8 @@ int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx)
} }
int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx, int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx,
const unsigned char *src, int len) const unsigned char *src, int len,
enum dmx_buffer_flags *buffer_flags)
{ {
unsigned long flags = 0; unsigned long flags = 0;
void *vbuf = NULL; void *vbuf = NULL;
...@@ -264,15 +265,17 @@ int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx, ...@@ -264,15 +265,17 @@ int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx,
unsigned char *psrc = (unsigned char *)src; unsigned char *psrc = (unsigned char *)src;
int ll = 0; int ll = 0;
dprintk(3, "[%s] %d bytes are rcvd\n", ctx->name, len); /*
if (!src) { * normal case: This func is called twice from demux driver
dprintk(3, "[%s]:NULL pointer src\n", ctx->name); * one with valid src pointer, second time with NULL pointer
/**normal case: This func is called twice from demux driver
* once with valid src pointer, second time with NULL pointer
*/ */
if (!src || !len)
return 0; return 0;
}
spin_lock_irqsave(&ctx->slock, flags); spin_lock_irqsave(&ctx->slock, flags);
if (buffer_flags && *buffer_flags) {
ctx->flags |= *buffer_flags;
*buffer_flags = 0;
}
while (todo) { while (todo) {
if (!ctx->buf) { if (!ctx->buf) {
if (list_empty(&ctx->dvb_q)) { if (list_empty(&ctx->dvb_q)) {
...@@ -395,6 +398,7 @@ int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b) ...@@ -395,6 +398,7 @@ int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b) int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
{ {
unsigned long flags;
int ret; int ret;
ret = vb2_core_dqbuf(&ctx->vb_q, &b->index, b, ctx->nonblocking); ret = vb2_core_dqbuf(&ctx->vb_q, &b->index, b, ctx->nonblocking);
...@@ -402,7 +406,16 @@ int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b) ...@@ -402,7 +406,16 @@ int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
dprintk(1, "[%s] errno=%d\n", ctx->name, ret); dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
return ret; return ret;
} }
dprintk(5, "[%s] index=%d\n", ctx->name, b->index);
spin_lock_irqsave(&ctx->slock, flags);
b->count = ctx->count++;
b->flags = ctx->flags;
ctx->flags = 0;
spin_unlock_irqrestore(&ctx->slock, flags);
dprintk(5, "[%s] index=%d, count=%d, flags=%d\n",
ctx->name, b->index, ctx->count, b->flags);
return 0; return 0;
} }
......
...@@ -1262,11 +1262,12 @@ static int m88ds3103_select(struct i2c_mux_core *muxc, u32 chan) ...@@ -1262,11 +1262,12 @@ static int m88ds3103_select(struct i2c_mux_core *muxc, u32 chan)
* New users must use I2C client binding directly! * New users must use I2C client binding directly!
*/ */
struct dvb_frontend *m88ds3103_attach(const struct m88ds3103_config *cfg, struct dvb_frontend *m88ds3103_attach(const struct m88ds3103_config *cfg,
struct i2c_adapter *i2c, struct i2c_adapter **tuner_i2c_adapter) struct i2c_adapter *i2c,
struct i2c_adapter **tuner_i2c_adapter)
{ {
struct i2c_client *client; struct i2c_client *client;
struct i2c_board_info board_info; struct i2c_board_info board_info;
struct m88ds3103_platform_data pdata; struct m88ds3103_platform_data pdata = {};
pdata.clk = cfg->clock; pdata.clk = cfg->clock;
pdata.i2c_wr_max = cfg->i2c_wr_max; pdata.i2c_wr_max = cfg->i2c_wr_max;
...@@ -1409,6 +1410,8 @@ static int m88ds3103_probe(struct i2c_client *client, ...@@ -1409,6 +1410,8 @@ static int m88ds3103_probe(struct i2c_client *client,
case M88DS3103_CHIP_ID: case M88DS3103_CHIP_ID:
break; break;
default: default:
ret = -ENODEV;
dev_err(&client->dev, "Unknown device. Chip_id=%02x\n", dev->chip_id);
goto err_kfree; goto err_kfree;
} }
......
...@@ -505,80 +505,77 @@ static struct i2c_vbi_ram_value vbi_ram_default[] = ...@@ -505,80 +505,77 @@ static struct i2c_vbi_ram_value vbi_ram_default[] =
/* FIXME: Current api doesn't handle all VBI types, those not /* FIXME: Current api doesn't handle all VBI types, those not
yet supported are placed under #if 0 */ yet supported are placed under #if 0 */
#if 0 #if 0
{0x010, /* Teletext, SECAM, WST System A */ [0] = {0x010, /* Teletext, SECAM, WST System A */
{V4L2_SLICED_TELETEXT_SECAM,6,23,1}, {V4L2_SLICED_TELETEXT_SECAM,6,23,1},
{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x26, { 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x26,
0xe6, 0xb4, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00 } 0xe6, 0xb4, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00 }
}, },
#endif #endif
{0x030, /* Teletext, PAL, WST System B */ [1] = {0x030, /* Teletext, PAL, WST System B */
{V4L2_SLICED_TELETEXT_B,6,22,1}, {V4L2_SLICED_TELETEXT_B,6,22,1},
{ 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x2b, { 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x2b,
0xa6, 0x72, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00 } 0xa6, 0x72, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00 }
}, },
#if 0 #if 0
{0x050, /* Teletext, PAL, WST System C */ [2] = {0x050, /* Teletext, PAL, WST System C */
{V4L2_SLICED_TELETEXT_PAL_C,6,22,1}, {V4L2_SLICED_TELETEXT_PAL_C,6,22,1},
{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22, { 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22,
0xa6, 0x98, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 } 0xa6, 0x98, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
}, },
{0x070, /* Teletext, NTSC, WST System B */ [3] = {0x070, /* Teletext, NTSC, WST System B */
{V4L2_SLICED_TELETEXT_NTSC_B,10,21,1}, {V4L2_SLICED_TELETEXT_NTSC_B,10,21,1},
{ 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x23, { 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x23,
0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 } 0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
}, },
{0x090, /* Tetetext, NTSC NABTS System C */ [4] = {0x090, /* Tetetext, NTSC NABTS System C */
{V4L2_SLICED_TELETEXT_NTSC_C,10,21,1}, {V4L2_SLICED_TELETEXT_NTSC_C,10,21,1},
{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22, { 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22,
0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x15, 0x00 } 0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x15, 0x00 }
}, },
{0x0b0, /* Teletext, NTSC-J, NABTS System D */ [5] = {0x0b0, /* Teletext, NTSC-J, NABTS System D */
{V4L2_SLICED_TELETEXT_NTSC_D,10,21,1}, {V4L2_SLICED_TELETEXT_NTSC_D,10,21,1},
{ 0xaa, 0xaa, 0xff, 0xff, 0xa7, 0x2e, 0x20, 0x23, { 0xaa, 0xaa, 0xff, 0xff, 0xa7, 0x2e, 0x20, 0x23,
0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 } 0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
}, },
{0x0d0, /* Closed Caption, PAL/SECAM */ [6] = {0x0d0, /* Closed Caption, PAL/SECAM */
{V4L2_SLICED_CAPTION_625,22,22,1}, {V4L2_SLICED_CAPTION_625,22,22,1},
{ 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02, { 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
0xa6, 0x7b, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 } 0xa6, 0x7b, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 }
}, },
#endif #endif
{0x0f0, /* Closed Caption, NTSC */ [7] = {0x0f0, /* Closed Caption, NTSC */
{V4L2_SLICED_CAPTION_525,21,21,1}, {V4L2_SLICED_CAPTION_525,21,21,1},
{ 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02, { 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
0x69, 0x8c, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 } 0x69, 0x8c, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 }
}, },
{0x110, /* Wide Screen Signal, PAL/SECAM */ [8] = {0x110, /* Wide Screen Signal, PAL/SECAM */
{V4L2_SLICED_WSS_625,23,23,1}, {V4L2_SLICED_WSS_625,23,23,1},
{ 0x5b, 0x55, 0xc5, 0xff, 0x00, 0x71, 0x6e, 0x42, { 0x5b, 0x55, 0xc5, 0xff, 0x00, 0x71, 0x6e, 0x42,
0xa6, 0xcd, 0x0f, 0x00, 0x00, 0x00, 0x3a, 0x00 } 0xa6, 0xcd, 0x0f, 0x00, 0x00, 0x00, 0x3a, 0x00 }
}, },
#if 0 #if 0
{0x130, /* Wide Screen Signal, NTSC C */ [9] = {0x130, /* Wide Screen Signal, NTSC C */
{V4L2_SLICED_WSS_525,20,20,1}, {V4L2_SLICED_WSS_525,20,20,1},
{ 0x38, 0x00, 0x3f, 0x00, 0x00, 0x71, 0x6e, 0x43, { 0x38, 0x00, 0x3f, 0x00, 0x00, 0x71, 0x6e, 0x43,
0x69, 0x7c, 0x08, 0x00, 0x00, 0x00, 0x39, 0x00 } 0x69, 0x7c, 0x08, 0x00, 0x00, 0x00, 0x39, 0x00 }
}, },
{0x150, /* Vertical Interval Timecode (VITC), PAL/SECAM */ [10] = {0x150, /* Vertical Interval Timecode (VITC), PAL/SECAM */
{V4l2_SLICED_VITC_625,6,22,0}, {V4l2_SLICED_VITC_625,6,22,0},
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49,
0xa6, 0x85, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 } 0xa6, 0x85, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 }
}, },
{0x170, /* Vertical Interval Timecode (VITC), NTSC */ [11] = {0x170, /* Vertical Interval Timecode (VITC), NTSC */
{V4l2_SLICED_VITC_525,10,20,0}, {V4l2_SLICED_VITC_525,10,20,0},
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49,
0x69, 0x94, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 } 0x69, 0x94, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 }
}, },
#endif #endif
{0x190, /* Video Program System (VPS), PAL */ [12] = {0x190, /* Video Program System (VPS), PAL */
{V4L2_SLICED_VPS,16,16,0}, {V4L2_SLICED_VPS,16,16,0},
{ 0xaa, 0xaa, 0xff, 0xff, 0xba, 0xce, 0x2b, 0x0d, { 0xaa, 0xaa, 0xff, 0xff, 0xba, 0xce, 0x2b, 0x0d,
0xa6, 0xda, 0x0b, 0x00, 0x00, 0x00, 0x60, 0x00 } 0xa6, 0xda, 0x0b, 0x00, 0x00, 0x00, 0x60, 0x00 }
}, },
/* 0x1d0 User programmable */ /* 0x1d0 User programmable */
/* End of struct */
{ (u16)-1 }
}; };
static int tvp5150_write_inittab(struct v4l2_subdev *sd, static int tvp5150_write_inittab(struct v4l2_subdev *sd,
...@@ -591,10 +588,10 @@ static int tvp5150_write_inittab(struct v4l2_subdev *sd, ...@@ -591,10 +588,10 @@ static int tvp5150_write_inittab(struct v4l2_subdev *sd,
return 0; return 0;
} }
static int tvp5150_vdp_init(struct v4l2_subdev *sd, static int tvp5150_vdp_init(struct v4l2_subdev *sd)
const struct i2c_vbi_ram_value *regs)
{ {
unsigned int i; unsigned int i;
int j;
/* Disable Full Field */ /* Disable Full Field */
tvp5150_write(sd, TVP5150_FULL_FIELD_ENA, 0); tvp5150_write(sd, TVP5150_FULL_FIELD_ENA, 0);
...@@ -604,14 +601,17 @@ static int tvp5150_vdp_init(struct v4l2_subdev *sd, ...@@ -604,14 +601,17 @@ static int tvp5150_vdp_init(struct v4l2_subdev *sd,
tvp5150_write(sd, i, 0xff); tvp5150_write(sd, i, 0xff);
/* Load Ram Table */ /* Load Ram Table */
while (regs->reg != (u16)-1) { for (j = 0; j < ARRAY_SIZE(vbi_ram_default); j++) {
const struct i2c_vbi_ram_value *regs = &vbi_ram_default[j];
if (!regs->type.vbi_type)
continue;
tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_HIGH, regs->reg >> 8); tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_HIGH, regs->reg >> 8);
tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_LOW, regs->reg); tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_LOW, regs->reg);
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
tvp5150_write(sd, TVP5150_VDP_CONF_RAM_DATA, regs->values[i]); tvp5150_write(sd, TVP5150_VDP_CONF_RAM_DATA, regs->values[i]);
regs++;
} }
return 0; return 0;
} }
...@@ -620,19 +620,23 @@ static int tvp5150_vdp_init(struct v4l2_subdev *sd, ...@@ -620,19 +620,23 @@ static int tvp5150_vdp_init(struct v4l2_subdev *sd,
static int tvp5150_g_sliced_vbi_cap(struct v4l2_subdev *sd, static int tvp5150_g_sliced_vbi_cap(struct v4l2_subdev *sd,
struct v4l2_sliced_vbi_cap *cap) struct v4l2_sliced_vbi_cap *cap)
{ {
const struct i2c_vbi_ram_value *regs = vbi_ram_default; int line, i;
int line;
dev_dbg_lvl(sd->dev, 1, debug, "g_sliced_vbi_cap\n"); dev_dbg_lvl(sd->dev, 1, debug, "g_sliced_vbi_cap\n");
memset(cap, 0, sizeof *cap); memset(cap, 0, sizeof *cap);
while (regs->reg != (u16)-1 ) { for (i = 0; i < ARRAY_SIZE(vbi_ram_default); i++) {
for (line=regs->type.ini_line;line<=regs->type.end_line;line++) { const struct i2c_vbi_ram_value *regs = &vbi_ram_default[i];
if (!regs->type.vbi_type)
continue;
for (line = regs->type.ini_line;
line <= regs->type.end_line;
line++) {
cap->service_lines[0][line] |= regs->type.vbi_type; cap->service_lines[0][line] |= regs->type.vbi_type;
} }
cap->service_set |= regs->type.vbi_type; cap->service_set |= regs->type.vbi_type;
regs++;
} }
return 0; return 0;
} }
...@@ -651,14 +655,13 @@ static int tvp5150_g_sliced_vbi_cap(struct v4l2_subdev *sd, ...@@ -651,14 +655,13 @@ static int tvp5150_g_sliced_vbi_cap(struct v4l2_subdev *sd,
* MSB = field2 * MSB = field2
*/ */
static int tvp5150_set_vbi(struct v4l2_subdev *sd, static int tvp5150_set_vbi(struct v4l2_subdev *sd,
const struct i2c_vbi_ram_value *regs,
unsigned int type,u8 flags, int line, unsigned int type,u8 flags, int line,
const int fields) const int fields)
{ {
struct tvp5150 *decoder = to_tvp5150(sd); struct tvp5150 *decoder = to_tvp5150(sd);
v4l2_std_id std = decoder->norm; v4l2_std_id std = decoder->norm;
u8 reg; u8 reg;
int pos = 0; int i, pos = 0;
if (std == V4L2_STD_ALL) { if (std == V4L2_STD_ALL) {
dev_err(sd->dev, "VBI can't be configured without knowing number of lines\n"); dev_err(sd->dev, "VBI can't be configured without knowing number of lines\n");
...@@ -671,19 +674,19 @@ static int tvp5150_set_vbi(struct v4l2_subdev *sd, ...@@ -671,19 +674,19 @@ static int tvp5150_set_vbi(struct v4l2_subdev *sd,
if (line < 6 || line > 27) if (line < 6 || line > 27)
return 0; return 0;
while (regs->reg != (u16)-1) { for (i = 0; i < ARRAY_SIZE(vbi_ram_default); i++) {
const struct i2c_vbi_ram_value *regs = &vbi_ram_default[i];
if (!regs->type.vbi_type)
continue;
if ((type & regs->type.vbi_type) && if ((type & regs->type.vbi_type) &&
(line >= regs->type.ini_line) && (line >= regs->type.ini_line) &&
(line <= regs->type.end_line)) (line <= regs->type.end_line))
break; break;
regs++;
pos++; pos++;
} }
if (regs->reg == (u16)-1)
return 0;
type = pos | (flags & 0xf0); type = pos | (flags & 0xf0);
reg = ((line - 6) << 1) + TVP5150_LINE_MODE_INI; reg = ((line - 6) << 1) + TVP5150_LINE_MODE_INI;
...@@ -696,8 +699,7 @@ static int tvp5150_set_vbi(struct v4l2_subdev *sd, ...@@ -696,8 +699,7 @@ static int tvp5150_set_vbi(struct v4l2_subdev *sd,
return type; return type;
} }
static int tvp5150_get_vbi(struct v4l2_subdev *sd, static int tvp5150_get_vbi(struct v4l2_subdev *sd, int line)
const struct i2c_vbi_ram_value *regs, int line)
{ {
struct tvp5150 *decoder = to_tvp5150(sd); struct tvp5150 *decoder = to_tvp5150(sd);
v4l2_std_id std = decoder->norm; v4l2_std_id std = decoder->norm;
...@@ -726,8 +728,8 @@ static int tvp5150_get_vbi(struct v4l2_subdev *sd, ...@@ -726,8 +728,8 @@ static int tvp5150_get_vbi(struct v4l2_subdev *sd,
return 0; return 0;
} }
pos = ret & 0x0f; pos = ret & 0x0f;
if (pos < 0x0f) if (pos < ARRAY_SIZE(vbi_ram_default))
type |= regs[pos].type.vbi_type; type |= vbi_ram_default[pos].type.vbi_type;
} }
return type; return type;
...@@ -788,7 +790,7 @@ static int tvp5150_reset(struct v4l2_subdev *sd, u32 val) ...@@ -788,7 +790,7 @@ static int tvp5150_reset(struct v4l2_subdev *sd, u32 val)
tvp5150_write_inittab(sd, tvp5150_init_default); tvp5150_write_inittab(sd, tvp5150_init_default);
/* Initializes VDP registers */ /* Initializes VDP registers */
tvp5150_vdp_init(sd, vbi_ram_default); tvp5150_vdp_init(sd);
/* Selects decoder input */ /* Selects decoder input */
tvp5150_selmux(sd); tvp5150_selmux(sd);
...@@ -1121,8 +1123,8 @@ static int tvp5150_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f ...@@ -1121,8 +1123,8 @@ static int tvp5150_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
for (i = 0; i <= 23; i++) { for (i = 0; i <= 23; i++) {
svbi->service_lines[1][i] = 0; svbi->service_lines[1][i] = 0;
svbi->service_lines[0][i] = svbi->service_lines[0][i] =
tvp5150_set_vbi(sd, vbi_ram_default, tvp5150_set_vbi(sd, svbi->service_lines[0][i],
svbi->service_lines[0][i], 0xf0, i, 3); 0xf0, i, 3);
} }
/* Enables FIFO */ /* Enables FIFO */
tvp5150_write(sd, TVP5150_FIFO_OUT_CTRL, 1); tvp5150_write(sd, TVP5150_FIFO_OUT_CTRL, 1);
...@@ -1148,7 +1150,7 @@ static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f ...@@ -1148,7 +1150,7 @@ static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
for (i = 0; i <= 23; i++) { for (i = 0; i <= 23; i++) {
svbi->service_lines[0][i] = svbi->service_lines[0][i] =
tvp5150_get_vbi(sd, vbi_ram_default, i); tvp5150_get_vbi(sd, i);
mask |= svbi->service_lines[0][i]; mask |= svbi->service_lines[0][i];
} }
svbi->service_set = mask; svbi->service_set = mask;
......
...@@ -324,14 +324,15 @@ static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len, ...@@ -324,14 +324,15 @@ static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
} }
return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len, return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
buffer2, buffer2_len, buffer2, buffer2_len,
&dvbdmxfilter->filter); &dvbdmxfilter->filter, NULL);
case DMX_TYPE_TS: case DMX_TYPE_TS:
if (!(dvbdmxfilter->feed->ts_type & TS_PACKET)) if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
return 0; return 0;
if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY) if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len, return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
buffer2, buffer2_len, buffer2, buffer2_len,
&dvbdmxfilter->feed->feed.ts); &dvbdmxfilter->feed->feed.ts,
NULL);
else else
av7110_p2t_write(buffer1, buffer1_len, av7110_p2t_write(buffer1, buffer1_len,
dvbdmxfilter->feed->pid, dvbdmxfilter->feed->pid,
......
...@@ -99,7 +99,7 @@ int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len) ...@@ -99,7 +99,7 @@ int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len)
buf[4] = buf[5] = 0; buf[4] = buf[5] = 0;
if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY) if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)
return dvbdmxfeed->cb.ts(buf, len, NULL, 0, return dvbdmxfeed->cb.ts(buf, len, NULL, 0,
&dvbdmxfeed->feed.ts); &dvbdmxfeed->feed.ts, NULL);
else else
return dvb_filter_pes2ts(p2t, buf, len, 1); return dvb_filter_pes2ts(p2t, buf, len, 1);
} }
...@@ -109,7 +109,7 @@ static int dvb_filter_pes2ts_cb(void *priv, unsigned char *data) ...@@ -109,7 +109,7 @@ static int dvb_filter_pes2ts_cb(void *priv, unsigned char *data)
struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) priv; struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) priv;
dvbdmxfeed->cb.ts(data, 188, NULL, 0, dvbdmxfeed->cb.ts(data, 188, NULL, 0,
&dvbdmxfeed->feed.ts); &dvbdmxfeed->feed.ts, NULL);
return 0; return 0;
} }
...@@ -814,7 +814,7 @@ static void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter, ...@@ -814,7 +814,7 @@ static void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter,
memcpy(obuf + l, buf + c, TS_SIZE - l); memcpy(obuf + l, buf + c, TS_SIZE - l);
c = length; c = length;
} }
feed->cb.ts(obuf, 188, NULL, 0, &feed->feed.ts); feed->cb.ts(obuf, 188, NULL, 0, &feed->feed.ts, NULL);
pes_start = 0; pes_start = 0;
} }
} }
......
config VIDEO_AU0828 config VIDEO_AU0828
tristate "Auvitek AU0828 support" tristate "Auvitek AU0828 support"
depends on I2C && INPUT && DVB_CORE && USB depends on I2C && INPUT && DVB_CORE && USB && VIDEO_V4L2
select I2C_ALGOBIT select I2C_ALGOBIT
select VIDEO_TVEEPROM select VIDEO_TVEEPROM
select VIDEOBUF2_VMALLOC select VIDEOBUF2_VMALLOC
......
...@@ -428,7 +428,7 @@ static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data) ...@@ -428,7 +428,7 @@ static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data)
struct ttusb_dec *dec = priv; struct ttusb_dec *dec = priv;
dec->audio_filter->feed->cb.ts(data, 188, NULL, 0, dec->audio_filter->feed->cb.ts(data, 188, NULL, 0,
&dec->audio_filter->feed->feed.ts); &dec->audio_filter->feed->feed.ts, NULL);
return 0; return 0;
} }
...@@ -438,7 +438,7 @@ static int ttusb_dec_video_pes2ts_cb(void *priv, unsigned char *data) ...@@ -438,7 +438,7 @@ static int ttusb_dec_video_pes2ts_cb(void *priv, unsigned char *data)
struct ttusb_dec *dec = priv; struct ttusb_dec *dec = priv;
dec->video_filter->feed->cb.ts(data, 188, NULL, 0, dec->video_filter->feed->cb.ts(data, 188, NULL, 0,
&dec->video_filter->feed->feed.ts); &dec->video_filter->feed->feed.ts, NULL);
return 0; return 0;
} }
...@@ -490,7 +490,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length) ...@@ -490,7 +490,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
if (output_pva) { if (output_pva) {
dec->video_filter->feed->cb.ts(pva, length, NULL, 0, dec->video_filter->feed->cb.ts(pva, length, NULL, 0,
&dec->video_filter->feed->feed.ts); &dec->video_filter->feed->feed.ts, NULL);
return; return;
} }
...@@ -551,7 +551,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length) ...@@ -551,7 +551,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
case 0x02: /* MainAudioStream */ case 0x02: /* MainAudioStream */
if (output_pva) { if (output_pva) {
dec->audio_filter->feed->cb.ts(pva, length, NULL, 0, dec->audio_filter->feed->cb.ts(pva, length, NULL, 0,
&dec->audio_filter->feed->feed.ts); &dec->audio_filter->feed->feed.ts, NULL);
return; return;
} }
...@@ -589,7 +589,7 @@ static void ttusb_dec_process_filter(struct ttusb_dec *dec, u8 *packet, ...@@ -589,7 +589,7 @@ static void ttusb_dec_process_filter(struct ttusb_dec *dec, u8 *packet,
if (filter) if (filter)
filter->feed->cb.sec(&packet[2], length - 2, NULL, 0, filter->feed->cb.sec(&packet[2], length - 2, NULL, 0,
&filter->filter); &filter->filter, NULL);
} }
static void ttusb_dec_process_packet(struct ttusb_dec *dec) static void ttusb_dec_process_packet(struct ttusb_dec *dec)
......
...@@ -7,6 +7,7 @@ config VIDEO_V4L2 ...@@ -7,6 +7,7 @@ config VIDEO_V4L2
tristate tristate
depends on (I2C || I2C=n) && VIDEO_DEV depends on (I2C || I2C=n) && VIDEO_DEV
select RATIONAL select RATIONAL
select VIDEOBUF2_V4L2 if VIDEOBUF2_CORE
default (I2C || I2C=n) && VIDEO_DEV default (I2C || I2C=n) && VIDEO_DEV
config VIDEO_ADV_DEBUG config VIDEO_ADV_DEBUG
......
...@@ -13,7 +13,7 @@ ifeq ($(CONFIG_COMPAT),y) ...@@ -13,7 +13,7 @@ ifeq ($(CONFIG_COMPAT),y)
endif endif
obj-$(CONFIG_V4L2_FWNODE) += v4l2-fwnode.o obj-$(CONFIG_V4L2_FWNODE) += v4l2-fwnode.o
ifeq ($(CONFIG_TRACEPOINTS),y) ifeq ($(CONFIG_TRACEPOINTS),y)
videodev-objs += vb2-trace.o v4l2-trace.o videodev-objs += v4l2-trace.o
endif endif
videodev-$(CONFIG_MEDIA_CONTROLLER) += v4l2-mc.o videodev-$(CONFIG_MEDIA_CONTROLLER) += v4l2-mc.o
...@@ -35,4 +35,3 @@ obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o ...@@ -35,4 +35,3 @@ obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o
ccflags-y += -I$(srctree)/drivers/media/dvb-frontends ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
ccflags-y += -I$(srctree)/drivers/media/tuners ccflags-y += -I$(srctree)/drivers/media/tuners
...@@ -117,7 +117,7 @@ struct dmx_ts_feed { ...@@ -117,7 +117,7 @@ struct dmx_ts_feed {
* specified by @filter_value that will be used on the filter * specified by @filter_value that will be used on the filter
* match logic. * match logic.
* @filter_mode: Contains a 16 bytes (128 bits) filter mode. * @filter_mode: Contains a 16 bytes (128 bits) filter mode.
* @parent: Pointer to struct dmx_section_feed. * @parent: Back-pointer to struct dmx_section_feed.
* @priv: Pointer to private data of the API client. * @priv: Pointer to private data of the API client.
* *
* *
...@@ -130,8 +130,9 @@ struct dmx_section_filter { ...@@ -130,8 +130,9 @@ struct dmx_section_filter {
u8 filter_value[DMX_MAX_FILTER_SIZE]; u8 filter_value[DMX_MAX_FILTER_SIZE];
u8 filter_mask[DMX_MAX_FILTER_SIZE]; u8 filter_mask[DMX_MAX_FILTER_SIZE];
u8 filter_mode[DMX_MAX_FILTER_SIZE]; u8 filter_mode[DMX_MAX_FILTER_SIZE];
struct dmx_section_feed *parent; /* Back-pointer */ struct dmx_section_feed *parent;
void *priv; /* Pointer to private data of the API client */
void *priv;
}; };
/** /**
...@@ -193,6 +194,10 @@ struct dmx_section_feed { ...@@ -193,6 +194,10 @@ struct dmx_section_feed {
* @buffer2: Pointer to the tail of the filtered TS packets, or NULL. * @buffer2: Pointer to the tail of the filtered TS packets, or NULL.
* @buffer2_length: Length of the TS data in buffer2. * @buffer2_length: Length of the TS data in buffer2.
* @source: Indicates which TS feed is the source of the callback. * @source: Indicates which TS feed is the source of the callback.
* @buffer_flags: Address where buffer flags are stored. Those are
* used to report discontinuity users via DVB
* memory mapped API, as defined by
* &enum dmx_buffer_flags.
* *
* This function callback prototype, provided by the client of the demux API, * This function callback prototype, provided by the client of the demux API,
* is called from the demux code. The function is only called when filtering * is called from the demux code. The function is only called when filtering
...@@ -245,7 +250,8 @@ typedef int (*dmx_ts_cb)(const u8 *buffer1, ...@@ -245,7 +250,8 @@ typedef int (*dmx_ts_cb)(const u8 *buffer1,
size_t buffer1_length, size_t buffer1_length,
const u8 *buffer2, const u8 *buffer2,
size_t buffer2_length, size_t buffer2_length,
struct dmx_ts_feed *source); struct dmx_ts_feed *source,
u32 *buffer_flags);
/** /**
* typedef dmx_section_cb - DVB demux TS filter callback function prototype * typedef dmx_section_cb - DVB demux TS filter callback function prototype
...@@ -261,6 +267,10 @@ typedef int (*dmx_ts_cb)(const u8 *buffer1, ...@@ -261,6 +267,10 @@ typedef int (*dmx_ts_cb)(const u8 *buffer1,
* including headers and CRC. * including headers and CRC.
* @source: Indicates which section feed is the source of the * @source: Indicates which section feed is the source of the
* callback. * callback.
* @buffer_flags: Address where buffer flags are stored. Those are
* used to report discontinuity users via DVB
* memory mapped API, as defined by
* &enum dmx_buffer_flags.
* *
* This function callback prototype, provided by the client of the demux API, * This function callback prototype, provided by the client of the demux API,
* is called from the demux code. The function is only called when * is called from the demux code. The function is only called when
...@@ -286,7 +296,8 @@ typedef int (*dmx_section_cb)(const u8 *buffer1, ...@@ -286,7 +296,8 @@ typedef int (*dmx_section_cb)(const u8 *buffer1,
size_t buffer1_len, size_t buffer1_len,
const u8 *buffer2, const u8 *buffer2,
size_t buffer2_len, size_t buffer2_len,
struct dmx_section_filter *source); struct dmx_section_filter *source,
u32 *buffer_flags);
/* /*
* DVB Front-End * DVB Front-End
......
...@@ -163,6 +163,7 @@ struct dmxdev_filter { ...@@ -163,6 +163,7 @@ struct dmxdev_filter {
* @demux: pointer to &struct dmx_demux. * @demux: pointer to &struct dmx_demux.
* @filternum: number of filters. * @filternum: number of filters.
* @capabilities: demux capabilities as defined by &enum dmx_demux_caps. * @capabilities: demux capabilities as defined by &enum dmx_demux_caps.
* @may_do_mmap: flag used to indicate if the device may do mmap.
* @exit: flag to indicate that the demux is being released. * @exit: flag to indicate that the demux is being released.
* @dvr_orig_fe: pointer to &struct dmx_frontend. * @dvr_orig_fe: pointer to &struct dmx_frontend.
* @dvr_buffer: embedded &struct dvb_ringbuffer for DVB output. * @dvr_buffer: embedded &struct dvb_ringbuffer for DVB output.
...@@ -180,6 +181,7 @@ struct dmxdev { ...@@ -180,6 +181,7 @@ struct dmxdev {
int filternum; int filternum;
int capabilities; int capabilities;
unsigned int may_do_mmap:1;
unsigned int exit:1; unsigned int exit:1;
#define DMXDEV_CAP_DUPLEX 1 #define DMXDEV_CAP_DUPLEX 1
struct dmx_frontend *dvr_orig_fe; struct dmx_frontend *dvr_orig_fe;
......
...@@ -115,6 +115,8 @@ struct dvb_demux_filter { ...@@ -115,6 +115,8 @@ struct dvb_demux_filter {
* @pid: PID to be filtered. * @pid: PID to be filtered.
* @timeout: feed timeout. * @timeout: feed timeout.
* @filter: pointer to &struct dvb_demux_filter. * @filter: pointer to &struct dvb_demux_filter.
* @buffer_flags: Buffer flags used to report discontinuity users via DVB
* memory mapped API, as defined by &enum dmx_buffer_flags.
* @ts_type: type of TS, as defined by &enum ts_filter_type. * @ts_type: type of TS, as defined by &enum ts_filter_type.
* @pes_type: type of PES, as defined by &enum dmx_ts_pes. * @pes_type: type of PES, as defined by &enum dmx_ts_pes.
* @cc: MPEG-TS packet continuity counter * @cc: MPEG-TS packet continuity counter
...@@ -145,6 +147,8 @@ struct dvb_demux_feed { ...@@ -145,6 +147,8 @@ struct dvb_demux_feed {
ktime_t timeout; ktime_t timeout;
struct dvb_demux_filter *filter; struct dvb_demux_filter *filter;
u32 buffer_flags;
enum ts_filter_type ts_type; enum ts_filter_type ts_type;
enum dmx_ts_pes pes_type; enum dmx_ts_pes pes_type;
......
...@@ -85,6 +85,12 @@ struct dvb_buffer { ...@@ -85,6 +85,12 @@ struct dvb_buffer {
* @nonblocking: * @nonblocking:
* If different than zero, device is operating on non-blocking * If different than zero, device is operating on non-blocking
* mode. * mode.
* @flags: buffer flags as defined by &enum dmx_buffer_flags.
* Filled only at &DMX_DQBUF. &DMX_QBUF should zero this field.
* @count: monotonic counter for filled buffers. Helps to identify
* data stream loses. Filled only at &DMX_DQBUF. &DMX_QBUF should
* zero this field.
*
* @name: name of the device type. Currently, it can either be * @name: name of the device type. Currently, it can either be
* "dvr" or "demux_filter". * "dvr" or "demux_filter".
*/ */
...@@ -100,10 +106,14 @@ struct dvb_vb2_ctx { ...@@ -100,10 +106,14 @@ struct dvb_vb2_ctx {
int buf_siz; int buf_siz;
int buf_cnt; int buf_cnt;
int nonblocking; int nonblocking;
enum dmx_buffer_flags flags;
u32 count;
char name[DVB_VB2_NAME_MAX + 1]; char name[DVB_VB2_NAME_MAX + 1];
}; };
#ifndef DVB_MMAP #ifndef CONFIG_DVB_MMAP
static inline int dvb_vb2_init(struct dvb_vb2_ctx *ctx, static inline int dvb_vb2_init(struct dvb_vb2_ctx *ctx,
const char *name, int non_blocking) const char *name, int non_blocking)
{ {
...@@ -114,7 +124,7 @@ static inline int dvb_vb2_release(struct dvb_vb2_ctx *ctx) ...@@ -114,7 +124,7 @@ static inline int dvb_vb2_release(struct dvb_vb2_ctx *ctx)
return 0; return 0;
}; };
#define dvb_vb2_is_streaming(ctx) (0) #define dvb_vb2_is_streaming(ctx) (0)
#define dvb_vb2_fill_buffer(ctx, file, wait) (0) #define dvb_vb2_fill_buffer(ctx, file, wait, flags) (0)
static inline __poll_t dvb_vb2_poll(struct dvb_vb2_ctx *ctx, static inline __poll_t dvb_vb2_poll(struct dvb_vb2_ctx *ctx,
struct file *file, struct file *file,
...@@ -153,9 +163,13 @@ int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx); ...@@ -153,9 +163,13 @@ int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx);
* @ctx: control struct for VB2 handler * @ctx: control struct for VB2 handler
* @src: place where the data is stored * @src: place where the data is stored
* @len: number of bytes to be copied from @src * @len: number of bytes to be copied from @src
* @buffer_flags:
* pointer to buffer flags as defined by &enum dmx_buffer_flags.
* can be NULL.
*/ */
int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx, int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx,
const unsigned char *src, int len); const unsigned char *src, int len,
enum dmx_buffer_flags *buffer_flags);
/** /**
* dvb_vb2_poll - Wrapper to vb2_core_streamon() for Digital TV * dvb_vb2_poll - Wrapper to vb2_core_streamon() for Digital TV
......
...@@ -211,6 +211,32 @@ struct dmx_stc { ...@@ -211,6 +211,32 @@ struct dmx_stc {
__u64 stc; __u64 stc;
}; };
/**
* enum dmx_buffer_flags - DMX memory-mapped buffer flags
*
* @DMX_BUFFER_FLAG_HAD_CRC32_DISCARD:
* Indicates that the Kernel discarded one or more frames due to wrong
* CRC32 checksum.
* @DMX_BUFFER_FLAG_TEI:
* Indicates that the Kernel has detected a Transport Error indicator
* (TEI) on a filtered pid.
* @DMX_BUFFER_PKT_COUNTER_MISMATCH:
* Indicates that the Kernel has detected a packet counter mismatch
* on a filtered pid.
* @DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED:
* Indicates that the Kernel has detected one or more frame discontinuity.
* @DMX_BUFFER_FLAG_DISCONTINUITY_INDICATOR:
* Received at least one packet with a frame discontinuity indicator.
*/
enum dmx_buffer_flags {
DMX_BUFFER_FLAG_HAD_CRC32_DISCARD = 1 << 0,
DMX_BUFFER_FLAG_TEI = 1 << 1,
DMX_BUFFER_PKT_COUNTER_MISMATCH = 1 << 2,
DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED = 1 << 3,
DMX_BUFFER_FLAG_DISCONTINUITY_INDICATOR = 1 << 4,
};
/** /**
* struct dmx_buffer - dmx buffer info * struct dmx_buffer - dmx buffer info
* *
...@@ -220,15 +246,24 @@ struct dmx_stc { ...@@ -220,15 +246,24 @@ struct dmx_stc {
* offset from the start of the device memory for this plane, * offset from the start of the device memory for this plane,
* (or a "cookie" that should be passed to mmap() as offset) * (or a "cookie" that should be passed to mmap() as offset)
* @length: size in bytes of the buffer * @length: size in bytes of the buffer
* @flags: bit array of buffer flags as defined by &enum dmx_buffer_flags.
* Filled only at &DMX_DQBUF.
* @count: monotonic counter for filled buffers. Helps to identify
* data stream loses. Filled only at &DMX_DQBUF.
* *
* Contains data exchanged by application and driver using one of the streaming * Contains data exchanged by application and driver using one of the streaming
* I/O methods. * I/O methods.
*
* Please notice that, for &DMX_QBUF, only @index should be filled.
* On &DMX_DQBUF calls, all fields will be filled by the Kernel.
*/ */
struct dmx_buffer { struct dmx_buffer {
__u32 index; __u32 index;
__u32 bytesused; __u32 bytesused;
__u32 offset; __u32 offset;
__u32 length; __u32 length;
__u32 flags;
__u32 count;
}; };
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment