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>
This commit is contained in:
Hamad Kadmany
2012-10-23 14:15:41 +02:00
committed by Stephen Boyd
parent 408f458d7b
commit df7e43cddf
5 changed files with 81 additions and 25 deletions

View File

@@ -157,13 +157,12 @@ the application is able.
API API
=== ===
int tspp_open_stream(tspp_device *dev, void *stream, void *channel, tspp_mode int tspp_open_stream(u32 dev, u32 channel, struct tspp_select_source *source);
mode); int tspp_close_stream(u32 dev, u32 channel);
int tspp_close_stream(tspp_device *dev, void *stream); int tspp_open_channel(u32 dev, u32 channel);
int tspp_open_channel(tspp_device *dev, int dest, int bufsize, void *channel); int tspp_close_channelu(32 dev, u32 channel);
int tspp_close_channel(tspp_device *dev, void *channel); int tspp_add_filter(u32 dev, u32 channel, struct tspp_filter *filter);
int tspp_register_filter(tspp_device *dev, void *channel, tspp_filter *filter); int tspp_remove_filter(u32 dev, u32 channel, struct tspp_filter *filter);
int tspp_unregister_filter(tspp_device *dev, void *channel, int pid);
Refer to chrdev implementation in kernel/drivers/misc/tspp.c for an example of Refer to chrdev implementation in kernel/drivers/misc/tspp.c for an example of
how to use this api. how to use this api.

View File

@@ -35,8 +35,8 @@ typedef void* (tspp_allocator)(int channel, int size,
u32 *phys_base, void *user); u32 *phys_base, void *user);
/* Kernel API functions */ /* Kernel API functions */
int tspp_open_stream(u32 dev, u32 channel_id, enum tspp_source src, int tspp_open_stream(u32 dev, u32 channel_id,
enum tspp_tsif_mode mode); struct tspp_select_source *source);
int tspp_close_stream(u32 dev, u32 channel_id); int tspp_close_stream(u32 dev, u32 channel_id);
int tspp_open_channel(u32 dev, u32 channel_id); int tspp_open_channel(u32 dev, u32 channel_id);
int tspp_close_channel(u32 dev, u32 channel_id); int tspp_close_channel(u32 dev, u32 channel_id);

View File

