tspp: Add option to inverse tsif signals
TSIF signals (clock, data, enable and sync) may be configured
to be inversed at TSPP unit input. This is useful in case
TSIF signals from external units need to be inversed.
Change-Id: I4f0bfdc58fb8658dbf10fe3805b8787f9d36aeca
Signed-off-by: Hamad Kadmany <hkadmany@codeaurora.org>
Signed-off-by: Neha Pandey <nehap@codeaurora.org>
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
index e4f00c0..68af7e1 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
@@ -272,23 +272,27 @@
static int mpq_tspp_dmx_add_channel(struct dvb_demux_feed *feed)
{
struct mpq_demux *mpq_demux = feed->demux->priv;
- enum tspp_source tspp_source;
+ struct tspp_select_source tspp_source;
struct tspp_filter tspp_filter;
int tsif;
int ret;
int channel_id;
int *channel_ref_count;
- enum tspp_tsif_mode mode;
+
+ tspp_source.clk_inverse = 0;
+ tspp_source.data_inverse = 0;
+ tspp_source.sync_inverse = 0;
+ tspp_source.enable_inverse = 0;
/* determine the TSIF we are reading from */
if (mpq_demux->source == DMX_SOURCE_FRONT0) {
tsif = 0;
- tspp_source = TSPP_SOURCE_TSIF0;
- mode = (enum tspp_tsif_mode)tsif0_mode;
+ tspp_source.source = TSPP_SOURCE_TSIF0;
+ tspp_source.mode = (enum tspp_tsif_mode)tsif0_mode;
} else if (mpq_demux->source == DMX_SOURCE_FRONT1) {
tsif = 1;
- tspp_source = TSPP_SOURCE_TSIF1;
- mode = (enum tspp_tsif_mode)tsif1_mode;
+ tspp_source.source = TSPP_SOURCE_TSIF1;
+ tspp_source.mode = (enum tspp_tsif_mode)tsif1_mode;
} else {
/* invalid source */
MPQ_DVB_ERR_PRINT(
@@ -341,13 +345,13 @@
}
/* set TSPP source */
- ret = tspp_open_stream(0, channel_id, tspp_source, mode);
+ ret = tspp_open_stream(0, channel_id, &tspp_source);
if (ret < 0) {
MPQ_DVB_ERR_PRINT(
"%s: tspp_select_source(%d,%d) failed (%d)\n",
__func__,
channel_id,
- tspp_source,
+ tspp_source.source,
ret);
goto add_channel_close_ch;
@@ -418,7 +422,7 @@
* accordingly.
*/
tspp_filter.mode = TSPP_MODE_RAW;
- tspp_filter.source = tspp_source;
+ tspp_filter.source = tspp_source.source;
tspp_filter.decrypt = 0;
ret = tspp_add_filter(0, channel_id, &tspp_filter);
if (ret < 0) {
@@ -553,6 +557,7 @@
/* channel is not used any more, release it */
tspp_unregister_notification(0, channel_id);
tspp_close_channel(0, channel_id);
+ tspp_close_stream(0, channel_id);
}
mutex_unlock(&mpq_dmx_tspp_info.tsif[tsif].mutex);
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index 1792104..8a1e0da 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -323,6 +323,10 @@
u32 time_limit;
u32 ref_count;
enum tspp_tsif_mode mode;
+ int clock_inverse;
+ int data_inverse;
+ int sync_inverse;
+ int enable_inverse;
/* debugfs */
struct dentry *dent_tsif;
@@ -698,6 +702,19 @@
if (start_hardware) {
ctl = TSIF_STS_CTL_EN_IRQ |
TSIF_STS_CTL_EN_DM;
+
+ if (tsif_device->clock_inverse)
+ ctl |= TSIF_STS_CTL_INV_CLOCK;
+
+ if (tsif_device->data_inverse)
+ ctl |= TSIF_STS_CTL_INV_DATA;
+
+ if (tsif_device->sync_inverse)
+ ctl |= TSIF_STS_CTL_INV_SYNC;
+
+ if (tsif_device->enable_inverse)
+ ctl |= TSIF_STS_CTL_INV_ENABLE;
+
switch (tsif_device->mode) {
case TSPP_TSIF_MODE_LOOPBACK:
ctl |= TSIF_STS_CTL_EN_NULL |
@@ -852,6 +869,10 @@
pdev->tsif[i].ref_count = 1; /* allows stopping hw */
tspp_stop_tsif(&pdev->tsif[i]); /* will reset ref_count to 0 */
pdev->tsif[i].time_limit = TSPP_TSIF_DEFAULT_TIME_LIMIT;
+ pdev->tsif[i].clock_inverse = 0;
+ pdev->tsif[i].data_inverse = 0;
+ pdev->tsif[i].sync_inverse = 0;
+ pdev->tsif[i].enable_inverse = 0;
}
writel_relaxed(TSPP_RST_RESET, pdev->base + TSPP_RST);
wmb();
@@ -913,7 +934,7 @@
}
/* open the stream */
- tspp_open_stream(dev, channel_id, src->source, src->mode);
+ tspp_open_stream(dev, channel_id, src);
return 0;
}
@@ -1011,14 +1032,37 @@
channel->pdev->tsif[index].mode = mode;
}
+static void tspp_set_signal_inversion(struct tspp_channel *channel,
+ int clock_inverse, int data_inverse,
+ int sync_inverse, int enable_inverse)
+{
+ int index;
+
+ switch (channel->src) {
+ case TSPP_SOURCE_TSIF0:
+ index = 0;
+ break;
+ case TSPP_SOURCE_TSIF1:
+ index = 1;
+ break;
+ default:
+ return;
+ }
+ channel->pdev->tsif[index].clock_inverse = clock_inverse;
+ channel->pdev->tsif[index].data_inverse = data_inverse;
+ channel->pdev->tsif[index].sync_inverse = sync_inverse;
+ channel->pdev->tsif[index].enable_inverse = enable_inverse;
+}
+
/*** TSPP API functions ***/
-int tspp_open_stream(u32 dev, u32 channel_id, enum tspp_source src, enum tspp_tsif_mode mode)
+int tspp_open_stream(u32 dev, u32 channel_id, struct tspp_select_source *source)
{
u32 val;
struct tspp_device *pdev;
struct tspp_channel *channel;
- TSPP_DEBUG("tspp_open_stream %i %i %i %i", dev, channel_id, src, mode);
+ TSPP_DEBUG("tspp_open_stream %i %i %i %i",
+ dev, channel_id, source->source, source->mode);
if (dev >= TSPP_MAX_DEVICES) {
pr_err("tspp: device id out of range");
return -ENODEV;
@@ -1035,10 +1079,13 @@
return -ENODEV;
}
channel = &pdev->channels[channel_id];
- channel->src = src;
- tspp_set_tsif_mode(channel, mode);
+ channel->src = source->source;
+ tspp_set_tsif_mode(channel, source->mode);
+ tspp_set_signal_inversion(channel, source->clk_inverse,
+ source->data_inverse, source->sync_inverse,
+ source->enable_inverse);
- switch (src) {
+ switch (source->source) {
case TSPP_SOURCE_TSIF0:
/* make sure TSIF0 is running & enabled */
if (tspp_start_tsif(&pdev->tsif[0]) != 0) {
@@ -1064,7 +1111,8 @@
case TSPP_SOURCE_MEM:
break;
default:
- pr_err("tspp: channel %i invalid source %i", channel->id, src);
+ pr_err("tspp: channel %i invalid source %i",
+ channel->id, source->source);
return -EBUSY;
}