From ce345ff94d7d5e5da33c1365d30a203f1fe9ccfa Mon Sep 17 00:00:00 2001 From: Anvesh Salveru Date: Mon, 6 Dec 2021 06:38:56 -0800 Subject: [PATCH] slimbus: stream: add support to control port disconnect There is a requirement where slimbus slave don't expect ports to be disconnected during stream unprepare for sample rates other than 44.1/88.2k, which is causing mute issues. Added new slim_stream_unprepare_disconnect_port API to support disconnect port request from clients without freeing port memory allocated during stream prepare. Change-Id: Idb00a1fdf15d864cb6ee82f67c0db4777434b296 Signed-off-by: Anvesh Salveru --- drivers/slimbus/stream.c | 44 ++++++++++++++++++++++++++++++++++++++++ include/linux/slimbus.h | 2 ++ 2 files changed, 46 insertions(+) diff --git a/drivers/slimbus/stream.c b/drivers/slimbus/stream.c index 75f87b3d8b95..81a5225f8111 100644 --- a/drivers/slimbus/stream.c +++ b/drivers/slimbus/stream.c @@ -449,6 +449,50 @@ int slim_stream_unprepare(struct slim_stream_runtime *stream) } EXPORT_SYMBOL_GPL(slim_stream_unprepare); +/** + * slim_stream_unprepare_disconnect_port() - Un-prepare and disconnect + * selected SLIMbus Stream ports + * + * @stream: instance of slim stream runtime to unprepare + * @disconnect_ports: disconnect the ports of the stream + * @is_session_completed: free the ports allocated to the stream + * + * This API will disconnect all the ports and un allocate all the ports and + * channels associated with SLIMbus stream. + * + * Return: zero on success and error code on failure. From ASoC DPCM framework, + * this state is linked to trigger() stop operation. + */ +int slim_stream_unprepare_disconnect_port(struct slim_stream_runtime *stream, + bool disconnect_ports, bool is_session_completed) +{ + int i; + + if (!stream) { + pr_err("%s: Stream is NULL, Check from client side\n", __func__); + return -EINVAL; + } + + if (!stream->ports || !stream->num_ports) { + pr_err("%s: Stream port is NULL %d\n", __func__, stream->num_ports); + return -EINVAL; + } + + if (disconnect_ports) { + for (i = 0; i < stream->num_ports; i++) + slim_disconnect_port(stream, &stream->ports[i]); + } + + if (is_session_completed) { + kfree(stream->ports); + stream->ports = NULL; + stream->num_ports = 0; + } + + return 0; +} +EXPORT_SYMBOL(slim_stream_unprepare_disconnect_port); + /** * slim_stream_free() - Free a SLIMbus Stream * diff --git a/include/linux/slimbus.h b/include/linux/slimbus.h index 12c9719b2a55..d39e0c47ff2e 100644 --- a/include/linux/slimbus.h +++ b/include/linux/slimbus.h @@ -207,6 +207,8 @@ int slim_stream_prepare(struct slim_stream_runtime *stream, int slim_stream_enable(struct slim_stream_runtime *stream); int slim_stream_disable(struct slim_stream_runtime *stream); int slim_stream_unprepare(struct slim_stream_runtime *stream); +int slim_stream_unprepare_disconnect_port(struct slim_stream_runtime *stream, + bool disconnect_ports, bool is_session_completed); int slim_stream_free(struct slim_stream_runtime *stream); #endif /* _LINUX_SLIMBUS_H */