Merge "media: platform: msm: Add demux support for mediabox"
This commit is contained in:
committed by
Gerrit - the friendly Code Review server
commit
65ec0b0413
@@ -131,6 +131,39 @@ static const struct dvb_dmx_video_patterns h264_non_idr = {
|
||||
DMX_IDX_H264_NON_IDR_START
|
||||
};
|
||||
|
||||
/*
|
||||
* Forbidden (1 bit) + NAL idc (2 bits) + NAL type (5 bits)
|
||||
* I-Slice NAL idc = 3, NAL type = 5, 01100101 mask 0x7F
|
||||
*/
|
||||
static const struct dvb_dmx_video_patterns h264_idr_islice = {
|
||||
{0x00, 0x00, 0x01, 0x65, 0x80},
|
||||
{0xFF, 0xFF, 0xFF, 0x7F, 0x80},
|
||||
5,
|
||||
DMX_IDX_H264_IDR_ISLICE_START
|
||||
};
|
||||
|
||||
/*
|
||||
* Forbidden (1 bit) + NAL idc (2 bits) + NAL type (5 bits)
|
||||
* P-Slice NAL idc = 2, NAL type = 1, 01000001 mask 0x7F
|
||||
*/
|
||||
static const struct dvb_dmx_video_patterns h264_non_idr_pslice = {
|
||||
{0x00, 0x00, 0x01, 0x41, 0x80},
|
||||
{0xFF, 0xFF, 0xFF, 0x7F, 0x80},
|
||||
5,
|
||||
DMX_IDX_H264_NON_IDR_PSLICE_START
|
||||
};
|
||||
|
||||
/*
|
||||
* Forbidden (1 bit) + NAL idc (2 bits) + NAL type (5 bits)
|
||||
* B-Slice NAL idc = 0, NAL type = 1, 00000001 mask 0x7F
|
||||
*/
|
||||
static const struct dvb_dmx_video_patterns h264_non_idr_bslice = {
|
||||
{0x00, 0x00, 0x01, 0x01, 0x80},
|
||||
{0xFF, 0xFF, 0xFF, 0x7F, 0x80},
|
||||
5,
|
||||
DMX_IDX_H264_NON_IDR_BSLICE_START
|
||||
};
|
||||
|
||||
static const struct dvb_dmx_video_patterns h264_non_access_unit_del = {
|
||||
{0x00, 0x00, 0x01, 0x09},
|
||||
{0xFF, 0xFF, 0xFF, 0x1F},
|
||||
@@ -1011,6 +1044,18 @@ static void dvb_dmx_process_pattern_result(struct dvb_demux_feed *feed,
|
||||
} else if (feed->prev_frame_type & DMX_IDX_H264_NON_IDR_START) {
|
||||
idx_event.type = DMX_IDX_H264_NON_IDR_END;
|
||||
frame_end_in_seq = DMX_IDX_H264_FIRST_SPS_FRAME_END;
|
||||
} else if (feed->prev_frame_type &
|
||||
DMX_IDX_H264_IDR_ISLICE_START) {
|
||||
idx_event.type = DMX_IDX_H264_IDR_END;
|
||||
frame_end_in_seq = DMX_IDX_H264_FIRST_SPS_FRAME_END;
|
||||
} else if (feed->prev_frame_type &
|
||||
DMX_IDX_H264_NON_IDR_PSLICE_START) {
|
||||
idx_event.type = DMX_IDX_H264_NON_IDR_END;
|
||||
frame_end_in_seq = DMX_IDX_H264_FIRST_SPS_FRAME_END;
|
||||
} else if (feed->prev_frame_type &
|
||||
DMX_IDX_H264_NON_IDR_BSLICE_START) {
|
||||
idx_event.type = DMX_IDX_H264_NON_IDR_END;
|
||||
frame_end_in_seq = DMX_IDX_H264_FIRST_SPS_FRAME_END;
|
||||
} else {
|
||||
idx_event.type = DMX_IDX_VC1_FRAME_END;
|
||||
frame_end_in_seq = DMX_IDX_VC1_FIRST_SEQ_FRAME_END;
|
||||
@@ -1848,6 +1893,15 @@ const struct dvb_dmx_video_patterns *dvb_dmx_get_pattern(u64 dmx_idx_pattern)
|
||||
case DMX_IDX_H264_NON_IDR_START:
|
||||
return &h264_non_idr;
|
||||
|
||||
case DMX_IDX_H264_IDR_ISLICE_START:
|
||||
return &h264_idr_islice;
|
||||
|
||||
case DMX_IDX_H264_NON_IDR_PSLICE_START:
|
||||
return &h264_non_idr_pslice;
|
||||
|
||||
case DMX_IDX_H264_NON_IDR_BSLICE_START:
|
||||
return &h264_non_idr_bslice;
|
||||
|
||||
case DMX_IDX_H264_ACCESS_UNIT_DEL:
|
||||
return &h264_non_access_unit_del;
|
||||
|
||||
@@ -1975,6 +2029,40 @@ static void dvb_dmx_init_idx_state(struct dvb_demux_feed *feed)
|
||||
feed->pattern_num++;
|
||||
}
|
||||
|
||||
/* H264 IDR ISlice */
|
||||
if ((feed->pattern_num < DVB_DMX_MAX_SEARCH_PATTERN_NUM) &&
|
||||
(feed->idx_params.types &
|
||||
(DMX_IDX_H264_IDR_ISLICE_START | DMX_IDX_H264_IDR_END |
|
||||
DMX_IDX_H264_NON_IDR_END |
|
||||
DMX_IDX_H264_FIRST_SPS_FRAME_START |
|
||||
DMX_IDX_H264_FIRST_SPS_FRAME_END))) {
|
||||
feed->patterns[feed->pattern_num] =
|
||||
dvb_dmx_get_pattern(DMX_IDX_H264_IDR_ISLICE_START);
|
||||
feed->pattern_num++;
|
||||
}
|
||||
/* H264 non-IDR PSlice */
|
||||
if ((feed->pattern_num < DVB_DMX_MAX_SEARCH_PATTERN_NUM) &&
|
||||
(feed->idx_params.types &
|
||||
(DMX_IDX_H264_NON_IDR_PSLICE_START | DMX_IDX_H264_NON_IDR_END |
|
||||
DMX_IDX_H264_IDR_END |
|
||||
DMX_IDX_H264_FIRST_SPS_FRAME_START |
|
||||
DMX_IDX_H264_FIRST_SPS_FRAME_END))) {
|
||||
feed->patterns[feed->pattern_num] =
|
||||
dvb_dmx_get_pattern(DMX_IDX_H264_NON_IDR_PSLICE_START);
|
||||
feed->pattern_num++;
|
||||
}
|
||||
/* H264 non-IDR BSlice */
|
||||
if ((feed->pattern_num < DVB_DMX_MAX_SEARCH_PATTERN_NUM) &&
|
||||
(feed->idx_params.types &
|
||||
(DMX_IDX_H264_NON_IDR_BSLICE_START | DMX_IDX_H264_NON_IDR_END |
|
||||
DMX_IDX_H264_IDR_END |
|
||||
DMX_IDX_H264_FIRST_SPS_FRAME_START |
|
||||
DMX_IDX_H264_FIRST_SPS_FRAME_END))) {
|
||||
feed->patterns[feed->pattern_num] =
|
||||
dvb_dmx_get_pattern(DMX_IDX_H264_NON_IDR_BSLICE_START);
|
||||
feed->pattern_num++;
|
||||
}
|
||||
|
||||
if ((feed->pattern_num < DVB_DMX_MAX_SEARCH_PATTERN_NUM) &&
|
||||
(feed->idx_params.types & DMX_IDX_H264_ACCESS_UNIT_DEL)) {
|
||||
feed->patterns[feed->pattern_num] =
|
||||
@@ -3253,7 +3341,8 @@ static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 * pids)
|
||||
{
|
||||
struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
|
||||
|
||||
memcpy(pids, dvbdemux->pids, 5 * sizeof(u16));
|
||||
/* 4 Demux Instances each with group of 5 pids */
|
||||
memcpy(pids, dvbdemux->pids, DMX_PES_OTHER*sizeof(u16));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -359,6 +359,31 @@ static inline int dvb_dmx_is_video_feed(struct dvb_demux_feed *feed)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* dvb_dmx_is_audio_feed - Returns whether the PES feed
|
||||
* is audio one.
|
||||
*
|
||||
* @feed: The feed to be checked.
|
||||
*
|
||||
* Return 1 if feed is audio feed, 0 otherwise.
|
||||
*/
|
||||
static inline int dvb_dmx_is_audio_feed(struct dvb_demux_feed *feed)
|
||||
{
|
||||
if (feed->type != DMX_TYPE_TS)
|
||||
return 0;
|
||||
|
||||
if (feed->ts_type & (~TS_DECODER))
|
||||
return 0;
|
||||
|
||||
if ((feed->pes_type == DMX_PES_AUDIO0) ||
|
||||
(feed->pes_type == DMX_PES_AUDIO1) ||
|
||||
(feed->pes_type == DMX_PES_AUDIO2) ||
|
||||
(feed->pes_type == DMX_PES_AUDIO3))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* dvb_dmx_is_pcr_feed - Returns whether the PES feed
|
||||
* is PCR one.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -45,6 +45,8 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/msm-bus.h>
|
||||
#include <linux/interrupt.h> /* tasklet */
|
||||
#include <asm/arch_timer.h> /* Timer */
|
||||
#include <linux/avtimer_kernel.h> /* Timer */
|
||||
|
||||
/*
|
||||
* General defines
|
||||
@@ -100,6 +102,7 @@
|
||||
#define TSIF_TEST_RESET_OFF (0x1c)
|
||||
#define TSIF_TEST_EXPORT_OFF (0x20)
|
||||
#define TSIF_TEST_CURRENT_OFF (0x24)
|
||||
#define TSIF_TTS_CTL_OFF (0x38)
|
||||
|
||||
#define TSIF_DATA_PORT_OFF (0x100)
|
||||
|
||||
@@ -128,6 +131,12 @@
|
||||
#define TSIF_STS_CTL_STOP BIT(3)
|
||||
#define TSIF_STS_CTL_START BIT(0)
|
||||
|
||||
/* bits for TSIF_TTS_CTRL register */
|
||||
#define TSIF_TTS_CTL_TTS_ENDIANNESS BIT(4)
|
||||
#define TSIF_TTS_CTL_TTS_SOURCE BIT(3)
|
||||
#define TSIF_TTS_CTL_TTS_LENGTH_1 BIT(1)
|
||||
#define TSIF_TTS_CTL_TTS_LENGTH_0 BIT(0)
|
||||
|
||||
/*
|
||||
* TSPP register offsets
|
||||
*/
|
||||
@@ -255,6 +264,7 @@ static const struct debugfs_entry debugfs_tsif_regs[] = {
|
||||
{"test_export", S_IRUGO | S_IWUSR, TSIF_TEST_EXPORT_OFF},
|
||||
{"test_current", S_IRUGO, TSIF_TEST_CURRENT_OFF},
|
||||
{"data_port", S_IRUSR, TSIF_DATA_PORT_OFF},
|
||||
{"tts_source", S_IRUSR | S_IWUSR, TSIF_TTS_CTL_OFF},
|
||||
};
|
||||
|
||||
static const struct debugfs_entry debugfs_tspp_regs[] = {
|
||||
@@ -369,6 +379,8 @@ struct tspp_tsif_device {
|
||||
u32 stat_overflow;
|
||||
u32 stat_lost_sync;
|
||||
u32 stat_timeout;
|
||||
enum tsif_tts_source tts_source;
|
||||
u32 lpass_timer_enable;
|
||||
};
|
||||
|
||||
enum tspp_buf_state {
|
||||
@@ -477,6 +489,7 @@ struct tspp_device {
|
||||
/* pinctrl */
|
||||
struct mutex mutex;
|
||||
struct tspp_pinctrl pinctrl;
|
||||
unsigned int tts_source; /* Time stamp source type LPASS timer/TCR */
|
||||
|
||||
struct dentry *dent;
|
||||
struct dentry *debugfs_regs[ARRAY_SIZE(debugfs_tspp_regs)];
|
||||
@@ -911,6 +924,8 @@ static int tspp_start_tsif(struct tspp_tsif_device *tsif_device)
|
||||
{
|
||||
int start_hardware = 0;
|
||||
u32 ctl;
|
||||
u32 tts_ctl;
|
||||
int retval;
|
||||
|
||||
if (tsif_device->ref_count == 0) {
|
||||
start_hardware = 1;
|
||||
@@ -949,19 +964,57 @@ static int tspp_start_tsif(struct tspp_tsif_device *tsif_device)
|
||||
TSIF_STS_CTL_TEST_MODE;
|
||||
break;
|
||||
case TSPP_TSIF_MODE_1:
|
||||
ctl |= TSIF_STS_CTL_EN_TIME_LIM |
|
||||
TSIF_STS_CTL_EN_TCR;
|
||||
ctl |= TSIF_STS_CTL_EN_TIME_LIM;
|
||||
if (tsif_device->tts_source != TSIF_TTS_LPASS_TIMER)
|
||||
ctl |= TSIF_STS_CTL_EN_TCR;
|
||||
break;
|
||||
case TSPP_TSIF_MODE_2:
|
||||
ctl |= TSIF_STS_CTL_EN_TIME_LIM |
|
||||
TSIF_STS_CTL_EN_TCR |
|
||||
TSIF_STS_CTL_MODE_2;
|
||||
if (tsif_device->tts_source != TSIF_TTS_LPASS_TIMER)
|
||||
ctl |= TSIF_STS_CTL_EN_TCR;
|
||||
break;
|
||||
default:
|
||||
pr_warn("tspp: unknown tsif mode 0x%x",
|
||||
tsif_device->mode);
|
||||
}
|
||||
/* Set 4bytes Time Stamp for TCR */
|
||||
if (tsif_device->tts_source == TSIF_TTS_LPASS_TIMER) {
|
||||
if (tsif_device->lpass_timer_enable == 0) {
|
||||
retval = avcs_core_open();
|
||||
if (retval < 0) {
|
||||
pr_warn("tspp: avcs open fail:%d\n",
|
||||
retval);
|
||||
return retval;
|
||||
}
|
||||
retval = avcs_core_disable_power_collapse(1);
|
||||
if (retval < 0) {
|
||||
pr_warn("tspp: avcs power enable:%d\n",
|
||||
retval);
|
||||
return retval;
|
||||
}
|
||||
tsif_device->lpass_timer_enable = 1;
|
||||
}
|
||||
|
||||
tts_ctl = readl_relaxed(tsif_device->base +
|
||||
TSIF_TTS_CTL_OFF);
|
||||
tts_ctl = 0;
|
||||
/* Set LPASS Timer TTS source */
|
||||
tts_ctl |= TSIF_TTS_CTL_TTS_SOURCE;
|
||||
/* Set 4 byte TTS */
|
||||
tts_ctl |= TSIF_TTS_CTL_TTS_LENGTH_0;
|
||||
|
||||
writel_relaxed(tts_ctl, tsif_device->base +
|
||||
TSIF_TTS_CTL_OFF);
|
||||
/* write TTS control register */
|
||||
wmb();
|
||||
tts_ctl = readl_relaxed(tsif_device->base +
|
||||
TSIF_TTS_CTL_OFF);
|
||||
}
|
||||
|
||||
writel_relaxed(ctl, tsif_device->base + TSIF_STS_CTL_OFF);
|
||||
/* write Status control register */
|
||||
wmb();
|
||||
writel_relaxed(tsif_device->time_limit,
|
||||
tsif_device->base + TSIF_TIME_LIMIT_OFF);
|
||||
/* assure register configuration is done before starting TSIF */
|
||||
@@ -982,8 +1035,13 @@ static int tspp_start_tsif(struct tspp_tsif_device *tsif_device)
|
||||
|
||||
static void tspp_stop_tsif(struct tspp_tsif_device *tsif_device)
|
||||
{
|
||||
if (tsif_device->ref_count == 0)
|
||||
if (tsif_device->ref_count == 0) {
|
||||
if (tsif_device->lpass_timer_enable == 1) {
|
||||
if (avcs_core_disable_power_collapse(0) == 0)
|
||||
tsif_device->lpass_timer_enable = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
tsif_device->ref_count--;
|
||||
|
||||
@@ -1113,6 +1171,7 @@ static int tspp_global_reset(struct tspp_device *pdev)
|
||||
pdev->tsif[i].data_inverse = 0;
|
||||
pdev->tsif[i].sync_inverse = 0;
|
||||
pdev->tsif[i].enable_inverse = 0;
|
||||
pdev->tsif[i].lpass_timer_enable = 0;
|
||||
}
|
||||
writel_relaxed(TSPP_RST_RESET, pdev->base + TSPP_RST);
|
||||
/* assure state is reset before continuing with configuration */
|
||||
@@ -1884,6 +1943,89 @@ int tspp_get_ref_clk_counter(u32 dev, enum tspp_source source, u32 *tcr_counter)
|
||||
}
|
||||
EXPORT_SYMBOL(tspp_get_ref_clk_counter);
|
||||
|
||||
/**
|
||||
* tspp_get_lpass_time_counter - return the LPASS Timer counter value.
|
||||
*
|
||||
* @dev: TSPP device (up to TSPP_MAX_DEVICES)
|
||||
* @source: The TSIF source from which the counter should be read
|
||||
* @tcr_counter: the value of TCR counter
|
||||
*
|
||||
* Return error status
|
||||
*
|
||||
* If source is neither TSIF 0 or TSIF1 0 is returned.
|
||||
*/
|
||||
int tspp_get_lpass_time_counter(u32 dev, enum tspp_source source,
|
||||
u64 *lpass_time_counter)
|
||||
{
|
||||
struct tspp_device *pdev;
|
||||
struct tspp_tsif_device *tsif_device;
|
||||
|
||||
if (!lpass_time_counter)
|
||||
return -EINVAL;
|
||||
|
||||
pdev = tspp_find_by_id(dev);
|
||||
if (!pdev) {
|
||||
pr_err("tspp_get_lpass_time_counter: can't find device %i\n",
|
||||
dev);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
switch (source) {
|
||||
case TSPP_SOURCE_TSIF0:
|
||||
tsif_device = &pdev->tsif[0];
|
||||
break;
|
||||
|
||||
case TSPP_SOURCE_TSIF1:
|
||||
tsif_device = &pdev->tsif[1];
|
||||
break;
|
||||
|
||||
default:
|
||||
tsif_device = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tsif_device && tsif_device->ref_count) {
|
||||
if (avcs_core_query_timer(lpass_time_counter) < 0) {
|
||||
pr_err("tspp_get_lpass_time_counter: read error\n");
|
||||
*lpass_time_counter = 0;
|
||||
return -ENETRESET;
|
||||
}
|
||||
} else
|
||||
*lpass_time_counter = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(tspp_get_lpass_time_counter);
|
||||
|
||||
/**
|
||||
* tspp_get_tts_source - Return the TTS source value.
|
||||
*
|
||||
* @dev: TSPP device (up to TSPP_MAX_DEVICES)
|
||||
* @tts_source:Updated TTS source type
|
||||
*
|
||||
* Return error status
|
||||
*
|
||||
*/
|
||||
int tspp_get_tts_source(u32 dev, int *tts_source)
|
||||
{
|
||||
struct tspp_device *pdev;
|
||||
|
||||
if (tts_source == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
pdev = tspp_find_by_id(dev);
|
||||
if (!pdev) {
|
||||
pr_err("tspp_get_tts_source: can't find device %i\n",
|
||||
dev);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
*tts_source = pdev->tts_source;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(tspp_get_tts_source);
|
||||
|
||||
/**
|
||||
* tspp_add_filter - add a TSPP filter to a channel.
|
||||
*
|
||||
@@ -2891,6 +3033,20 @@ static int msm_tspp_probe(struct platform_device *pdev)
|
||||
goto err_irq;
|
||||
device->req_irqs = false;
|
||||
|
||||
/* Check whether AV timer time stamps are enabled */
|
||||
if (!of_property_read_u32(pdev->dev.of_node, "qcom,lpass-timer-tts",
|
||||
&device->tts_source)) {
|
||||
if (device->tts_source == 1)
|
||||
device->tts_source = TSIF_TTS_LPASS_TIMER;
|
||||
else
|
||||
device->tts_source = TSIF_TTS_TCR;
|
||||
} else {
|
||||
device->tts_source = TSIF_TTS_TCR;
|
||||
}
|
||||
|
||||
for (i = 0; i < TSPP_TSIF_INSTANCES; i++)
|
||||
device->tsif[i].tts_source = device->tts_source;
|
||||
|
||||
/* power management */
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
ccflags-y += -Idrivers/media/dvb-core/
|
||||
ccflags-y += -Idrivers/media/platform/msm/dvb/include/
|
||||
ccflags-y += -Idrivers/media/platform/msm/dvb/demux/
|
||||
|
||||
obj-$(CONFIG_DVB_MPQ) += mpq-adapter.o
|
||||
|
||||
|
||||
@@ -44,3 +44,11 @@ choice
|
||||
TSPP hardware support. All demux tasks will be
|
||||
performed in SW.
|
||||
endchoice
|
||||
|
||||
config DVB_MPQ_MEDIA_BOX_DEMUX
|
||||
bool "Media box demux support"
|
||||
depends on DVB_MPQ_DEMUX
|
||||
|
||||
help
|
||||
Use this option if your HW is Qualcomm media box and demux
|
||||
support is required on that media box.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -44,12 +44,20 @@
|
||||
#define VIDEO_META_DATA_BUFFER_SIZE \
|
||||
(VIDEO_NUM_OF_PES_PACKETS * VIDEO_META_DATA_PACKET_SIZE)
|
||||
|
||||
#define AUDIO_NUM_OF_PES_PACKETS 100
|
||||
|
||||
#define AUDIO_META_DATA_PACKET_SIZE \
|
||||
(DVB_RINGBUFFER_PKTHDRSIZE + \
|
||||
sizeof(struct mpq_streambuffer_packet_header) + \
|
||||
sizeof(struct mpq_adapter_audio_meta_data))
|
||||
|
||||
#define AUDIO_META_DATA_BUFFER_SIZE \
|
||||
(AUDIO_NUM_OF_PES_PACKETS * AUDIO_META_DATA_PACKET_SIZE)
|
||||
|
||||
/* Max number open() request can be done on demux device */
|
||||
#define MPQ_MAX_DMX_FILES 128
|
||||
|
||||
/**
|
||||
* TSIF alias name length
|
||||
*/
|
||||
/* TSIF alias name length */
|
||||
#define TSIF_NAME_LENGTH 20
|
||||
|
||||
/**
|
||||
@@ -332,6 +340,30 @@ const struct dvb_dmx_video_patterns *patterns[DVB_DMX_MAX_SEARCH_PATTERN_NUM];
|
||||
u64 prev_stc;
|
||||
};
|
||||
|
||||
/* require a bare minimal mpq_audio_feed_info struct */
|
||||
struct mpq_audio_feed_info {
|
||||
struct mpq_streambuffer *audio_buffer;
|
||||
spinlock_t audio_buffer_lock;
|
||||
struct mpq_decoder_buffers_desc buffer_desc;
|
||||
struct pes_packet_header pes_header;
|
||||
u32 pes_header_left_bytes;
|
||||
u32 pes_header_offset;
|
||||
int fullness_wait_cancel;
|
||||
enum mpq_adapter_stream_if stream_interface;
|
||||
u32 frame_offset; /* pes frame offset */
|
||||
struct dmx_pts_dts_info saved_pts_dts_info;
|
||||
struct dmx_pts_dts_info new_pts_dts_info;
|
||||
int saved_info_used;
|
||||
int new_info_exists;
|
||||
int first_pts_dts_copy;
|
||||
u32 tei_errs;
|
||||
int last_continuity;
|
||||
u32 continuity_errs;
|
||||
u32 ts_packets_num;
|
||||
u32 ts_dropped_bytes;
|
||||
u64 prev_stc;
|
||||
};
|
||||
|
||||
/**
|
||||
* mpq feed object - mpq common plugin feed information
|
||||
*
|
||||
@@ -367,6 +399,7 @@ struct mpq_feed {
|
||||
struct ion_handle *sdmx_buf_handle;
|
||||
|
||||
struct mpq_video_feed_info video_info;
|
||||
struct mpq_audio_feed_info audio_info;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -509,6 +542,7 @@ struct mpq_demux {
|
||||
enum sdmx_log_level sdmx_log_level;
|
||||
|
||||
struct timespec last_notification_time;
|
||||
int ts_packet_timestamp_source;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -879,11 +913,12 @@ struct dvb_demux_feed *mpq_dmx_peer_rec_feed(struct dvb_demux_feed *feed);
|
||||
/**
|
||||
* mpq_dmx_decoder_eos_cmd() - Report EOS event to the mpq_streambuffer
|
||||
*
|
||||
* @mpq_feed: Video mpq_feed object for notification
|
||||
* @mpq_feed: Audio/Video mpq_feed object for notification
|
||||
* @feed_type: Feed type( Audio or Video )
|
||||
*
|
||||
* Return error code
|
||||
*/
|
||||
int mpq_dmx_decoder_eos_cmd(struct mpq_feed *mpq_feed);
|
||||
int mpq_dmx_decoder_eos_cmd(struct mpq_feed *mpq_feed, int feed_type);
|
||||
|
||||
/**
|
||||
* mpq_dmx_parse_mandatory_pes_header() - Parse non-optional PES header fields
|
||||
@@ -1023,5 +1058,66 @@ int mpq_dmx_get_param_scramble_even(void);
|
||||
/* Return the common module parameter mpq_sdmx_scramble_default_discard */
|
||||
int mpq_dmx_get_param_scramble_default_discard(void);
|
||||
|
||||
/* APIs for Audio stream buffers interface -- Added for broadcase use case */
|
||||
/*
|
||||
* The Audio/Video drivers (or consumers) require the stream_buffer information
|
||||
* for consuming packet headers and compressed AV data from the
|
||||
* ring buffer filled by demux driver which is the producer
|
||||
*/
|
||||
struct mpq_streambuffer *consumer_audio_streambuffer(int dmx_ts_pes_audio);
|
||||
struct mpq_streambuffer *consumer_video_streambuffer(int dmx_ts_pes_video);
|
||||
|
||||
int mpq_dmx_init_audio_feed(struct mpq_feed *mpq_feed);
|
||||
|
||||
int mpq_dmx_terminate_audio_feed(struct mpq_feed *mpq_feed);
|
||||
|
||||
int mpq_dmx_parse_remaining_audio_pes_header(
|
||||
struct dvb_demux_feed *feed,
|
||||
struct mpq_audio_feed_info *feed_data,
|
||||
struct pes_packet_header *pes_header,
|
||||
const u8 *buf,
|
||||
u32 *ts_payload_offset,
|
||||
int *bytes_avail);
|
||||
|
||||
static inline void mpq_dmx_save_audio_pts_dts(
|
||||
struct mpq_audio_feed_info *feed_data)
|
||||
{
|
||||
if (feed_data->new_info_exists) {
|
||||
feed_data->saved_pts_dts_info.pts_exist =
|
||||
feed_data->new_pts_dts_info.pts_exist;
|
||||
feed_data->saved_pts_dts_info.pts =
|
||||
feed_data->new_pts_dts_info.pts;
|
||||
feed_data->saved_pts_dts_info.dts_exist =
|
||||
feed_data->new_pts_dts_info.dts_exist;
|
||||
feed_data->saved_pts_dts_info.dts =
|
||||
feed_data->new_pts_dts_info.dts;
|
||||
|
||||
feed_data->new_info_exists = 0;
|
||||
feed_data->saved_info_used = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* mpq_dmx_process_audio_packet - Assemble Audio PES data and output to
|
||||
* stream buffer connected to decoder.
|
||||
*/
|
||||
int mpq_dmx_process_audio_packet(struct dvb_demux_feed *feed, const u8 *buf);
|
||||
|
||||
static inline void mpq_dmx_write_audio_pts_dts(
|
||||
struct mpq_audio_feed_info *feed_data,
|
||||
struct dmx_pts_dts_info *info)
|
||||
{
|
||||
if (!feed_data->saved_info_used) {
|
||||
info->pts_exist = feed_data->saved_pts_dts_info.pts_exist;
|
||||
info->pts = feed_data->saved_pts_dts_info.pts;
|
||||
info->dts_exist = feed_data->saved_pts_dts_info.dts_exist;
|
||||
info->dts = feed_data->saved_pts_dts_info.dts;
|
||||
|
||||
feed_data->saved_info_used = 1;
|
||||
} else {
|
||||
info->pts_exist = 0;
|
||||
info->dts_exist = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _MPQ_DMX_PLUGIN_COMMON_H */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -1634,6 +1634,9 @@ static int mpq_tspp_dmx_write_to_decoder(
|
||||
if (dvb_dmx_is_video_feed(feed))
|
||||
return mpq_dmx_process_video_packet(feed, buf);
|
||||
|
||||
if (dvb_dmx_is_audio_feed(feed))
|
||||
return mpq_dmx_process_audio_packet(feed, buf);
|
||||
|
||||
if (dvb_dmx_is_pcr_feed(feed))
|
||||
return mpq_dmx_process_pcr_packet(feed, buf);
|
||||
|
||||
@@ -1663,7 +1666,7 @@ static int mpq_tspp_dmx_get_caps(struct dmx_demux *demux,
|
||||
|
||||
caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_DECODER_DATA |
|
||||
DMX_CAP_TS_INSERTION | DMX_CAP_VIDEO_INDEXING |
|
||||
DMX_CAP_AUTO_BUFFER_FLUSH;
|
||||
DMX_CAP_AUDIO_DECODER_DATA | DMX_CAP_AUTO_BUFFER_FLUSH;
|
||||
caps->recording_max_video_pids_indexed = 0;
|
||||
caps->num_decoders = MPQ_ADAPTER_MAX_NUM_OF_INTERFACES;
|
||||
caps->num_demux_devices = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
|
||||
@@ -1753,6 +1756,8 @@ static int mpq_tspp_dmx_get_stc(struct dmx_demux *demux, unsigned int num,
|
||||
{
|
||||
enum tspp_source source;
|
||||
u32 tcr_counter;
|
||||
u64 avtimer_stc = 0;
|
||||
int tts_source = 0;
|
||||
|
||||
if (!demux || !stc || !base)
|
||||
return -EINVAL;
|
||||
@@ -1764,11 +1769,18 @@ static int mpq_tspp_dmx_get_stc(struct dmx_demux *demux, unsigned int num,
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
tspp_get_ref_clk_counter(0, source, &tcr_counter);
|
||||
|
||||
*stc = ((u64)tcr_counter) * 256; /* conversion to 27MHz */
|
||||
*base = 300; /* divisor to get 90KHz clock from stc value */
|
||||
if (tspp_get_tts_source(0, &tts_source) < 0)
|
||||
tts_source = TSIF_TTS_TCR;
|
||||
|
||||
if (tts_source != TSIF_TTS_LPASS_TIMER) {
|
||||
tspp_get_ref_clk_counter(0, source, &tcr_counter);
|
||||
*stc = ((u64)tcr_counter) * 256; /* conversion to 27MHz */
|
||||
*base = 300; /* divisor to get 90KHz clock from stc value */
|
||||
} else {
|
||||
if (tspp_get_lpass_time_counter(0, source, &avtimer_stc) < 0)
|
||||
return -EINVAL;
|
||||
*stc = avtimer_stc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1840,6 +1852,10 @@ static int mpq_tspp_dmx_init(
|
||||
/* Extend dvb-demux debugfs with TSPP statistics. */
|
||||
mpq_dmx_init_debugfs_entries(mpq_demux);
|
||||
|
||||
/* Get the TSIF TTS info */
|
||||
if (tspp_get_tts_source(0, &mpq_demux->ts_packet_timestamp_source) < 0)
|
||||
mpq_demux->ts_packet_timestamp_source = TSIF_TTS_TCR;
|
||||
|
||||
return 0;
|
||||
|
||||
init_failed_dmx_release:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -27,12 +27,24 @@ enum mpq_adapter_stream_if {
|
||||
/** Interface holding stream-buffer for video1 stream */
|
||||
MPQ_ADAPTER_VIDEO1_STREAM_IF = 1,
|
||||
|
||||
/** Interface holding stream-buffer for video1 stream */
|
||||
/** Interface holding stream-buffer for video2 stream */
|
||||
MPQ_ADAPTER_VIDEO2_STREAM_IF = 2,
|
||||
|
||||
/** Interface holding stream-buffer for video1 stream */
|
||||
/** Interface holding stream-buffer for video3 stream */
|
||||
MPQ_ADAPTER_VIDEO3_STREAM_IF = 3,
|
||||
|
||||
/** Interface holding stream-buffer for audio0 stream */
|
||||
MPQ_ADAPTER_AUDIO0_STREAM_IF = 4,
|
||||
|
||||
/** Interface holding stream-buffer for audio1 stream */
|
||||
MPQ_ADAPTER_AUDIO1_STREAM_IF = 5,
|
||||
|
||||
/** Interface holding stream-buffer for audio2 stream */
|
||||
MPQ_ADAPTER_AUDIO2_STREAM_IF = 6,
|
||||
|
||||
/** Interface holding stream-buffer for audio3 stream */
|
||||
MPQ_ADAPTER_AUDIO3_STREAM_IF = 7,
|
||||
|
||||
/** Maximum number of interfaces holding stream-buffers */
|
||||
MPQ_ADAPTER_MAX_NUM_OF_INTERFACES,
|
||||
};
|
||||
@@ -113,6 +125,17 @@ struct mpq_adapter_video_meta_data {
|
||||
} info;
|
||||
} __packed;
|
||||
|
||||
/** The meta-data used for audio interface */
|
||||
struct mpq_adapter_audio_meta_data {
|
||||
/** meta-data packet type */
|
||||
enum dmx_packet_type packet_type;
|
||||
|
||||
/** packet-type specific information */
|
||||
union {
|
||||
struct dmx_pes_packet_info pes;
|
||||
struct dmx_marker_info marker;
|
||||
} info;
|
||||
} __packed;
|
||||
|
||||
/** Callback function to notify on registrations of specific interfaces */
|
||||
typedef void (*mpq_adapter_stream_if_callback)(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include "dvb_ringbuffer.h"
|
||||
|
||||
|
||||
/**
|
||||
* DOC: MPQ Stream Buffer
|
||||
*
|
||||
@@ -459,4 +458,37 @@ ssize_t mpq_streambuffer_metadata_free(struct mpq_streambuffer *sbuff);
|
||||
*/
|
||||
int mpq_streambuffer_flush(struct mpq_streambuffer *sbuff);
|
||||
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* Consumer or AV Decoder Stream Interface to Ring Buffer
|
||||
* ------------------------------------------------------
|
||||
* Producer is Demux Driver
|
||||
* ------------------------
|
||||
*
|
||||
* call from Audio/Video Decoder Driver to find Audio/Video
|
||||
* streambuffer AV handles, "DMX_PES_AUDIO0 through 3" or
|
||||
* DMX_PES_VIDEO0 through 3" interfaces corresponding to 4 programs.
|
||||
*/
|
||||
|
||||
/* call from Audio/Video Decoder Driver via POLLING to consume
|
||||
* Headers and Compressed data from ring buffer using streambuffer handle.
|
||||
* hdrdata[] and cdata[] buffers have to be malloc'd by consumer
|
||||
*
|
||||
* --------------------------
|
||||
* Consumer Calling Sequence
|
||||
* --------------------------
|
||||
* Find the streambuffer corresponding to a DMX TS PES stream instance.
|
||||
* 1. consumer_audio_streambuffer() or consumer_video_streambuffer()
|
||||
* Process the packet headers if required.
|
||||
* 2. mpq_read_new_packet_hdr_data()
|
||||
* Process the compressed data by forwarding to AV decoder.
|
||||
* 3. mpq_read_new_packet_compressed_data()
|
||||
* Dispose the packet.
|
||||
* 4. mpq_dispose_new_packet_read()
|
||||
*
|
||||
* The Audio/Video drivers (or consumers) require the stream_buffer information
|
||||
* for consuming packet headers and compressed AV data from the
|
||||
* ring buffer filled by demux driver which is the producer
|
||||
*/
|
||||
|
||||
#endif /* _MPQ_STREAM_BUFFER_H */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -70,6 +70,11 @@ struct tspp_select_source {
|
||||
int enable_inverse;
|
||||
};
|
||||
|
||||
enum tsif_tts_source {
|
||||
TSIF_TTS_TCR = 0, /* Time stamps from TCR counter */
|
||||
TSIF_TTS_LPASS_TIMER /* Time stamps from AV/Qtimer Timer */
|
||||
};
|
||||
|
||||
typedef void (tspp_notifier)(int channel_id, void *user);
|
||||
typedef void* (tspp_allocator)(int channel_id, u32 size,
|
||||
phys_addr_t *phys_base, void *user);
|
||||
@@ -96,4 +101,8 @@ int tspp_allocate_buffers(u32 dev, u32 channel_id, u32 count,
|
||||
u32 size, u32 int_freq, tspp_allocator *alloc,
|
||||
tspp_memfree *memfree, void *user);
|
||||
|
||||
int tspp_get_tts_source(u32 dev, int *tts_source);
|
||||
int tspp_get_lpass_time_counter(u32 dev, enum tspp_source source,
|
||||
u64 *lpass_time_counter);
|
||||
|
||||
#endif /* _MSM_TSPP_H_ */
|
||||
|
||||
@@ -148,6 +148,9 @@ enum dmx_video_codec {
|
||||
#define DMX_IDX_VC1_FRAME_END 0x02000000
|
||||
#define DMX_IDX_H264_ACCESS_UNIT_DEL 0x04000000
|
||||
#define DMX_IDX_H264_SEI 0x08000000
|
||||
#define DMX_IDX_H264_IDR_ISLICE_START 0x10000000
|
||||
#define DMX_IDX_H264_NON_IDR_PSLICE_START 0x20000000
|
||||
#define DMX_IDX_H264_NON_IDR_BSLICE_START 0x40000000
|
||||
|
||||
struct dmx_pes_filter_params
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user