media: platform: msm: Add demux support for mediabox

Add audio stream buffer interface to write the Audio demux data
to audio decoder buffers. Add support in TSIF driver to append
LPASS subsystem time stamps to Transport Stream packets in TSIF HW.
This is required for AV sync & clock recovery handling
for mediabox project based on LE platform.

CR's-Fixed: 2005724
Change-Id: I39d2544e958c31ff1abdd2ad77412a87bc2a189b
Signed-off-by: Udaya Bhaskara Reddy Mallavarapu <udaym@codeaurora.org>
Signed-off-by: Arun Menon <avmenon@codeaurora.org>
This commit is contained in:
Udaya Bhaskara Reddy Mallavarapu 2017-01-17 10:20:00 +05:30 committed by Gerrit - the friendly Code Review server
parent 3a7e752617
commit 79db7c3476
12 changed files with 2098 additions and 140 deletions

View file

@ -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;
}

View file

@ -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.

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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 */

View file

@ -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:

View file

@ -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)(

View file

@ -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 */

View file

@ -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_ */

View file

@ -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
{