Merge "media: dvb: Clean-up capabilities of demux devices"
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 6734da8..28e8092 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -1067,6 +1067,41 @@
wake_up_all(&cmdbuf->queue);
}
+static int dvb_dvr_external_input_only(struct dmxdev *dmxdev)
+{
+ struct dmx_caps caps;
+ int is_external_only;
+ int flags;
+ size_t tsp_size;
+
+ if (dmxdev->demux->get_tsp_size)
+ tsp_size = dmxdev->demux->get_tsp_size(dmxdev->demux);
+ else
+ tsp_size = 188;
+
+ /*
+ * For backward compatibility, default assumes that
+ * external only buffers are not supported.
+ */
+ flags = 0;
+ if (dmxdev->demux->get_caps) {
+ dmxdev->demux->get_caps(dmxdev->demux, &caps);
+
+ if (tsp_size == 188)
+ flags = caps.playback_188_tsp.flags;
+ else
+ flags = caps.playback_192_tsp.flags;
+ }
+
+ if (!(flags & DMX_BUFFER_INTERNAL_SUPPORT) &&
+ (flags & DMX_BUFFER_EXTERNAL_SUPPORT))
+ is_external_only = 1;
+ else
+ is_external_only = 0;
+
+ return is_external_only;
+}
+
static ssize_t dvb_dvr_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
@@ -1082,7 +1117,9 @@
return -EOPNOTSUPP;
if (((file->f_flags & O_ACCMODE) == O_RDONLY) ||
- (!src->data) || (!cmdbuf->data))
+ !src->data || !cmdbuf->data ||
+ (dvb_dvr_external_input_only(dmxdev) &&
+ (dmxdev->dvr_input_buffer_mode == DMX_BUFFER_MODE_INTERNAL)))
return -EINVAL;
if ((file->f_flags & O_NONBLOCK) &&
@@ -1238,7 +1275,7 @@
if (buf->size == size)
return 0;
- if ((!size) || (buffer_mode == DMX_BUFFER_MODE_EXTERNAL))
+ if (!size || (buffer_mode == DMX_BUFFER_MODE_EXTERNAL))
return -EINVAL;
newmem = vmalloc_user(size);
@@ -1282,10 +1319,6 @@
(mode != DMX_BUFFER_MODE_EXTERNAL))
return -EINVAL;
- if ((mode == DMX_BUFFER_MODE_INTERNAL) &&
- (dmxdev->capabilities & DMXDEV_CAP_EXTERNAL_BUFFS_ONLY))
- return -EINVAL;
-
if ((mode == DMX_BUFFER_MODE_EXTERNAL) &&
(!dmxdev->demux->map_buffer || !dmxdev->demux->unmap_buffer))
return -EINVAL;
@@ -1543,7 +1576,8 @@
if (buf->size == size)
return 0;
- if ((!size) || (dmxdevfilter->buffer_mode == DMX_BUFFER_MODE_EXTERNAL))
+ if (!size ||
+ (dmxdevfilter->buffer_mode == DMX_BUFFER_MODE_EXTERNAL))
return -EINVAL;
if (dmxdevfilter->state >= DMXDEV_STATE_GO)
return -EBUSY;
@@ -1580,10 +1614,6 @@
(mode != DMX_BUFFER_MODE_EXTERNAL))
return -EINVAL;
- if ((mode == DMX_BUFFER_MODE_INTERNAL) &&
- (dmxdev->capabilities & DMXDEV_CAP_EXTERNAL_BUFFS_ONLY))
- return -EINVAL;
-
if ((mode == DMX_BUFFER_MODE_EXTERNAL) &&
(!dmxdev->demux->map_buffer || !dmxdev->demux->unmap_buffer))
return -EINVAL;
@@ -1765,8 +1795,15 @@
int found_pid;
struct dmxdev_feed *feed;
struct dmxdev_feed *ts_feed = NULL;
+ struct dmx_caps caps;
+
+ if (!dmxdevfilter->dev->demux->get_caps)
+ return -EINVAL;
+
+ dmxdevfilter->dev->demux->get_caps(dmxdevfilter->dev->demux, &caps);
if (!idx_params ||
+ !(caps.caps & DMX_CAP_VIDEO_INDEXING) ||
(dmxdevfilter->state < DMXDEV_STATE_SET) ||
(dmxdevfilter->type != DMXDEV_TYPE_PES) ||
((dmxdevfilter->params.pes.output != DMX_OUT_TS_TAP) &&
@@ -1907,10 +1944,16 @@
int first_buffer;
struct dmxdev_feed *feed;
struct ts_insertion_buffer *ts_buffer;
+ struct dmx_caps caps;
+
+ if (!dmxdevfilter->dev->demux->get_caps)
+ return -EINVAL;
+
+ dmxdevfilter->dev->demux->get_caps(dmxdevfilter->dev->demux, &caps);
if (!params ||
!params->size ||
- !(dmxdevfilter->dev->capabilities & DMXDEV_CAP_TS_INSERTION) ||
+ !(caps.caps & DMX_CAP_TS_INSERTION) ||
(dmxdevfilter->state < DMXDEV_STATE_SET) ||
(dmxdevfilter->type != DMXDEV_TYPE_PES) ||
((dmxdevfilter->params.pes.output != DMX_OUT_TS_TAP) &&
@@ -1974,9 +2017,15 @@
int found_buffer;
struct dmxdev_feed *feed;
struct ts_insertion_buffer *ts_buffer, *tmp;
+ struct dmx_caps caps;
+
+ if (!dmxdevfilter->dev->demux->get_caps)
+ return -EINVAL;
+
+ dmxdevfilter->dev->demux->get_caps(dmxdevfilter->dev->demux, &caps);
if (!params ||
- !(dmxdevfilter->dev->capabilities & DMXDEV_CAP_TS_INSERTION) ||
+ !(caps.caps & DMX_CAP_TS_INSERTION) ||
(dmxdevfilter->state < DMXDEV_STATE_SET) ||
(dmxdevfilter->type != DMXDEV_TYPE_PES) ||
((dmxdevfilter->params.pes.output != DMX_OUT_TS_TAP) &&
@@ -2122,15 +2171,21 @@
enum dmx_playback_mode_t playback_mode)
{
struct dmxdev *dmxdev = dmxdevfilter->dev;
+ struct dmx_caps caps;
+
+ if (dmxdev->demux->get_caps)
+ dmxdev->demux->get_caps(dmxdev->demux, &caps);
+ else
+ caps.caps = 0;
if ((playback_mode != DMX_PB_MODE_PUSH) &&
(playback_mode != DMX_PB_MODE_PULL))
return -EINVAL;
if (((dmxdev->source < DMX_SOURCE_DVR0) ||
- !dmxdev->demux->set_playback_mode ||
- !(dmxdev->capabilities & DMXDEV_CAP_PULL_MODE)) &&
- (playback_mode == DMX_PB_MODE_PULL))
+ !dmxdev->demux->set_playback_mode ||
+ !(caps.caps & DMX_CAP_PULL_MODE)) &&
+ (playback_mode == DMX_PB_MODE_PULL))
return -EPERM;
if (dmxdevfilter->state == DMXDEV_STATE_GO)
@@ -3083,6 +3138,43 @@
return 0;
}
+static int dvb_filter_external_buffer_only(struct dmxdev *dmxdev,
+ struct dmxdev_filter *filter)
+{
+ struct dmx_caps caps;
+ int is_external_only;
+ int flags;
+
+ /*
+ * For backward compatibility, default assumes that
+ * external only buffers are not supported.
+ */
+ flags = 0;
+ if (dmxdev->demux->get_caps) {
+ dmxdev->demux->get_caps(dmxdev->demux, &caps);
+
+ if (filter->type == DMXDEV_TYPE_SEC)
+ flags = caps.section.flags;
+ else if (filter->params.pes.output == DMX_OUT_DECODER)
+ /* For decoder filters dmxdev buffer is not required */
+ flags = 0;
+ else if (filter->params.pes.output == DMX_OUT_TAP)
+ flags = caps.pes.flags;
+ else if (filter->dmx_tsp_format == DMX_TSP_FORMAT_188)
+ flags = caps.recording_188_tsp.flags;
+ else
+ flags = caps.recording_192_tsp.flags;
+ }
+
+ if (!(flags & DMX_BUFFER_INTERNAL_SUPPORT) &&
+ (flags & DMX_BUFFER_EXTERNAL_SUPPORT))
+ is_external_only = 1;
+ else
+ is_external_only = 0;
+
+ return is_external_only;
+}
+
static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
{
struct dmxdev *dmxdev = filter->dev;
@@ -3098,14 +3190,18 @@
if (!filter->buffer.data) {
if ((filter->buffer_mode == DMX_BUFFER_MODE_EXTERNAL) ||
- (dmxdev->capabilities & DMXDEV_CAP_EXTERNAL_BUFFS_ONLY))
+ dvb_filter_external_buffer_only(dmxdev, filter))
return -ENOMEM;
+
mem = vmalloc_user(filter->buffer.size);
if (!mem)
return -ENOMEM;
spin_lock_irq(&filter->dev->lock);
filter->buffer.data = mem;
spin_unlock_irq(&filter->dev->lock);
+ } else if ((filter->buffer_mode == DMX_BUFFER_MODE_INTERNAL) &&
+ dvb_filter_external_buffer_only(dmxdev, filter)) {
+ return -ENOMEM;
}
filter->eos_state = 0;
@@ -3577,10 +3673,13 @@
struct dmx_decoder_buffers *dec_buffs;
struct dmx_caps caps;
- if (NULL == dmxdev || NULL == filter || NULL == buffs)
+ if (!dmxdev || !filter || !buffs)
return -EINVAL;
dec_buffs = &filter->decoder_buffers;
+ if (!dmxdev->demux->get_caps)
+ return -EINVAL;
+
dmxdev->demux->get_caps(dmxdev->demux, &caps);
if ((buffs->buffers_size == 0) ||
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h
index 49e5e1b..4e306e8 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.h
+++ b/drivers/media/dvb/dvb-core/dmxdev.h
@@ -196,11 +196,6 @@
int filternum;
int capabilities;
#define DMXDEV_CAP_DUPLEX 0x01
-#define DMXDEV_CAP_PULL_MODE 0x02
-#define DMXDEV_CAP_INDEXING 0x04
-#define DMXDEV_CAP_EXTERNAL_BUFFS_ONLY 0x08
-#define DMXDEV_CAP_TS_INSERTION 0x10
-
enum dmx_playback_mode_t playback_mode;
dmx_source_t source;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
index 29369de..ef3f57f 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
@@ -548,7 +548,8 @@
return -EINVAL;
}
- caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_DECODER_DATA;
+ caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_DECODER_DATA |
+ DMX_CAP_TS_INSERTION | DMX_CAP_VIDEO_INDEXING;
caps->num_decoders = MPQ_ADAPTER_MAX_NUM_OF_INTERFACES;
caps->num_demux_devices = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
caps->num_pid_filters = dvb_demux->feednum;
@@ -599,7 +600,6 @@
caps->playback_192_tsp.max_size = 0xFFFFFFFF;
caps->playback_192_tsp.size_alignment = 0;
caps->decoder.flags =
- DMX_BUFFER_CONTIGUOUS_MEM |
DMX_BUFFER_SECURED_IF_DECRYPTED |
DMX_BUFFER_EXTERNAL_SUPPORT |
DMX_BUFFER_INTERNAL_SUPPORT |
@@ -700,11 +700,7 @@
/* Now initailize the dmx-dev object */
mpq_demux->dmxdev.filternum = MPQ_MAX_DMX_FILES;
mpq_demux->dmxdev.demux = &mpq_demux->demux.dmx;
- mpq_demux->dmxdev.capabilities =
- DMXDEV_CAP_DUPLEX |
- DMXDEV_CAP_PULL_MODE |
- DMXDEV_CAP_INDEXING |
- DMXDEV_CAP_TS_INSERTION;
+ mpq_demux->dmxdev.capabilities = DMXDEV_CAP_DUPLEX;
mpq_demux->dmxdev.demux->set_source = mpq_dmx_set_source;
mpq_demux->dmxdev.demux->get_stc = mpq_tsif_dmx_get_stc;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
index a2ce428..8e628f6 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
@@ -1614,7 +1614,8 @@
return -EINVAL;
}
- caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_DECODER_DATA;
+ caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_DECODER_DATA |
+ DMX_CAP_TS_INSERTION | DMX_CAP_VIDEO_INDEXING;
caps->num_decoders = MPQ_ADAPTER_MAX_NUM_OF_INTERFACES;
caps->num_demux_devices = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
caps->num_pid_filters = TSPP_MAX_PID_FILTER_NUM;
@@ -1623,9 +1624,9 @@
caps->section_filter_length = DMX_FILTER_SIZE;
caps->num_demod_inputs = TSIF_COUNT;
caps->num_memory_inputs = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
- caps->max_bitrate = 144;
- caps->demod_input_max_bitrate = 72;
- caps->memory_input_max_bitrate = 72;
+ caps->max_bitrate = 192;
+ caps->demod_input_max_bitrate = 96;
+ caps->memory_input_max_bitrate = 96;
/* Buffer requirements */
caps->section.flags =
@@ -1665,7 +1666,6 @@
caps->playback_192_tsp.max_size = 0xFFFFFFFF;
caps->playback_192_tsp.size_alignment = 0;
caps->decoder.flags =
- DMX_BUFFER_CONTIGUOUS_MEM |
DMX_BUFFER_SECURED_IF_DECRYPTED |
DMX_BUFFER_EXTERNAL_SUPPORT |
DMX_BUFFER_INTERNAL_SUPPORT |
@@ -1758,11 +1758,7 @@
/* Now initailize the dmx-dev object */
mpq_demux->dmxdev.filternum = MPQ_MAX_DMX_FILES;
mpq_demux->dmxdev.demux = &mpq_demux->demux.dmx;
- mpq_demux->dmxdev.capabilities =
- DMXDEV_CAP_DUPLEX |
- DMXDEV_CAP_PULL_MODE |
- DMXDEV_CAP_INDEXING |
- DMXDEV_CAP_TS_INSERTION;
+ mpq_demux->dmxdev.capabilities = DMXDEV_CAP_DUPLEX;
mpq_demux->dmxdev.demux->set_source = mpq_dmx_set_source;
mpq_demux->dmxdev.demux->get_stc = mpq_tspp_dmx_get_stc;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
index 60e3cb4..1ab9da1 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
@@ -73,7 +73,7 @@
}
caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_INDEXING |
- DMX_CAP_VIDEO_DECODER_DATA;
+ DMX_CAP_VIDEO_DECODER_DATA | DMX_CAP_TS_INSERTION;
caps->num_decoders = MPQ_ADAPTER_MAX_NUM_OF_INTERFACES;
caps->num_demux_devices = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
caps->num_pid_filters = TSPP_MAX_PID_FILTER_NUM;
@@ -140,11 +140,7 @@
/* Now initailize the dmx-dev object */
mpq_demux->dmxdev.filternum = MPQ_MAX_DMX_FILES;
mpq_demux->dmxdev.demux = &mpq_demux->demux.dmx;
- mpq_demux->dmxdev.capabilities =
- DMXDEV_CAP_DUPLEX |
- DMXDEV_CAP_PULL_MODE |
- DMXDEV_CAP_INDEXING |
- DMXDEV_CAP_TS_INSERTION;
+ mpq_demux->dmxdev.capabilities = DMXDEV_CAP_DUPLEX;
mpq_demux->dmxdev.demux->set_source = mpq_dmx_set_source;
mpq_demux->dmxdev.demux->get_caps = mpq_tspp_dmx_get_caps;
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index ce9e5b9..bd954ee 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -528,6 +528,9 @@
/* Indicates whether demux support sending data directly to subtitle decoder */
#define DMX_CAP_SUBTITLE_DECODER_DATA 0x10
+/* Indicates whether TS insertion is supported */
+#define DMX_CAP_TS_INSERTION 0x20
+
/* Number of decoders demux can output data to */
int num_decoders;