diff --git a/asoc/codecs/wsa883x/internal.h b/asoc/codecs/wsa883x/internal.h index 1863aacf89..8f73129e0b 100644 --- a/asoc/codecs/wsa883x/internal.h +++ b/asoc/codecs/wsa883x/internal.h @@ -130,6 +130,9 @@ struct wsa883x_priv { int num_supplies; struct regulator_bulk_data *supplies; unsigned long status_mask; + char *wsa883x_name_prefix; + struct snd_soc_dai_driver *dai_driver; + struct snd_soc_component_driver *driver; }; #endif /* WSA883X_INTERNAL_H */ diff --git a/asoc/codecs/wsa883x/wsa883x.c b/asoc/codecs/wsa883x/wsa883x.c index 94b3e34715..13d2d8a11f 100644 --- a/asoc/codecs/wsa883x/wsa883x.c +++ b/asoc/codecs/wsa883x/wsa883x.c @@ -38,12 +38,23 @@ #define WSA883X_TEMP_RETRY 3 #define WSA883X_VBAT_TIMER_SEC 2 +#define MAX_NAME_LEN 30 +#define WSA883X_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 WSA883X_FRAC_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800) + +#define WSA883X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) + static int wsa883x_vbat_timer_sec = WSA883X_VBAT_TIMER_SEC; module_param(wsa883x_vbat_timer_sec, int, 0664); MODULE_PARM_DESC(wsa883x_vbat_timer_sec, "timer for VBAT monitor polling"); -#define DRV_NAME "wsa-codec" - enum { WSA_4OHMS =4, WSA_8OHMS = 8, @@ -1242,8 +1253,8 @@ static void wsa883x_codec_remove(struct snd_soc_component *component) return; } -static const struct snd_soc_component_driver soc_codec_dev_wsa883x = { - .name = DRV_NAME, +static const struct snd_soc_component_driver soc_codec_dev_wsa883x_wsa = { + .name = "", .probe = wsa883x_codec_probe, .remove = wsa883x_codec_remove, .controls = wsa883x_snd_controls, @@ -1336,6 +1347,21 @@ static int wsa883x_enable_supplies(struct device * dev, return ret; } +static struct snd_soc_dai_driver wsa_dai[] = { + { + .name = "", + .playback = { + .stream_name = "", + .rates = WSA883X_RATES | WSA883X_FRAC_RATES, + .formats = WSA883X_FORMATS, + .rate_max = 192000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 2, + }, + }, +}; + static int wsa883x_swr_probe(struct swr_device *pdev) { int ret = 0, i = 0; @@ -1343,6 +1369,10 @@ static int wsa883x_swr_probe(struct swr_device *pdev) u8 devnum = 0; bool pin_state_current = false; struct wsa_ctrl_platform_data *plat_data = NULL; + struct snd_soc_component *component; + const char *wsa883x_name_prefix_of = NULL; + char buffer[MAX_NAME_LEN]; + int dev_index = 0; wsa883x = devm_kzalloc(&pdev->dev, sizeof(struct wsa883x_priv), GFP_KERNEL); @@ -1445,14 +1475,58 @@ static int wsa883x_swr_probe(struct swr_device *pdev) wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR); - ret = snd_soc_register_component(&pdev->dev, &soc_codec_dev_wsa883x, - NULL, 0); + ret = of_property_read_string(pdev->dev.of_node, "qcom,wsa-prefix", + &wsa883x_name_prefix_of); if (ret) { - dev_err(&pdev->dev, "%s: Codec registration failed\n", - __func__); + 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 err_irq; } + wsa883x->driver = devm_kzalloc(&pdev->dev, + sizeof(struct snd_soc_component_driver), GFP_KERNEL); + if (!wsa883x->driver) { + ret = -ENOMEM; + goto err_irq; + } + + memcpy(wsa883x->driver, &soc_codec_dev_wsa883x_wsa, + sizeof(struct snd_soc_component_driver)); + + wsa883x->dai_driver = devm_kzalloc(&pdev->dev, + sizeof(struct snd_soc_dai_driver), GFP_KERNEL); + if (!wsa883x->dai_driver) { + ret = -ENOMEM; + goto err_mem; + } + + memcpy(wsa883x->dai_driver, wsa_dai, sizeof(struct snd_soc_dai_driver)); + + /* Get last digit from HEX format */ + dev_index = (int)((char)(pdev->addr & 0xF)); + + snprintf(buffer, sizeof(buffer), "wsa-codec.%d", dev_index); + wsa883x->driver->name = kstrndup(buffer, strlen(buffer), GFP_KERNEL); + + snprintf(buffer, sizeof(buffer), "wsa_rx%d", dev_index); + wsa883x->dai_driver->name = + kstrndup(buffer, strlen(buffer), GFP_KERNEL); + + snprintf(buffer, sizeof(buffer), "WSA883X_AIF%d Playback", dev_index); + wsa883x->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, + wsa883x->driver, wsa883x->dai_driver, 1); + + wsa883x->wsa883x_name_prefix = kstrndup(wsa883x_name_prefix_of, + strlen(wsa883x_name_prefix_of), GFP_KERNEL); + component = snd_soc_lookup_component(&pdev->dev, wsa883x->driver->name); + component->name_prefix = wsa883x->wsa883x_name_prefix; + wsa883x->parent_np = of_parse_phandle(pdev->dev.of_node, "qcom,bolero-handle", 0); if (wsa883x->parent_np) { @@ -1517,6 +1591,11 @@ static int wsa883x_swr_probe(struct swr_device *pdev) return 0; +err_mem: + if (wsa883x->dai_driver) + kfree(wsa883x->dai_driver); + if (wsa883x->driver) + kfree(wsa883x->driver); err_irq: wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_SAF2WAR, NULL); wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_WAR2SAF, NULL); @@ -1567,6 +1646,14 @@ static int wsa883x_swr_remove(struct swr_device *pdev) #endif mutex_destroy(&wsa883x->res_lock); snd_soc_unregister_component(&pdev->dev); + kfree(wsa883x->wsa883x_name_prefix); + kfree(wsa883x->driver->name); + kfree(wsa883x->dai_driver->name); + kfree(wsa883x->dai_driver->playback.stream_name); + if (wsa883x->dai_driver) + kfree(wsa883x->dai_driver); + if (wsa883x->driver) + kfree(wsa883x->driver); swr_set_dev_data(pdev, NULL); return 0; }