|
@@ -35,6 +35,7 @@
|
|
|
#include "codecs/msm-cdc-pinctrl.h"
|
|
|
#include "codecs/wcd9335.h"
|
|
|
#include "codecs/wsa881x.h"
|
|
|
+#include "codecs/csra66x0/csra66x0.h"
|
|
|
#include <dt-bindings/sound/audio-codec-port-types.h>
|
|
|
|
|
|
#define DRV_NAME "qcs405-asoc-snd"
|
|
@@ -150,6 +151,11 @@ struct msm_wsa881x_dev_info {
|
|
|
u32 index;
|
|
|
};
|
|
|
|
|
|
+struct msm_csra66x0_dev_info {
|
|
|
+ struct device_node *of_node;
|
|
|
+ u32 index;
|
|
|
+};
|
|
|
+
|
|
|
enum pinctrl_pin_state {
|
|
|
STATE_DISABLE = 0, /* All pins are in sleep state */
|
|
|
STATE_MI2S_ACTIVE, /* I2S = active, TDM = sleep */
|
|
@@ -7300,6 +7306,200 @@ err:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static int msm_csra66x0_init(struct snd_soc_component *component)
|
|
|
+{
|
|
|
+ struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
|
|
|
+
|
|
|
+ if (!codec) {
|
|
|
+ pr_err("%s codec is NULL\n", __func__);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int msm_init_csra_dev(struct platform_device *pdev,
|
|
|
+ struct snd_soc_card *card)
|
|
|
+{
|
|
|
+ struct device_node *csra_of_node;
|
|
|
+ u32 csra_max_devs;
|
|
|
+ u32 csra_dev_cnt;
|
|
|
+ char *dev_name_str = NULL;
|
|
|
+ struct msm_csra66x0_dev_info *csra66x0_dev_info;
|
|
|
+ const char *csra_auxdev_name_prefix[1];
|
|
|
+ int i;
|
|
|
+ int found = 0;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ /* Get maximum CSRA device count for this platform */
|
|
|
+ ret = of_property_read_u32(pdev->dev.of_node,
|
|
|
+ "qcom,csra-max-devs", &csra_max_devs);
|
|
|
+ if (ret) {
|
|
|
+ dev_info(&pdev->dev,
|
|
|
+ "%s: csra-max-devs property missing in DT %s, ret = %d\n",
|
|
|
+ __func__, pdev->dev.of_node->full_name, ret);
|
|
|
+ card->num_aux_devs = 0;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (csra_max_devs == 0) {
|
|
|
+ dev_warn(&pdev->dev,
|
|
|
+ "%s: Max CSRA devices is 0 for this target?\n",
|
|
|
+ __func__);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Get count of CSRA device phandles for this platform */
|
|
|
+ csra_dev_cnt = of_count_phandle_with_args(pdev->dev.of_node,
|
|
|
+ "qcom,csra-devs", NULL);
|
|
|
+ if (csra_dev_cnt == -ENOENT) {
|
|
|
+ dev_warn(&pdev->dev, "%s: No csra device defined in DT.\n",
|
|
|
+ __func__);
|
|
|
+ goto err;
|
|
|
+ } else if (csra_dev_cnt <= 0) {
|
|
|
+ dev_err(&pdev->dev,
|
|
|
+ "%s: Error reading csra device from DT. csra_dev_cnt = %d\n",
|
|
|
+ __func__, csra_dev_cnt);
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Expect total phandles count to be NOT less than maximum possible
|
|
|
+ * CSRA count. However, if it is less, then assign same value to
|
|
|
+ * max count as well.
|
|
|
+ */
|
|
|
+ if (csra_dev_cnt < csra_max_devs) {
|
|
|
+ dev_dbg(&pdev->dev,
|
|
|
+ "%s: csra_max_devs = %d cannot exceed csra_dev_cnt = %d\n",
|
|
|
+ __func__, csra_max_devs, csra_dev_cnt);
|
|
|
+ csra_max_devs = csra_dev_cnt;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Make sure prefix string passed for each CSRA device */
|
|
|
+ ret = of_property_count_strings(pdev->dev.of_node,
|
|
|
+ "qcom,csra-aux-dev-prefix");
|
|
|
+ if (ret != csra_dev_cnt) {
|
|
|
+ dev_err(&pdev->dev,
|
|
|
+ "%s: expecting %d csra prefix. Defined only %d in DT\n",
|
|
|
+ __func__, csra_dev_cnt, ret);
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Alloc mem to store phandle and index info of CSRA device, if already
|
|
|
+ * registered with ALSA core
|
|
|
+ */
|
|
|
+ csra66x0_dev_info = devm_kcalloc(&pdev->dev, csra_max_devs,
|
|
|
+ sizeof(struct msm_csra66x0_dev_info),
|
|
|
+ GFP_KERNEL);
|
|
|
+ if (!csra66x0_dev_info) {
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * search and check whether all CSRA devices are already
|
|
|
+ * registered with ALSA core or not. If found a node, store
|
|
|
+ * the node and the index in a local array of struct for later
|
|
|
+ * use.
|
|
|
+ */
|
|
|
+ for (i = 0; i < csra_dev_cnt; i++) {
|
|
|
+ csra_of_node = of_parse_phandle(pdev->dev.of_node,
|
|
|
+ "qcom,csra-devs", i);
|
|
|
+ if (unlikely(!csra_of_node)) {
|
|
|
+ /* we should not be here */
|
|
|
+ dev_err(&pdev->dev,
|
|
|
+ "%s: csra dev node is not present\n",
|
|
|
+ __func__);
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto err_free_dev_info;
|
|
|
+ }
|
|
|
+ if (soc_find_component(csra_of_node, NULL)) {
|
|
|
+ /* CSRA device registered with ALSA core */
|
|
|
+ csra66x0_dev_info[found].of_node = csra_of_node;
|
|
|
+ csra66x0_dev_info[found].index = i;
|
|
|
+ found++;
|
|
|
+ if (found == csra_max_devs)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (found < csra_max_devs) {
|
|
|
+ dev_dbg(&pdev->dev,
|
|
|
+ "%s: failed to find %d components. Found only %d\n",
|
|
|
+ __func__, csra_max_devs, found);
|
|
|
+ return -EPROBE_DEFER;
|
|
|
+ }
|
|
|
+ dev_info(&pdev->dev,
|
|
|
+ "%s: found %d csra66x0 devices registered with ALSA core\n",
|
|
|
+ __func__, found);
|
|
|
+
|
|
|
+ card->num_aux_devs = csra_max_devs;
|
|
|
+ card->num_configs = csra_max_devs;
|
|
|
+
|
|
|
+ /* Alloc array of AUX devs struct */
|
|
|
+ msm_aux_dev = devm_kcalloc(&pdev->dev, card->num_aux_devs,
|
|
|
+ sizeof(struct snd_soc_aux_dev), GFP_KERNEL);
|
|
|
+ if (!msm_aux_dev) {
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto err_free_dev_info;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Alloc array of codec conf struct */
|
|
|
+ msm_codec_conf = devm_kcalloc(&pdev->dev, card->num_aux_devs,
|
|
|
+ sizeof(struct snd_soc_codec_conf), GFP_KERNEL);
|
|
|
+ if (!msm_codec_conf) {
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto err_free_aux_dev;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < card->num_aux_devs; i++) {
|
|
|
+ dev_name_str = devm_kzalloc(&pdev->dev, DEV_NAME_STR_LEN,
|
|
|
+ GFP_KERNEL);
|
|
|
+ if (!dev_name_str) {
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto err_free_cdc_conf;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = of_property_read_string_index(pdev->dev.of_node,
|
|
|
+ "qcom,csra-aux-dev-prefix",
|
|
|
+ csra66x0_dev_info[i].index,
|
|
|
+ csra_auxdev_name_prefix);
|
|
|
+ if (ret) {
|
|
|
+ dev_err(&pdev->dev,
|
|
|
+ "%s: failed to read csra aux dev prefix, ret = %d\n",
|
|
|
+ __func__, ret);
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto err_free_dev_name_str;
|
|
|
+ }
|
|
|
+
|
|
|
+ snprintf(dev_name_str, strlen("csra66x0.%d"), "csra66x0.%d", i);
|
|
|
+ msm_aux_dev[i].name = dev_name_str;
|
|
|
+ msm_aux_dev[i].codec_name = NULL;
|
|
|
+ msm_aux_dev[i].codec_of_node =
|
|
|
+ csra66x0_dev_info[i].of_node;
|
|
|
+ msm_aux_dev[i].init = msm_csra66x0_init; /* codec specific init */
|
|
|
+ msm_codec_conf[i].dev_name = NULL;
|
|
|
+ msm_codec_conf[i].name_prefix = csra_auxdev_name_prefix[0];
|
|
|
+ msm_codec_conf[i].of_node = csra66x0_dev_info[i].of_node;
|
|
|
+ }
|
|
|
+ card->codec_conf = msm_codec_conf;
|
|
|
+ card->aux_dev = msm_aux_dev;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+err_free_dev_name_str:
|
|
|
+ devm_kfree(&pdev->dev, dev_name_str);
|
|
|
+err_free_cdc_conf:
|
|
|
+ devm_kfree(&pdev->dev, msm_codec_conf);
|
|
|
+err_free_aux_dev:
|
|
|
+ devm_kfree(&pdev->dev, msm_aux_dev);
|
|
|
+err_free_dev_info:
|
|
|
+ devm_kfree(&pdev->dev, csra66x0_dev_info);
|
|
|
+err:
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
static void msm_i2s_auxpcm_init(struct platform_device *pdev)
|
|
|
{
|
|
|
int count;
|
|
@@ -7341,6 +7541,7 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
|
|
|
struct snd_soc_card *card;
|
|
|
struct msm_asoc_mach_data *pdata;
|
|
|
int ret;
|
|
|
+ u32 val;
|
|
|
|
|
|
if (!pdev->dev.of_node) {
|
|
|
dev_err(&pdev->dev, "No platform supplied from device tree\n");
|
|
@@ -7381,9 +7582,21 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
|
|
|
ret = -EPROBE_DEFER;
|
|
|
goto err;
|
|
|
}
|
|
|
- ret = msm_init_wsa_dev(pdev, card);
|
|
|
- if (ret)
|
|
|
- goto err;
|
|
|
+
|
|
|
+ ret = of_property_read_u32(pdev->dev.of_node, "qcom,csra-codec", &val);
|
|
|
+ if (ret) {
|
|
|
+ dev_info(&pdev->dev, "no 'qcom,csra-codec' in DT\n");
|
|
|
+ val = 0;
|
|
|
+ }
|
|
|
+ if (val) {
|
|
|
+ ret = msm_init_csra_dev(pdev, card);
|
|
|
+ if (ret)
|
|
|
+ goto err;
|
|
|
+ } else {
|
|
|
+ ret = msm_init_wsa_dev(pdev, card);
|
|
|
+ if (ret)
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
|
|
|
pdata->dmic_01_gpio_p = of_parse_phandle(pdev->dev.of_node,
|
|
|
"qcom,cdc-dmic01-gpios",
|