summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/wcd938x.c
diff options
context:
space:
mode:
authorSrinivas Kandagatla <srinivas.kandagatla@linaro.org>2021-06-09 12:09:39 +0300
committerMark Brown <broonie@kernel.org>2021-06-14 13:14:39 +0300
commit16572522aece6a142d303a25f32544643f52c383 (patch)
treeeb95354472fd7c9bc2c86020c487a67fae0db3fe /sound/soc/codecs/wcd938x.c
parente02c65f3a7ce11ce522e805c78ed2f1da5d96975 (diff)
downloadlinux-16572522aece6a142d303a25f32544643f52c383.tar.xz
ASoC: codecs: wcd938x-sdw: add SoundWire driver
This patch adds support to SoundWire devices on WCD9380/WCD9385 Codec Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Link: https://lore.kernel.org/r/20210609090943.7896-6-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/codecs/wcd938x.c')
-rw-r--r--sound/soc/codecs/wcd938x.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c
index 6b8ee9971945..6400ff7347d4 100644
--- a/sound/soc/codecs/wcd938x.c
+++ b/sound/soc/codecs/wcd938x.c
@@ -1514,7 +1514,39 @@ int wcd938x_handle_sdw_irq(struct wcd938x_sdw_priv *wcd)
}
EXPORT_SYMBOL_GPL(wcd938x_handle_sdw_irq);
+static int wcd938x_codec_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct wcd938x_priv *wcd938x = dev_get_drvdata(dai->dev);
+ struct wcd938x_sdw_priv *wcd = wcd938x->sdw_priv[dai->id];
+
+ return wcd938x_sdw_hw_params(wcd, substream, params, dai);
+}
+
+static int wcd938x_codec_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct wcd938x_priv *wcd938x = dev_get_drvdata(dai->dev);
+ struct wcd938x_sdw_priv *wcd = wcd938x->sdw_priv[dai->id];
+
+ return wcd938x_sdw_free(wcd, substream, dai);
+}
+
+static int wcd938x_codec_set_sdw_stream(struct snd_soc_dai *dai,
+ void *stream, int direction)
+{
+ struct wcd938x_priv *wcd938x = dev_get_drvdata(dai->dev);
+ struct wcd938x_sdw_priv *wcd = wcd938x->sdw_priv[dai->id];
+
+ return wcd938x_sdw_set_sdw_stream(wcd, dai, stream, direction);
+
+}
+
static struct snd_soc_dai_ops wcd938x_sdw_dai_ops = {
+ .hw_params = wcd938x_codec_hw_params,
+ .hw_free = wcd938x_codec_free,
+ .set_sdw_stream = wcd938x_codec_set_sdw_stream,
};
static struct snd_soc_dai_driver wcd938x_dais[] = {
@@ -1558,6 +1590,53 @@ static int wcd938x_bind(struct device *dev)
return ret;
}
+ wcd938x->rxdev = wcd938x_sdw_device_get(wcd938x->rxnode);
+ if (!wcd938x->rxdev) {
+ dev_err(dev, "could not find slave with matching of node\n");
+ return -EINVAL;
+ }
+ wcd938x->sdw_priv[AIF1_PB] = dev_get_drvdata(wcd938x->rxdev);
+ wcd938x->sdw_priv[AIF1_PB]->wcd938x = wcd938x;
+
+ wcd938x->txdev = wcd938x_sdw_device_get(wcd938x->txnode);
+ if (!wcd938x->txdev) {
+ dev_err(dev, "could not find txslave with matching of node\n");
+ return -EINVAL;
+ }
+ wcd938x->sdw_priv[AIF1_CAP] = dev_get_drvdata(wcd938x->txdev);
+ wcd938x->sdw_priv[AIF1_CAP]->wcd938x = wcd938x;
+ wcd938x->tx_sdw_dev = dev_to_sdw_dev(wcd938x->txdev);
+ if (!wcd938x->tx_sdw_dev) {
+ dev_err(dev, "could not get txslave with matching of dev\n");
+ return -EINVAL;
+ }
+
+ /* As TX is main CSR reg interface, which should not be suspended first.
+ * expicilty add the dependency link */
+ if (!device_link_add(wcd938x->rxdev, wcd938x->txdev, DL_FLAG_STATELESS |
+ DL_FLAG_PM_RUNTIME)) {
+ dev_err(dev, "could not devlink tx and rx\n");
+ return -EINVAL;
+ }
+
+ if (!device_link_add(dev, wcd938x->txdev, DL_FLAG_STATELESS |
+ DL_FLAG_PM_RUNTIME)) {
+ dev_err(dev, "could not devlink wcd and tx\n");
+ return -EINVAL;
+ }
+
+ if (!device_link_add(dev, wcd938x->rxdev, DL_FLAG_STATELESS |
+ DL_FLAG_PM_RUNTIME)) {
+ dev_err(dev, "could not devlink wcd and rx\n");
+ return -EINVAL;
+ }
+
+ wcd938x->regmap = dev_get_regmap(wcd938x->txdev, NULL);
+ if (!wcd938x->regmap) {
+ dev_err(dev, "%s: tx csr regmap not found\n", __func__);
+ return PTR_ERR(wcd938x->regmap);
+ }
+
ret = wcd938x_set_micbias_data(wcd938x);
if (ret < 0) {
dev_err(dev, "%s: bad micbias pdata\n", __func__);
@@ -1578,6 +1657,9 @@ static void wcd938x_unbind(struct device *dev)
{
struct wcd938x_priv *wcd938x = dev_get_drvdata(dev);
+ device_link_remove(dev, wcd938x->txdev);
+ device_link_remove(dev, wcd938x->rxdev);
+ device_link_remove(wcd938x->rxdev, wcd938x->txdev);
snd_soc_unregister_component(dev);
component_unbind_all(dev, wcd938x);
}