From 10e5816d4ad02ae761769a892b9e9307040465a2 Mon Sep 17 00:00:00 2001 From: Shuai Zhang Date: Fri, 4 Mar 2022 12:07:01 +0530 Subject: [PATCH] ASoC: codecs: wsa881x: add codec dai for each wsa881x Add new codec dai for each wsa881x, since each WSA is initialized as a codec and not as aux device. Change-Id: Ifee063cea54a65600d9040390666d58de49a0689 Signed-off-by: Shuai Zhang --- asoc/codecs/wsa881x.c | 128 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 122 insertions(+), 6 deletions(-) diff --git a/asoc/codecs/wsa881x.c b/asoc/codecs/wsa881x.c index 1c28ab051f24..fc4ae71882a9 100644 --- a/asoc/codecs/wsa881x.c +++ b/asoc/codecs/wsa881x.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -30,9 +31,21 @@ #include "wsa881x-temp-sensor.h" #include "asoc/bolero-slave-internal.h" -#define DRV_NAME "wsa-codec" #define WSA881X_NUM_RETRY 5 +#define MAX_NAME_LEN 30 +#define WSA881X_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000 |\ + SNDRV_PCM_RATE_384000) +/* Fractional Rates */ +#define WSA881X_FRAC_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800) + +#define WSA881X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) + enum { G_18DB = 0, G_16P5DB, @@ -115,6 +128,9 @@ struct wsa881x_priv { struct dentry *debugfs_poke; struct dentry *debugfs_reg_dump; unsigned int read_data; + char *wsa881x_name_prefix; + struct snd_soc_dai_driver *dai_driver; + struct snd_soc_component_driver *driver; }; struct wsa_ctrl_platform_data { @@ -1356,7 +1372,7 @@ static void wsa881x_remove(struct snd_soc_component *component) } static const struct snd_soc_component_driver soc_codec_dev_wsa881x = { - .name = DRV_NAME, + .name = "wsa-codec", .probe = wsa881x_probe, .remove = wsa881x_remove, .controls = wsa881x_snd_controls, @@ -1367,6 +1383,21 @@ static const struct snd_soc_component_driver soc_codec_dev_wsa881x = { .num_dapm_routes = ARRAY_SIZE(wsa881x_audio_map), }; +static struct snd_soc_dai_driver wsa_dai[] = { + { + .name = "wsa_rx", + .playback = { + .stream_name = "WSA881X_AIF Playback", + .rates = WSA881X_RATES | WSA881X_FRAC_RATES, + .formats = WSA881X_FORMATS, + .rate_max = 192000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 2, + }, + }, +}; + static int wsa881x_gpio_ctrl(struct wsa881x_priv *wsa881x, bool enable) { int ret = 0; @@ -1461,9 +1492,13 @@ static int wsa881x_event_notify(struct notifier_block *nb, static int wsa881x_swr_probe(struct swr_device *pdev) { int ret = 0; - struct wsa881x_priv *wsa881x; + struct wsa881x_priv *wsa881x = NULL; + struct snd_soc_component *component; u8 devnum = 0; + int dev_index = 0; bool pin_state_current = false; + char buffer[MAX_NAME_LEN]; + const char *wsa881x_name_prefix_of = NULL; struct wsa_ctrl_platform_data *plat_data = NULL; wsa881x = devm_kzalloc(&pdev->dev, sizeof(struct wsa881x_priv), @@ -1553,14 +1588,74 @@ static int wsa881x_swr_probe(struct swr_device *pdev) goto dev_err; } - ret = snd_soc_register_component(&pdev->dev, &soc_codec_dev_wsa881x, - NULL, 0); + ret = of_property_read_string(pdev->dev.of_node, + "qcom,wsa-prefix", &wsa881x_name_prefix_of); + if (ret) { + dev_err(&pdev->dev, + "%s: Looking up %s property in node %s failed\n", + __func__, "qcom,wsa-prefix", + pdev->dev.of_node->full_name); + goto dev_err; + } + + wsa881x->driver = devm_kzalloc(&pdev->dev, + sizeof(struct snd_soc_component_driver), + GFP_KERNEL); + if (!wsa881x->driver) { + ret = -ENOMEM; + goto err_mem; + } + + memcpy(wsa881x->driver, &soc_codec_dev_wsa881x, + sizeof(struct snd_soc_component_driver)); + + wsa881x->dai_driver = devm_kzalloc(&pdev->dev, + sizeof(struct snd_soc_dai_driver), + GFP_KERNEL); + if (!wsa881x->dai_driver) { + ret = -ENOMEM; + goto err_mem; + } + + memcpy(wsa881x->dai_driver, wsa_dai, + sizeof(struct snd_soc_dai_driver)); + + dev_index = (int)((char)(pdev->addr & 0xF)); + + snprintf(buffer, sizeof(buffer), "wsa-codec.%d", dev_index); + wsa881x->driver->name = kstrndup(buffer, + strlen(buffer), GFP_KERNEL); + + snprintf(buffer, sizeof(buffer), "wsa_rx%d", dev_index); + wsa881x->dai_driver->name = + kstrndup(buffer, strlen(buffer), GFP_KERNEL); + + snprintf(buffer, sizeof(buffer), + "WSA881X_AIF%d Playback", dev_index); + wsa881x->dai_driver->playback.stream_name = + kstrndup(buffer, strlen(buffer), GFP_KERNEL); + + /* Number of DAI's used is 1 */ + ret = snd_soc_register_component(&pdev->dev, + wsa881x->driver, wsa881x->dai_driver, 1); if (ret) { dev_err(&pdev->dev, "%s: Codec registration failed\n", __func__); - goto dev_err; + goto err_mem; } + wsa881x->wsa881x_name_prefix = kstrndup(wsa881x_name_prefix_of, + strlen(wsa881x_name_prefix_of), GFP_KERNEL); + + component = snd_soc_lookup_component(&pdev->dev, wsa881x->driver->name); + if (!component) { + dev_err(&pdev->dev, "%s: component is NULL \n", __func__); + ret = -EINVAL; + goto err_mem; + } + + component->name_prefix = wsa881x->wsa881x_name_prefix; + wsa881x->bolero_np = of_parse_phandle(pdev->dev.of_node, "qcom,bolero-handle", 0); if (wsa881x->bolero_np) { @@ -1596,6 +1691,17 @@ static int wsa881x_swr_probe(struct swr_device *pdev) return 0; +err_mem: + kfree(wsa881x->wsa881x_name_prefix); + if (wsa881x->dai_driver) { + devm_kfree(&pdev->dev, wsa881x->dai_driver->name); + devm_kfree(&pdev->dev, wsa881x->dai_driver->playback.stream_name); + devm_kfree(&pdev->dev, wsa881x->dai_driver); + } + if (wsa881x->driver) { + devm_kfree(&pdev->dev, wsa881x->driver->name); + devm_kfree(&pdev->dev, wsa881x->driver); + } dev_err: if (pin_state_current == false) wsa881x_gpio_ctrl(wsa881x, false); @@ -1625,6 +1731,16 @@ static int wsa881x_swr_remove(struct swr_device *pdev) if (wsa881x->pd_gpio) gpio_free(wsa881x->pd_gpio); swr_set_dev_data(pdev, NULL); + kfree(wsa881x->wsa881x_name_prefix); + if (wsa881x->dai_driver) { + devm_kfree(&pdev->dev, wsa881x->dai_driver->name); + devm_kfree(&pdev->dev, wsa881x->dai_driver->playback.stream_name); + devm_kfree(&pdev->dev, wsa881x->dai_driver); + } + if (wsa881x->driver) { + devm_kfree(&pdev->dev, wsa881x->driver->name); + devm_kfree(&pdev->dev, wsa881x->driver); + } return 0; }