diff --git a/Documentation/arm/msm/tspp.txt b/Documentation/arm/msm/tspp.txt index a56f014b3ca..d7702601951 100644 --- a/Documentation/arm/msm/tspp.txt +++ b/Documentation/arm/msm/tspp.txt @@ -157,13 +157,12 @@ the application is able. API === -int tspp_open_stream(tspp_device *dev, void *stream, void *channel, tspp_mode - mode); -int tspp_close_stream(tspp_device *dev, void *stream); -int tspp_open_channel(tspp_device *dev, int dest, int bufsize, void *channel); -int tspp_close_channel(tspp_device *dev, void *channel); -int tspp_register_filter(tspp_device *dev, void *channel, tspp_filter *filter); -int tspp_unregister_filter(tspp_device *dev, void *channel, int pid); +int tspp_open_stream(u32 dev, u32 channel, struct tspp_select_source *source); +int tspp_close_stream(u32 dev, u32 channel); +int tspp_open_channel(u32 dev, u32 channel); +int tspp_close_channelu(32 dev, u32 channel); +int tspp_add_filter(u32 dev, u32 channel, struct tspp_filter *filter); +int tspp_remove_filter(u32 dev, u32 channel, struct tspp_filter *filter); Refer to chrdev implementation in kernel/drivers/misc/tspp.c for an example of how to use this api. diff --git a/arch/arm/mach-msm/include/mach/msm_tspp.h b/arch/arm/mach-msm/include/mach/msm_tspp.h index 48be504e8e5..5395b88ccf1 100644 --- a/arch/arm/mach-msm/include/mach/msm_tspp.h +++ b/arch/arm/mach-msm/include/mach/msm_tspp.h @@ -35,8 +35,8 @@ typedef void* (tspp_allocator)(int channel, int size, u32 *phys_base, void *user); /* Kernel 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); int tspp_close_stream(u32 dev, u32 channel_id); int tspp_open_channel(u32 dev, u32 channel_id); int tspp_close_channel(u32 dev, u32 channel_id); 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 e4f00c0b9c2..68af7e187de 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 void mpq_tspp_callback(int channel_id, void *user) 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 @@ static int mpq_tspp_dmx_add_channel(struct dvb_demux_feed *feed) } /* 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 @@ static int mpq_tspp_dmx_add_channel(struct dvb_demux_feed *feed) * 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 @@ static int mpq_tspp_dmx_remove_channel(struct dvb_demux_feed *feed) /* 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 1792104303f..8a1e0da6b82 100644 --- a/drivers/misc/tspp.c +++ b/drivers/misc/tspp.c @@ -323,6 +323,10 @@ struct tspp_tsif_device { 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 @@ static int tspp_start_tsif(struct tspp_tsif_device *tsif_device) 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 @@ static int tspp_global_reset(struct tspp_device *pdev) 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 @@ static int tspp_select_source(u32 dev, u32 channel_id, } /* 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 @@ static void tspp_set_tsif_mode(struct tspp_channel *channel, 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 @@ int tspp_open_stream(u32 dev, u32 channel_id, enum tspp_source src, enum tspp_ts 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 @@ int tspp_open_stream(u32 dev, u32 channel_id, enum tspp_source src, enum tspp_ts 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; } diff --git a/include/linux/tspp.h b/include/linux/tspp.h index 3f0cc81bcc7..551fbb090aa 100644 --- a/include/linux/tspp.h +++ b/include/linux/tspp.h @@ -42,6 +42,10 @@ struct tspp_filter { struct tspp_select_source { enum tspp_source source; enum tspp_tsif_mode mode; + int clk_inverse; + int data_inverse; + int sync_inverse; + int enable_inverse; }; struct tspp_pid {