@@ -272,23 +272,27 @@ static void mpq_tspp_callback(int channel_id, void *user)
static int mpq_tspp_dmx_add_channel(struct dvb_demux_feed *feed) static int mpq_tspp_dmx_add_channel(struct dvb_demux_feed *feed)
{ {
struct mpq_demux *mpq_demux = feed->demux->priv; struct mpq_demux *mpq_demux = feed->demux->priv;
enum tspp_source tspp_source; struct tspp_select_source tspp_source;
struct tspp_filter tspp_filter; struct tspp_filter tspp_filter;
int tsif; int tsif;
int ret; int ret;
int channel_id; int channel_id;
int *channel_ref_count; 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 */ /* determine the TSIF we are reading from */
if (mpq_demux->source == DMX_SOURCE_FRONT0) { if (mpq_demux->source == DMX_SOURCE_FRONT0) {
tsif = 0; tsif = 0;
tspp_source = TSPP_SOURCE_TSIF0; tspp_source.source = TSPP_SOURCE_TSIF0;
mode = (enum tspp_tsif_mode)tsif0_mode; tspp_source.mode = (enum tspp_tsif_mode)tsif0_mode;
} else if (mpq_demux->source == DMX_SOURCE_FRONT1) { } else if (mpq_demux->source == DMX_SOURCE_FRONT1) {
tsif = 1; tsif = 1;
tspp_source = TSPP_SOURCE_TSIF1; tspp_source.source = TSPP_SOURCE_TSIF1;
mode = (enum tspp_tsif_mode)tsif1_mode; tspp_source.mode = (enum tspp_tsif_mode)tsif1_mode;
} else { } else {
/* invalid source */ /* invalid source */
MPQ_DVB_ERR_PRINT( MPQ_DVB_ERR_PRINT(
@@ -341,13 +345,13 @@ static int mpq_tspp_dmx_add_channel(struct dvb_demux_feed *feed)
} }
/* set TSPP source */ /* 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) { if (ret < 0) {
MPQ_DVB_ERR_PRINT( MPQ_DVB_ERR_PRINT(
"%s: tspp_select_source(%d,%d) failed (%d)\n", "%s: tspp_select_source(%d,%d) failed (%d)\n",
__func__, __func__,
channel_id, channel_id,
tspp_source, tspp_source.source,
ret); ret);
goto add_channel_close_ch; goto add_channel_close_ch;
@@ -418,7 +422,7 @@ static int mpq_tspp_dmx_add_channel(struct dvb_demux_feed *feed)
* accordingly. * accordingly.
*/ */
tspp_filter.mode = TSPP_MODE_RAW; tspp_filter.mode = TSPP_MODE_RAW;
tspp_filter.source = tspp_source; tspp_filter.source = tspp_source.source;
tspp_filter.decrypt = 0; tspp_filter.decrypt = 0;
ret = tspp_add_filter(0, channel_id, &tspp_filter); ret = tspp_add_filter(0, channel_id, &tspp_filter);
if (ret < 0) { if (ret < 0) {
@@ -553,6 +557,7 @@ static int mpq_tspp_dmx_remove_channel(struct dvb_demux_feed *feed)
/* channel is not used any more, release it */ /* channel is not used any more, release it */
tspp_unregister_notification(0, channel_id); tspp_unregister_notification(0, channel_id);
tspp_close_channel(0, channel_id); tspp_close_channel(0, channel_id);
tspp_close_stream(0, channel_id);
} }
mutex_unlock(&mpq_dmx_tspp_info.tsif[tsif].mutex); mutex_unlock(&mpq_dmx_tspp_info.tsif[tsif].mutex);

View File

@@ -323,6 +323,10 @@ struct tspp_tsif_device {
u32 time_limit; u32 time_limit;
u32 ref_count; u32 ref_count;
enum tspp_tsif_mode mode; enum tspp_tsif_mode mode;
int clock_inverse;
int data_inverse;
int sync_inverse;
int enable_inverse;
/* debugfs */ /* debugfs */
struct dentry *dent_tsif; struct dentry *dent_tsif;
@@ -698,6 +702,19 @@ static int tspp_start_tsif(struct tspp_tsif_device *tsif_device)
if (start_hardware) { if (start_hardware) {
ctl = TSIF_STS_CTL_EN_IRQ | ctl = TSIF_STS_CTL_EN_IRQ |
TSIF_STS_CTL_EN_DM; 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) { switch (tsif_device->mode) {
case TSPP_TSIF_MODE_LOOPBACK: case TSPP_TSIF_MODE_LOOPBACK:
ctl |= TSIF_STS_CTL_EN_NULL | ctl |= TSIF_STS_CTL_EN_NULL |
@@ -852,6 +869,10 @@ static int tspp_global_reset(struct tspp_device *pdev)
pdev->tsif[i].ref_count = 1; /* allows stopping hw */ pdev->tsif[i].ref_count = 1; /* allows stopping hw */
tspp_stop_tsif(&pdev->tsif[i]); /* will reset ref_count to 0 */ 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].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); writel_relaxed(TSPP_RST_RESET, pdev->base + TSPP_RST);
wmb(); wmb();
@@ -913,7 +934,7 @@ static int tspp_select_source(u32 dev, u32 channel_id,
} }
/* open the stream */ /* open the stream */
tspp_open_stream(dev, channel_id, src->source, src->mode); tspp_open_stream(dev, channel_id, src);
return 0; return 0;
} }
@@ -1011,14 +1032,37 @@ static void tspp_set_tsif_mode(struct tspp_channel *channel,
channel->pdev->tsif[index].mode = mode; 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 ***/ /*** 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; u32 val;
struct tspp_device *pdev; struct tspp_device *pdev;
struct tspp_channel *channel; 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) { if (dev >= TSPP_MAX_DEVICES) {
pr_err("tspp: device id out of range"); pr_err("tspp: device id out of range");
return -ENODEV; return -ENODEV;
@@ -1035,10 +1079,13 @@ int tspp_open_stream(u32 dev, u32 channel_id, enum tspp_source src, enum tspp_ts
return -ENODEV; return -ENODEV;
} }
channel = &pdev->channels[channel_id]; channel = &pdev->channels[channel_id];
channel->src = src; channel->src = source->source;
tspp_set_tsif_mode(channel, mode); 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: case TSPP_SOURCE_TSIF0:
/* make sure TSIF0 is running & enabled */ /* make sure TSIF0 is running & enabled */
if (tspp_start_tsif(&pdev->tsif[0]) != 0) { if (tspp_start_tsif(&pdev->tsif[0]) != 0) {
@@ -1064,7 +1111,8 @@ int tspp_open_stream(u32 dev, u32 channel_id, enum tspp_source src, enum tspp_ts
case TSPP_SOURCE_MEM: case TSPP_SOURCE_MEM:
break; break;
default: 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; return -EBUSY;
} }

View File

@@ -42,6 +42,10 @@ struct tspp_filter {
struct tspp_select_source { struct tspp_select_source {
enum tspp_source source; enum tspp_source source;
enum tspp_tsif_mode mode; enum tspp_tsif_mode mode;
int clk_inverse;
int data_inverse;
int sync_inverse;
int enable_inverse;
}; };
struct tspp_pid { struct tspp_pid {