Loading sound/soc/msm/mdmcalifornium.c +226 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ #define MDM_MCLK_CLK_12P288MHZ 12288000 #define MDM_MCLK_CLK_9P6HZ 9600000 #define MDM_MI2S_RATE 48000 #define DEV_NAME_STR_LEN 32 #define SAMPLE_RATE_8KHZ 8000 #define SAMPLE_RATE_16KHZ 16000 Loading Loading @@ -96,6 +97,14 @@ static const struct afe_clk_cfg lpass_default = { 0, }; struct mdm_wsa881x_dev_info { struct device_node *of_node; u32 index; }; static struct snd_soc_aux_dev *mdm_aux_dev; static struct snd_soc_codec_conf *mdm_codec_conf; static int mdm_auxpcm_rate = 8000; static void *lpaif_pri_muxsel_virt_addr; static void *lpaif_sec_muxsel_virt_addr; Loading Loading @@ -127,6 +136,55 @@ static struct wcd_mbhc_config wcd_mbhc_cfg = { .hs_ext_micbias = true, }; static int mdm_wsa881x_init(struct snd_soc_component *component) { u8 spkleft_ports[WSA881X_MAX_SWR_PORTS] = {100, 101, 102, 106}; u8 spkright_ports[WSA881X_MAX_SWR_PORTS] = {103, 104, 105, 107}; unsigned int ch_rate[WSA881X_MAX_SWR_PORTS] = {2400, 600, 300, 1200}; unsigned int ch_mask[WSA881X_MAX_SWR_PORTS] = {0x1, 0xF, 0x3, 0x3}; struct snd_soc_codec *codec = snd_soc_component_to_codec(component); struct mdm_machine_data *pdata; struct snd_soc_dapm_context *dapm; if (!codec) { pr_err("%s codec is NULL\n", __func__); return -EINVAL; } dapm = &codec->dapm; if (!strcmp(component->name_prefix, "SpkrLeft")) { dev_dbg(codec->dev, "%s: setting left ch map to codec %s\n", __func__, codec->component.name); wsa881x_set_channel_map(codec, &spkleft_ports[0], WSA881X_MAX_SWR_PORTS, &ch_mask[0], &ch_rate[0]); if (dapm->component) { snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft IN"); snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft SPKR"); } } else if (!strcmp(component->name_prefix, "SpkrRight")) { dev_dbg(codec->dev, "%s: setting right ch map to codec %s\n", __func__, codec->component.name); wsa881x_set_channel_map(codec, &spkright_ports[0], WSA881X_MAX_SWR_PORTS, &ch_mask[0], &ch_rate[0]); if (dapm->component) { snd_soc_dapm_ignore_suspend(dapm, "SpkrRight IN"); snd_soc_dapm_ignore_suspend(dapm, "SpkrRight SPKR"); } } else { dev_err(codec->dev, "%s: wrong codec name %s\n", __func__, codec->component.name); return -EINVAL; } pdata = snd_soc_card_get_drvdata(component->card); if (pdata && pdata->codec_root) wsa881x_codec_info_create_codec_entry(pdata->codec_root, codec); return 0; } static int mdm_mi2s_clk_ctl(struct snd_soc_pcm_runtime *rtd, bool enable) { struct snd_soc_card *card = rtd->card; Loading Loading @@ -1350,6 +1408,170 @@ static int mdm_populate_dai_link_component_of_node( err: return ret; } static int mdm_init_wsa_dev(struct platform_device *pdev, struct snd_soc_card *card) { struct device_node *wsa_of_node; u32 wsa_max_devs; u32 wsa_dev_cnt; char *dev_name_str = NULL; struct mdm_wsa881x_dev_info *wsa881x_dev_info; const char *wsa_auxdev_name_prefix[1]; int found = 0; int i; int ret; /* Get maximum WSA device count for this platform */ ret = of_property_read_u32(pdev->dev.of_node, "qcom,wsa-max-devs", &wsa_max_devs); if (ret) { dev_dbg(&pdev->dev, "%s: wsa-max-devs property missing in DT %s, ret = %d\n", __func__, pdev->dev.of_node->full_name, ret); return 0; } if (wsa_max_devs == 0) { dev_warn(&pdev->dev, "%s: Max WSA devices is 0 for this target?\n", __func__); return 0; } /* Get count of WSA device phandles for this platform */ wsa_dev_cnt = of_count_phandle_with_args(pdev->dev.of_node, "qcom,wsa-devs", NULL); if (wsa_dev_cnt == -ENOENT) { dev_dbg(&pdev->dev, "%s: No wsa device defined in DT.\n", __func__); return 0; } else if (wsa_dev_cnt <= 0) { dev_err(&pdev->dev, "%s: Error reading wsa device from DT. wsa_dev_cnt = %d\n", __func__, wsa_dev_cnt); return -EINVAL; } /* * Expect total phandles count to be NOT less than maximum possible * WSA count. However, if it is less, then assign same value to * max count as well. */ if (wsa_dev_cnt < wsa_max_devs) { dev_dbg(&pdev->dev, "%s: wsa_max_devs = %d cannot exceed wsa_dev_cnt = %d\n", __func__, wsa_max_devs, wsa_dev_cnt); wsa_max_devs = wsa_dev_cnt; } /* Make sure prefix string passed for each WSA device */ ret = of_property_count_strings(pdev->dev.of_node, "qcom,wsa-aux-dev-prefix"); if (ret != wsa_dev_cnt) { dev_err(&pdev->dev, "%s: expecting %d wsa prefix. Defined only %d in DT\n", __func__, wsa_dev_cnt, ret); return -EINVAL; } /* * Alloc mem to store phandle and index info of WSA device, if already * registered with ALSA core */ wsa881x_dev_info = devm_kcalloc(&pdev->dev, wsa_max_devs, sizeof(struct mdm_wsa881x_dev_info), GFP_KERNEL); if (!wsa881x_dev_info) return -ENOMEM; /* * search and check whether all WSA 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 < wsa_dev_cnt; i++) { wsa_of_node = of_parse_phandle(pdev->dev.of_node, "qcom,wsa-devs", i); if (unlikely(!wsa_of_node)) { /* we should not be here */ dev_err(&pdev->dev, "%s: wsa dev node is not present\n", __func__); return -EINVAL; } if (soc_find_component(wsa_of_node, NULL)) { /* WSA device registered with ALSA core */ wsa881x_dev_info[found].of_node = wsa_of_node; wsa881x_dev_info[found].index = i; found++; if (found == wsa_max_devs) break; } } if (found < wsa_max_devs) { dev_dbg(&pdev->dev, "%s: failed to find %d components. Found only %d\n", __func__, wsa_max_devs, found); return -EPROBE_DEFER; } dev_info(&pdev->dev, "%s: found %d wsa881x devices registered with ALSA core\n", __func__, found); card->num_aux_devs = wsa_max_devs; card->num_configs = wsa_max_devs; /* Alloc array of AUX devs struct */ mdm_aux_dev = devm_kcalloc(&pdev->dev, card->num_aux_devs, sizeof(struct snd_soc_aux_dev), GFP_KERNEL); if (!mdm_aux_dev) return -ENOMEM; /* Alloc array of codec conf struct */ mdm_codec_conf = devm_kcalloc(&pdev->dev, card->num_aux_devs, sizeof(struct snd_soc_codec_conf), GFP_KERNEL); if (!mdm_codec_conf) return -ENOMEM; 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) return -ENOMEM; ret = of_property_read_string_index(pdev->dev.of_node, "qcom,wsa-aux-dev-prefix", wsa881x_dev_info[i].index, wsa_auxdev_name_prefix); if (ret) { dev_err(&pdev->dev, "%s: failed to read wsa aux dev prefix, ret = %d\n", __func__, ret); return -EINVAL; } snprintf(dev_name_str, strlen("wsa881x.%d"), "wsa881x.%d", i); mdm_aux_dev[i].name = dev_name_str; mdm_aux_dev[i].codec_name = NULL; mdm_aux_dev[i].codec_of_node = wsa881x_dev_info[i].of_node; mdm_aux_dev[i].init = mdm_wsa881x_init; mdm_codec_conf[i].dev_name = NULL; mdm_codec_conf[i].name_prefix = wsa_auxdev_name_prefix[0]; mdm_codec_conf[i].of_node = wsa881x_dev_info[i].of_node; } card->codec_conf = mdm_codec_conf; card->aux_dev = mdm_aux_dev; return 0; } static int mdm_asoc_machine_probe(struct platform_device *pdev) { int ret; Loading Loading @@ -1408,6 +1630,10 @@ static int mdm_asoc_machine_probe(struct platform_device *pdev) goto err; } ret = mdm_init_wsa_dev(pdev, card); if (ret) goto err; ret = snd_soc_register_card(card); if (ret == -EPROBE_DEFER) { goto err; Loading Loading
sound/soc/msm/mdmcalifornium.c +226 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ #define MDM_MCLK_CLK_12P288MHZ 12288000 #define MDM_MCLK_CLK_9P6HZ 9600000 #define MDM_MI2S_RATE 48000 #define DEV_NAME_STR_LEN 32 #define SAMPLE_RATE_8KHZ 8000 #define SAMPLE_RATE_16KHZ 16000 Loading Loading @@ -96,6 +97,14 @@ static const struct afe_clk_cfg lpass_default = { 0, }; struct mdm_wsa881x_dev_info { struct device_node *of_node; u32 index; }; static struct snd_soc_aux_dev *mdm_aux_dev; static struct snd_soc_codec_conf *mdm_codec_conf; static int mdm_auxpcm_rate = 8000; static void *lpaif_pri_muxsel_virt_addr; static void *lpaif_sec_muxsel_virt_addr; Loading Loading @@ -127,6 +136,55 @@ static struct wcd_mbhc_config wcd_mbhc_cfg = { .hs_ext_micbias = true, }; static int mdm_wsa881x_init(struct snd_soc_component *component) { u8 spkleft_ports[WSA881X_MAX_SWR_PORTS] = {100, 101, 102, 106}; u8 spkright_ports[WSA881X_MAX_SWR_PORTS] = {103, 104, 105, 107}; unsigned int ch_rate[WSA881X_MAX_SWR_PORTS] = {2400, 600, 300, 1200}; unsigned int ch_mask[WSA881X_MAX_SWR_PORTS] = {0x1, 0xF, 0x3, 0x3}; struct snd_soc_codec *codec = snd_soc_component_to_codec(component); struct mdm_machine_data *pdata; struct snd_soc_dapm_context *dapm; if (!codec) { pr_err("%s codec is NULL\n", __func__); return -EINVAL; } dapm = &codec->dapm; if (!strcmp(component->name_prefix, "SpkrLeft")) { dev_dbg(codec->dev, "%s: setting left ch map to codec %s\n", __func__, codec->component.name); wsa881x_set_channel_map(codec, &spkleft_ports[0], WSA881X_MAX_SWR_PORTS, &ch_mask[0], &ch_rate[0]); if (dapm->component) { snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft IN"); snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft SPKR"); } } else if (!strcmp(component->name_prefix, "SpkrRight")) { dev_dbg(codec->dev, "%s: setting right ch map to codec %s\n", __func__, codec->component.name); wsa881x_set_channel_map(codec, &spkright_ports[0], WSA881X_MAX_SWR_PORTS, &ch_mask[0], &ch_rate[0]); if (dapm->component) { snd_soc_dapm_ignore_suspend(dapm, "SpkrRight IN"); snd_soc_dapm_ignore_suspend(dapm, "SpkrRight SPKR"); } } else { dev_err(codec->dev, "%s: wrong codec name %s\n", __func__, codec->component.name); return -EINVAL; } pdata = snd_soc_card_get_drvdata(component->card); if (pdata && pdata->codec_root) wsa881x_codec_info_create_codec_entry(pdata->codec_root, codec); return 0; } static int mdm_mi2s_clk_ctl(struct snd_soc_pcm_runtime *rtd, bool enable) { struct snd_soc_card *card = rtd->card; Loading Loading @@ -1350,6 +1408,170 @@ static int mdm_populate_dai_link_component_of_node( err: return ret; } static int mdm_init_wsa_dev(struct platform_device *pdev, struct snd_soc_card *card) { struct device_node *wsa_of_node; u32 wsa_max_devs; u32 wsa_dev_cnt; char *dev_name_str = NULL; struct mdm_wsa881x_dev_info *wsa881x_dev_info; const char *wsa_auxdev_name_prefix[1]; int found = 0; int i; int ret; /* Get maximum WSA device count for this platform */ ret = of_property_read_u32(pdev->dev.of_node, "qcom,wsa-max-devs", &wsa_max_devs); if (ret) { dev_dbg(&pdev->dev, "%s: wsa-max-devs property missing in DT %s, ret = %d\n", __func__, pdev->dev.of_node->full_name, ret); return 0; } if (wsa_max_devs == 0) { dev_warn(&pdev->dev, "%s: Max WSA devices is 0 for this target?\n", __func__); return 0; } /* Get count of WSA device phandles for this platform */ wsa_dev_cnt = of_count_phandle_with_args(pdev->dev.of_node, "qcom,wsa-devs", NULL); if (wsa_dev_cnt == -ENOENT) { dev_dbg(&pdev->dev, "%s: No wsa device defined in DT.\n", __func__); return 0; } else if (wsa_dev_cnt <= 0) { dev_err(&pdev->dev, "%s: Error reading wsa device from DT. wsa_dev_cnt = %d\n", __func__, wsa_dev_cnt); return -EINVAL; } /* * Expect total phandles count to be NOT less than maximum possible * WSA count. However, if it is less, then assign same value to * max count as well. */ if (wsa_dev_cnt < wsa_max_devs) { dev_dbg(&pdev->dev, "%s: wsa_max_devs = %d cannot exceed wsa_dev_cnt = %d\n", __func__, wsa_max_devs, wsa_dev_cnt); wsa_max_devs = wsa_dev_cnt; } /* Make sure prefix string passed for each WSA device */ ret = of_property_count_strings(pdev->dev.of_node, "qcom,wsa-aux-dev-prefix"); if (ret != wsa_dev_cnt) { dev_err(&pdev->dev, "%s: expecting %d wsa prefix. Defined only %d in DT\n", __func__, wsa_dev_cnt, ret); return -EINVAL; } /* * Alloc mem to store phandle and index info of WSA device, if already * registered with ALSA core */ wsa881x_dev_info = devm_kcalloc(&pdev->dev, wsa_max_devs, sizeof(struct mdm_wsa881x_dev_info), GFP_KERNEL); if (!wsa881x_dev_info) return -ENOMEM; /* * search and check whether all WSA 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 < wsa_dev_cnt; i++) { wsa_of_node = of_parse_phandle(pdev->dev.of_node, "qcom,wsa-devs", i); if (unlikely(!wsa_of_node)) { /* we should not be here */ dev_err(&pdev->dev, "%s: wsa dev node is not present\n", __func__); return -EINVAL; } if (soc_find_component(wsa_of_node, NULL)) { /* WSA device registered with ALSA core */ wsa881x_dev_info[found].of_node = wsa_of_node; wsa881x_dev_info[found].index = i; found++; if (found == wsa_max_devs) break; } } if (found < wsa_max_devs) { dev_dbg(&pdev->dev, "%s: failed to find %d components. Found only %d\n", __func__, wsa_max_devs, found); return -EPROBE_DEFER; } dev_info(&pdev->dev, "%s: found %d wsa881x devices registered with ALSA core\n", __func__, found); card->num_aux_devs = wsa_max_devs; card->num_configs = wsa_max_devs; /* Alloc array of AUX devs struct */ mdm_aux_dev = devm_kcalloc(&pdev->dev, card->num_aux_devs, sizeof(struct snd_soc_aux_dev), GFP_KERNEL); if (!mdm_aux_dev) return -ENOMEM; /* Alloc array of codec conf struct */ mdm_codec_conf = devm_kcalloc(&pdev->dev, card->num_aux_devs, sizeof(struct snd_soc_codec_conf), GFP_KERNEL); if (!mdm_codec_conf) return -ENOMEM; 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) return -ENOMEM; ret = of_property_read_string_index(pdev->dev.of_node, "qcom,wsa-aux-dev-prefix", wsa881x_dev_info[i].index, wsa_auxdev_name_prefix); if (ret) { dev_err(&pdev->dev, "%s: failed to read wsa aux dev prefix, ret = %d\n", __func__, ret); return -EINVAL; } snprintf(dev_name_str, strlen("wsa881x.%d"), "wsa881x.%d", i); mdm_aux_dev[i].name = dev_name_str; mdm_aux_dev[i].codec_name = NULL; mdm_aux_dev[i].codec_of_node = wsa881x_dev_info[i].of_node; mdm_aux_dev[i].init = mdm_wsa881x_init; mdm_codec_conf[i].dev_name = NULL; mdm_codec_conf[i].name_prefix = wsa_auxdev_name_prefix[0]; mdm_codec_conf[i].of_node = wsa881x_dev_info[i].of_node; } card->codec_conf = mdm_codec_conf; card->aux_dev = mdm_aux_dev; return 0; } static int mdm_asoc_machine_probe(struct platform_device *pdev) { int ret; Loading Loading @@ -1408,6 +1630,10 @@ static int mdm_asoc_machine_probe(struct platform_device *pdev) goto err; } ret = mdm_init_wsa_dev(pdev, card); if (ret) goto err; ret = snd_soc_register_card(card); if (ret == -EPROBE_DEFER) { goto err; Loading