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:
Liron Kuch 2013-02-14 16:26:38 +02:00
parent 4a995e781b
commit c2392df88a
3 changed files with 34 additions and 20 deletions

View File

@ -1433,8 +1433,8 @@ static int mpq_tspp_dmx_remove_channel(struct dvb_demux_feed *feed)
if (*channel_ref_count == 0) {
/* 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);
tspp_close_channel(0, channel_id);
atomic_set(data_cnt, 0);
if (allocation_mode == MPQ_DMX_TSPP_CONTIGUOUS_PHYS_ALLOC)

View File

@ -1319,10 +1319,12 @@ int tspp_open_stream(u32 dev, u32 channel_id,
pr_err("tspp: error starting tsif0");
return -EBUSY;
}
val = readl_relaxed(pdev->base + TSPP_CONTROL);
writel_relaxed(val & ~TSPP_CONTROL_TSP_TSIF0_SRC_DIS,
pdev->base + TSPP_CONTROL);
wmb();
if (pdev->tsif[0].ref_count == 1) {
val = readl_relaxed(pdev->base + TSPP_CONTROL);
writel_relaxed(val & ~TSPP_CONTROL_TSP_TSIF0_SRC_DIS,
pdev->base + TSPP_CONTROL);
wmb();
}
break;
case TSPP_SOURCE_TSIF1:
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");
return -EBUSY;
}
val = readl_relaxed(pdev->base + TSPP_CONTROL);
writel_relaxed(val & ~TSPP_CONTROL_TSP_TSIF1_SRC_DIS,
pdev->base + TSPP_CONTROL);
wmb();
if (pdev->tsif[1].ref_count == 1) {
val = readl_relaxed(pdev->base + TSPP_CONTROL);
writel_relaxed(val & ~TSPP_CONTROL_TSP_TSIF1_SRC_DIS,
pdev->base + TSPP_CONTROL);
wmb();
}
break;
case TSPP_SOURCE_MEM:
break;
@ -1363,6 +1367,7 @@ EXPORT_SYMBOL(tspp_open_stream);
int tspp_close_stream(u32 dev, u32 channel_id)
{
u32 val;
u32 prev_ref_count;
struct tspp_device *pdev;
struct tspp_channel *channel;
@ -1379,23 +1384,30 @@ int tspp_close_stream(u32 dev, u32 channel_id)
switch (channel->src) {
case TSPP_SOURCE_TSIF0:
prev_ref_count = pdev->tsif[0].ref_count;
tspp_stop_tsif(&pdev->tsif[0]);
if (tspp_config_gpios(pdev, channel->src, 0) != 0)
pr_err("tspp: error disabling tsif0 GPIOs\n");
val = readl_relaxed(pdev->base + TSPP_CONTROL);
writel_relaxed(val | TSPP_CONTROL_TSP_TSIF0_SRC_DIS,
pdev->base + TSPP_CONTROL);
wmb();
if (prev_ref_count == 1) {
val = readl_relaxed(pdev->base + TSPP_CONTROL);
writel_relaxed(val | TSPP_CONTROL_TSP_TSIF0_SRC_DIS,
pdev->base + TSPP_CONTROL);
wmb();
}
break;
case TSPP_SOURCE_TSIF1:
prev_ref_count = pdev->tsif[1].ref_count;
tspp_stop_tsif(&pdev->tsif[1]);
if (tspp_config_gpios(pdev, channel->src, 0) != 0)
pr_err("tspp: error disabling tsif0 GPIOs\n");
val = readl_relaxed(pdev->base + TSPP_CONTROL);
writel_relaxed(val | TSPP_CONTROL_TSP_TSIF1_SRC_DIS,
pdev->base + TSPP_CONTROL);
if (prev_ref_count == 1) {
val = readl_relaxed(pdev->base + TSPP_CONTROL);
writel_relaxed(val | TSPP_CONTROL_TSP_TSIF1_SRC_DIS,
pdev->base + TSPP_CONTROL);
wmb();
}
break;
case TSPP_SOURCE_MEM:
break;
@ -1595,9 +1607,6 @@ int tspp_close_channel(u32 dev, u32 channel_id)
}
channel->filter_count = 0;
/* stop the stream */
tspp_close_stream(dev, channel->id);
/* disconnect the bam */
if (sps_disconnect(channel->pipe) != 0)
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;
dev = channel->pdev->pdev->id;
if (!param1)
if ((param0 != TSPP_IOCTL_CLOSE_STREAM) && !param1)
return -EINVAL;
switch (param0) {
@ -2502,6 +2511,9 @@ static long tspp_ioctl(struct file *filp,
sizeof(struct tspp_buffer)) == 0)
rc = tspp_set_buffer_size(channel, &b);
break;
case TSPP_IOCTL_CLOSE_STREAM:
rc = tspp_close_stream(dev, channel->id);
break;
default:
pr_err("tspp: Unknown ioctl %i", param0);
}

View File

@ -88,5 +88,7 @@ struct tspp_buffer {
_IOW(TSPP_IOCTL_BASE, 5, struct tspp_system_keys)
#define TSPP_IOCTL_BUFFER_SIZE \
_IOW(TSPP_IOCTL_BASE, 6, struct tspp_buffer)
#define TSPP_IOCTL_CLOSE_STREAM \
_IO(TSPP_IOCTL_BASE, 7)
#endif /* _TSPP_H_ */