tspp: improve tspp_open_stream/tspp_close_stream behavior
The TSPP driver's kernel API supports opening and closing a TSPP stream using the tspp_open_stream/tspp_close_stream API functions. This commit fixes a few minor issues with the behavior and usage of this API. tspp_open_stream and tspp_close_stream were fixed to connect/disconnect the appropriate TSIF source based on the TSIF reference count. The call to tspp_close_stream from within tspp_close_channel was removed, since a kernel driver that uses the TSPP driver API is expected to call tspp_close_stream explicitly, and not rely on the TSPP driver to close the stream implicitly when the channel is closed. An ioctl was added to allow user-space application to close the stream. Change-Id: If49b440d9d83c8bba54aeabc18e8f06b3cc11b3e Signed-off-by: Liron Kuch <lkuch@codeaurora.org>
This commit is contained in:
parent
4a995e781b
commit
c2392df88a
|
@ -1433,8 +1433,8 @@ static int mpq_tspp_dmx_remove_channel(struct dvb_demux_feed *feed)
|
||||||
if (*channel_ref_count == 0) {
|
if (*channel_ref_count == 0) {
|
||||||
/* 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_stream(0, channel_id);
|
tspp_close_stream(0, channel_id);
|
||||||
|
tspp_close_channel(0, channel_id);
|
||||||
atomic_set(data_cnt, 0);
|
atomic_set(data_cnt, 0);
|
||||||
|
|
||||||
if (allocation_mode == MPQ_DMX_TSPP_CONTIGUOUS_PHYS_ALLOC)
|
if (allocation_mode == MPQ_DMX_TSPP_CONTIGUOUS_PHYS_ALLOC)
|
||||||
|
|
|
@ -1319,10 +1319,12 @@ int tspp_open_stream(u32 dev, u32 channel_id,
|
||||||
pr_err("tspp: error starting tsif0");
|
pr_err("tspp: error starting tsif0");
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
val = readl_relaxed(pdev->base + TSPP_CONTROL);
|
if (pdev->tsif[0].ref_count == 1) {
|
||||||
writel_relaxed(val & ~TSPP_CONTROL_TSP_TSIF0_SRC_DIS,
|
val = readl_relaxed(pdev->base + TSPP_CONTROL);
|
||||||
pdev->base + TSPP_CONTROL);
|
writel_relaxed(val & ~TSPP_CONTROL_TSP_TSIF0_SRC_DIS,
|
||||||
wmb();
|
pdev->base + TSPP_CONTROL);
|
||||||
|
wmb();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TSPP_SOURCE_TSIF1:
|
case TSPP_SOURCE_TSIF1:
|
||||||
if (tspp_config_gpios(pdev, channel->src, 1) != 0) {
|
if (tspp_config_gpios(pdev, channel->src, 1) != 0) {
|
||||||
|
@ -1334,10 +1336,12 @@ int tspp_open_stream(u32 dev, u32 channel_id,
|
||||||
pr_err("tspp: error starting tsif1");
|
pr_err("tspp: error starting tsif1");
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
val = readl_relaxed(pdev->base + TSPP_CONTROL);
|
if (pdev->tsif[1].ref_count == 1) {
|
||||||
writel_relaxed(val & ~TSPP_CONTROL_TSP_TSIF1_SRC_DIS,
|
val = readl_relaxed(pdev->base + TSPP_CONTROL);
|
||||||
pdev->base + TSPP_CONTROL);
|
writel_relaxed(val & ~TSPP_CONTROL_TSP_TSIF1_SRC_DIS,
|
||||||
wmb();
|
pdev->base + TSPP_CONTROL);
|
||||||
|
wmb();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TSPP_SOURCE_MEM:
|
case TSPP_SOURCE_MEM:
|
||||||
break;
|
break;
|
||||||
|
@ -1363,6 +1367,7 @@ EXPORT_SYMBOL(tspp_open_stream);
|
||||||
int tspp_close_stream(u32 dev, u32 channel_id)
|
int tspp_close_stream(u32 dev, u32 channel_id)
|
||||||
{
|
{
|
||||||
u32 val;
|
u32 val;
|
||||||
|
u32 prev_ref_count;
|
||||||
struct tspp_device *pdev;
|
struct tspp_device *pdev;
|
||||||
struct tspp_channel *channel;
|
struct tspp_channel *channel;
|
||||||
|
|
||||||
|
@ -1379,23 +1384,30 @@ int tspp_close_stream(u32 dev, u32 channel_id)
|
||||||
|
|
||||||
switch (channel->src) {
|
switch (channel->src) {
|
||||||
case TSPP_SOURCE_TSIF0:
|
case TSPP_SOURCE_TSIF0:
|
||||||
|
prev_ref_count = pdev->tsif[0].ref_count;
|
||||||
tspp_stop_tsif(&pdev->tsif[0]);
|
tspp_stop_tsif(&pdev->tsif[0]);
|
||||||
if (tspp_config_gpios(pdev, channel->src, 0) != 0)
|
if (tspp_config_gpios(pdev, channel->src, 0) != 0)
|
||||||
pr_err("tspp: error disabling tsif0 GPIOs\n");
|
pr_err("tspp: error disabling tsif0 GPIOs\n");
|
||||||
|
|
||||||
val = readl_relaxed(pdev->base + TSPP_CONTROL);
|
if (prev_ref_count == 1) {
|
||||||
writel_relaxed(val | TSPP_CONTROL_TSP_TSIF0_SRC_DIS,
|
val = readl_relaxed(pdev->base + TSPP_CONTROL);
|
||||||
pdev->base + TSPP_CONTROL);
|
writel_relaxed(val | TSPP_CONTROL_TSP_TSIF0_SRC_DIS,
|
||||||
wmb();
|
pdev->base + TSPP_CONTROL);
|
||||||
|
wmb();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TSPP_SOURCE_TSIF1:
|
case TSPP_SOURCE_TSIF1:
|
||||||
|
prev_ref_count = pdev->tsif[1].ref_count;
|
||||||
tspp_stop_tsif(&pdev->tsif[1]);
|
tspp_stop_tsif(&pdev->tsif[1]);
|
||||||
if (tspp_config_gpios(pdev, channel->src, 0) != 0)
|
if (tspp_config_gpios(pdev, channel->src, 0) != 0)
|
||||||
pr_err("tspp: error disabling tsif0 GPIOs\n");
|
pr_err("tspp: error disabling tsif0 GPIOs\n");
|
||||||
|
|
||||||
val = readl_relaxed(pdev->base + TSPP_CONTROL);
|
if (prev_ref_count == 1) {
|
||||||
writel_relaxed(val | TSPP_CONTROL_TSP_TSIF1_SRC_DIS,
|
val = readl_relaxed(pdev->base + TSPP_CONTROL);
|
||||||
pdev->base + TSPP_CONTROL);
|
writel_relaxed(val | TSPP_CONTROL_TSP_TSIF1_SRC_DIS,
|
||||||
|
pdev->base + TSPP_CONTROL);
|
||||||
|
wmb();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TSPP_SOURCE_MEM:
|
case TSPP_SOURCE_MEM:
|
||||||
break;
|
break;
|
||||||
|
@ -1595,9 +1607,6 @@ int tspp_close_channel(u32 dev, u32 channel_id)
|
||||||
}
|
}
|
||||||
channel->filter_count = 0;
|
channel->filter_count = 0;
|
||||||
|
|
||||||
/* stop the stream */
|
|
||||||
tspp_close_stream(dev, channel->id);
|
|
||||||
|
|
||||||
/* disconnect the bam */
|
/* disconnect the bam */
|
||||||
if (sps_disconnect(channel->pipe) != 0)
|
if (sps_disconnect(channel->pipe) != 0)
|
||||||
pr_warn("tspp: Error freeing sps endpoint (%i)", channel->id);
|
pr_warn("tspp: Error freeing sps endpoint (%i)", channel->id);
|
||||||
|
@ -2435,7 +2444,7 @@ static long tspp_ioctl(struct file *filp,
|
||||||
channel = filp->private_data;
|
channel = filp->private_data;
|
||||||
dev = channel->pdev->pdev->id;
|
dev = channel->pdev->pdev->id;
|
||||||
|
|
||||||
if (!param1)
|
if ((param0 != TSPP_IOCTL_CLOSE_STREAM) && !param1)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
switch (param0) {
|
switch (param0) {
|
||||||
|
@ -2502,6 +2511,9 @@ static long tspp_ioctl(struct file *filp,
|
||||||
sizeof(struct tspp_buffer)) == 0)
|
sizeof(struct tspp_buffer)) == 0)
|
||||||
rc = tspp_set_buffer_size(channel, &b);
|
rc = tspp_set_buffer_size(channel, &b);
|
||||||
break;
|
break;
|
||||||
|
case TSPP_IOCTL_CLOSE_STREAM:
|
||||||
|
rc = tspp_close_stream(dev, channel->id);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
pr_err("tspp: Unknown ioctl %i", param0);
|
pr_err("tspp: Unknown ioctl %i", param0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,5 +88,7 @@ struct tspp_buffer {
|
||||||
_IOW(TSPP_IOCTL_BASE, 5, struct tspp_system_keys)
|
_IOW(TSPP_IOCTL_BASE, 5, struct tspp_system_keys)
|
||||||
#define TSPP_IOCTL_BUFFER_SIZE \
|
#define TSPP_IOCTL_BUFFER_SIZE \
|
||||||
_IOW(TSPP_IOCTL_BASE, 6, struct tspp_buffer)
|
_IOW(TSPP_IOCTL_BASE, 6, struct tspp_buffer)
|
||||||
|
#define TSPP_IOCTL_CLOSE_STREAM \
|
||||||
|
_IO(TSPP_IOCTL_BASE, 7)
|
||||||
|
|
||||||
#endif /* _TSPP_H_ */
|
#endif /* _TSPP_H_ */
|
||||||
|
|
Loading…
Reference in New Issue