Loading Documentation/devicetree/bindings/sound/qcom-audio-dev.txt +10 −0 Original line number Diff line number Diff line Loading @@ -289,6 +289,13 @@ Required properties: - compatible : "qcom,msm-pcm-hostless" Optional properties - compatible : "qcom,audio-test-mod" Add this compatible as child device to hostless device. This child device is added after lpass is up to invoke deferred probe devices. * msm-ocmem-audio Required properties: Loading Loading @@ -631,6 +638,9 @@ Example: qcom,msm-pcm-hostless { compatible = "qcom,msm-pcm-hostless"; audio-test-mod { compatible = "qcom,audio-test-mod"; }; }; qcom,msm-ocmem-audio { Loading arch/arm/boot/dts/qcom/msm-audio.dtsi +3 −0 Original line number Diff line number Diff line Loading @@ -370,6 +370,9 @@ hostless: qcom,msm-pcm-hostless { compatible = "qcom,msm-pcm-hostless"; audio_test_mod { compatible = "qcom,audio-test-mod"; }; }; dai_pri_auxpcm: qcom,msm-pri-auxpcm { Loading sound/soc/msm/Makefile +1 −1 Original line number Diff line number Diff line # MSM Machine Support snd-soc-hostless-pcm-objs := msm-pcm-hostless.o snd-soc-hostless-pcm-objs := msm-pcm-hostless.o audio_test_mod.o obj-$(CONFIG_SND_SOC_MSM_HOSTLESS_PCM) += snd-soc-hostless-pcm.o obj-$(CONFIG_SND_SOC_MSM_QDSP6V2_INTF) += qdsp6v2/ Loading sound/soc/msm/audio_test_mod.c 0 → 100644 +61 −0 Original line number Diff line number Diff line /* * Copyright (c) 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/of_device.h> static int audio_test_mod_probe(struct platform_device *pdev) { pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev)); return 0; } static int audio_test_mod_remove(struct platform_device *pdev) { return 0; } static const struct of_device_id audio_test_mod_dt_match[] = { {.compatible = "qcom,audio-test-mod"}, {} }; static struct platform_driver audio_test_mod_driver = { .driver = { .name = "audio-test-mod", .owner = THIS_MODULE, .of_match_table = audio_test_mod_dt_match, }, .probe = audio_test_mod_probe, .remove = audio_test_mod_remove, }; static int __init audio_test_mod_init(void) { platform_driver_register(&audio_test_mod_driver); return 0; } static void __exit audio_test_mod_exit(void) { platform_driver_unregister(&audio_test_mod_driver); } module_init(audio_test_mod_init); module_exit(audio_test_mod_exit); MODULE_DESCRIPTION("Audio test module driver"); MODULE_LICENSE("GPL v2"); sound/soc/msm/msm-pcm-hostless.c +83 −0 Original line number Diff line number Diff line Loading @@ -14,10 +14,85 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/of_device.h> #include <linux/workqueue.h> #include <linux/delay.h> #include <sound/core.h> #include <sound/soc.h> #include <sound/pcm.h> #include <linux/qdsp6v2/apr.h> struct hostless_pdata { struct work_struct msm_test_add_child_dev_work; struct device *dev; }; #define AUDIO_TEST_MOD_STRING_LEN 30 static void msm_test_add_child_dev(struct work_struct *work) { struct hostless_pdata *pdata; struct platform_device *pdev; struct device_node *node; int ret; char plat_dev_name[AUDIO_TEST_MOD_STRING_LEN]; int adsp_state; pdata = container_of(work, struct hostless_pdata, msm_test_add_child_dev_work); if (!pdata) { pr_err("%s: Memory for pdata does not exist\n", __func__); return; } if (!pdata->dev) { pr_err("%s: pdata dev is not initialized\n", __func__); return; } if (!pdata->dev->of_node) { dev_err(pdata->dev, "%s: DT node for pdata does not exist\n", __func__); return; } adsp_state = apr_get_subsys_state(); while (adsp_state != APR_SUBSYS_LOADED) { dev_dbg(pdata->dev, "Adsp is not loaded yet %d\n", adsp_state); msleep(500); adsp_state = apr_get_subsys_state(); } msleep(1000); for_each_child_of_node(pdata->dev->of_node, node) { if (!strcmp(node->name, "audio_test_mod")) strlcpy(plat_dev_name, "audio_test_mod", (AUDIO_TEST_MOD_STRING_LEN - 1)); else continue; pdev = platform_device_alloc(plat_dev_name, -1); if (!pdev) { dev_err(pdata->dev, "%s: pdev memory alloc failed\n", __func__); ret = -ENOMEM; goto err; } pdev->dev.parent = pdata->dev; pdev->dev.of_node = node; ret = platform_device_add(pdev); if (ret) { dev_err(&pdev->dev, "%s: Cannot add platform device\n", __func__); goto fail_pdev_add; } } return; fail_pdev_add: platform_device_put(pdev); err: return; } static int msm_pcm_hostless_prepare(struct snd_pcm_substream *substream) { Loading @@ -41,8 +116,16 @@ static struct snd_soc_platform_driver msm_soc_hostless_platform = { static int msm_pcm_hostless_probe(struct platform_device *pdev) { struct hostless_pdata *pdata; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev)); pdata->dev = &pdev->dev; INIT_WORK(&pdata->msm_test_add_child_dev_work, msm_test_add_child_dev); schedule_work(&pdata->msm_test_add_child_dev_work); return snd_soc_register_platform(&pdev->dev, &msm_soc_hostless_platform); } Loading Loading
Documentation/devicetree/bindings/sound/qcom-audio-dev.txt +10 −0 Original line number Diff line number Diff line Loading @@ -289,6 +289,13 @@ Required properties: - compatible : "qcom,msm-pcm-hostless" Optional properties - compatible : "qcom,audio-test-mod" Add this compatible as child device to hostless device. This child device is added after lpass is up to invoke deferred probe devices. * msm-ocmem-audio Required properties: Loading Loading @@ -631,6 +638,9 @@ Example: qcom,msm-pcm-hostless { compatible = "qcom,msm-pcm-hostless"; audio-test-mod { compatible = "qcom,audio-test-mod"; }; }; qcom,msm-ocmem-audio { Loading
arch/arm/boot/dts/qcom/msm-audio.dtsi +3 −0 Original line number Diff line number Diff line Loading @@ -370,6 +370,9 @@ hostless: qcom,msm-pcm-hostless { compatible = "qcom,msm-pcm-hostless"; audio_test_mod { compatible = "qcom,audio-test-mod"; }; }; dai_pri_auxpcm: qcom,msm-pri-auxpcm { Loading
sound/soc/msm/Makefile +1 −1 Original line number Diff line number Diff line # MSM Machine Support snd-soc-hostless-pcm-objs := msm-pcm-hostless.o snd-soc-hostless-pcm-objs := msm-pcm-hostless.o audio_test_mod.o obj-$(CONFIG_SND_SOC_MSM_HOSTLESS_PCM) += snd-soc-hostless-pcm.o obj-$(CONFIG_SND_SOC_MSM_QDSP6V2_INTF) += qdsp6v2/ Loading
sound/soc/msm/audio_test_mod.c 0 → 100644 +61 −0 Original line number Diff line number Diff line /* * Copyright (c) 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/of_device.h> static int audio_test_mod_probe(struct platform_device *pdev) { pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev)); return 0; } static int audio_test_mod_remove(struct platform_device *pdev) { return 0; } static const struct of_device_id audio_test_mod_dt_match[] = { {.compatible = "qcom,audio-test-mod"}, {} }; static struct platform_driver audio_test_mod_driver = { .driver = { .name = "audio-test-mod", .owner = THIS_MODULE, .of_match_table = audio_test_mod_dt_match, }, .probe = audio_test_mod_probe, .remove = audio_test_mod_remove, }; static int __init audio_test_mod_init(void) { platform_driver_register(&audio_test_mod_driver); return 0; } static void __exit audio_test_mod_exit(void) { platform_driver_unregister(&audio_test_mod_driver); } module_init(audio_test_mod_init); module_exit(audio_test_mod_exit); MODULE_DESCRIPTION("Audio test module driver"); MODULE_LICENSE("GPL v2");
sound/soc/msm/msm-pcm-hostless.c +83 −0 Original line number Diff line number Diff line Loading @@ -14,10 +14,85 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/of_device.h> #include <linux/workqueue.h> #include <linux/delay.h> #include <sound/core.h> #include <sound/soc.h> #include <sound/pcm.h> #include <linux/qdsp6v2/apr.h> struct hostless_pdata { struct work_struct msm_test_add_child_dev_work; struct device *dev; }; #define AUDIO_TEST_MOD_STRING_LEN 30 static void msm_test_add_child_dev(struct work_struct *work) { struct hostless_pdata *pdata; struct platform_device *pdev; struct device_node *node; int ret; char plat_dev_name[AUDIO_TEST_MOD_STRING_LEN]; int adsp_state; pdata = container_of(work, struct hostless_pdata, msm_test_add_child_dev_work); if (!pdata) { pr_err("%s: Memory for pdata does not exist\n", __func__); return; } if (!pdata->dev) { pr_err("%s: pdata dev is not initialized\n", __func__); return; } if (!pdata->dev->of_node) { dev_err(pdata->dev, "%s: DT node for pdata does not exist\n", __func__); return; } adsp_state = apr_get_subsys_state(); while (adsp_state != APR_SUBSYS_LOADED) { dev_dbg(pdata->dev, "Adsp is not loaded yet %d\n", adsp_state); msleep(500); adsp_state = apr_get_subsys_state(); } msleep(1000); for_each_child_of_node(pdata->dev->of_node, node) { if (!strcmp(node->name, "audio_test_mod")) strlcpy(plat_dev_name, "audio_test_mod", (AUDIO_TEST_MOD_STRING_LEN - 1)); else continue; pdev = platform_device_alloc(plat_dev_name, -1); if (!pdev) { dev_err(pdata->dev, "%s: pdev memory alloc failed\n", __func__); ret = -ENOMEM; goto err; } pdev->dev.parent = pdata->dev; pdev->dev.of_node = node; ret = platform_device_add(pdev); if (ret) { dev_err(&pdev->dev, "%s: Cannot add platform device\n", __func__); goto fail_pdev_add; } } return; fail_pdev_add: platform_device_put(pdev); err: return; } static int msm_pcm_hostless_prepare(struct snd_pcm_substream *substream) { Loading @@ -41,8 +116,16 @@ static struct snd_soc_platform_driver msm_soc_hostless_platform = { static int msm_pcm_hostless_probe(struct platform_device *pdev) { struct hostless_pdata *pdata; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev)); pdata->dev = &pdev->dev; INIT_WORK(&pdata->msm_test_add_child_dev_work, msm_test_add_child_dev); schedule_work(&pdata->msm_test_add_child_dev_work); return snd_soc_register_platform(&pdev->dev, &msm_soc_hostless_platform); } Loading