Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: imx-rpmsg: Force codec power on in low power audio mode

Low power audio mode requires binding codec still power on while Acore
enters into suspend so Mcore can continue playback music.

ASoC machine driver acquires DAPM endpoints through reading
"ignore-suspend-widgets" property from DT and then forces the path
between these endpoints ignoring suspend.

If the rpmsg sound card is in low power audio mode, the suspend/resume
callback of binding codec is overridden to disable the suspend/resume.

Signed-off-by: Chancel Liu <chancel.liu@nxp.com>
Link: https://lore.kernel.org/r/20231121052512.20235-2-chancel.liu@nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Chancel Liu and committed by
Mark Brown
5d9f746c 27c69d7d

+59 -2
+59 -2
sound/soc/fsl/imx-rpmsg.c
··· 2 2 // Copyright 2017-2020 NXP 3 3 4 4 #include <linux/module.h> 5 - #include <linux/of.h> 5 + #include <linux/of_platform.h> 6 6 #include <linux/of_reserved_mem.h> 7 - #include <linux/platform_device.h> 8 7 #include <linux/i2c.h> 9 8 #include <linux/of_gpio.h> 10 9 #include <linux/slab.h> ··· 20 21 struct snd_soc_dai_link dai; 21 22 struct snd_soc_card card; 22 23 unsigned long sysclk; 24 + bool lpa; 23 25 }; 26 + 27 + static struct dev_pm_ops lpa_pm; 24 28 25 29 static const struct snd_soc_dapm_widget imx_rpmsg_dapm_widgets[] = { 26 30 SND_SOC_DAPM_HP("Headphone Jack", NULL), ··· 40 38 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 41 39 struct device *dev = card->dev; 42 40 int ret; 41 + 42 + if (data->lpa) { 43 + struct snd_soc_component *codec_comp; 44 + struct device_node *codec_np; 45 + struct device_driver *codec_drv; 46 + struct device *codec_dev = NULL; 47 + 48 + codec_np = data->dai.codecs->of_node; 49 + if (codec_np) { 50 + struct platform_device *codec_pdev; 51 + struct i2c_client *codec_i2c; 52 + 53 + codec_i2c = of_find_i2c_device_by_node(codec_np); 54 + if (codec_i2c) 55 + codec_dev = &codec_i2c->dev; 56 + if (!codec_dev) { 57 + codec_pdev = of_find_device_by_node(codec_np); 58 + if (codec_pdev) 59 + codec_dev = &codec_pdev->dev; 60 + } 61 + } 62 + if (codec_dev) { 63 + codec_comp = snd_soc_lookup_component_nolocked(codec_dev, NULL); 64 + if (codec_comp) { 65 + int i, num_widgets; 66 + const char *widgets; 67 + struct snd_soc_dapm_context *dapm; 68 + 69 + num_widgets = of_property_count_strings(data->card.dev->of_node, 70 + "ignore-suspend-widgets"); 71 + for (i = 0; i < num_widgets; i++) { 72 + of_property_read_string_index(data->card.dev->of_node, 73 + "ignore-suspend-widgets", 74 + i, &widgets); 75 + dapm = snd_soc_component_get_dapm(codec_comp); 76 + snd_soc_dapm_ignore_suspend(dapm, widgets); 77 + } 78 + } 79 + codec_drv = codec_dev->driver; 80 + if (codec_drv->pm) { 81 + memcpy(&lpa_pm, codec_drv->pm, sizeof(lpa_pm)); 82 + lpa_pm.suspend = NULL; 83 + lpa_pm.resume = NULL; 84 + lpa_pm.freeze = NULL; 85 + lpa_pm.thaw = NULL; 86 + lpa_pm.poweroff = NULL; 87 + lpa_pm.restore = NULL; 88 + codec_drv->pm = &lpa_pm; 89 + } 90 + put_device(codec_dev); 91 + } 92 + } 43 93 44 94 if (!data->sysclk) 45 95 return 0; ··· 191 137 ret = -EINVAL; 192 138 goto fail; 193 139 } 140 + 141 + if (of_property_read_bool(np, "fsl,enable-lpa")) 142 + data->lpa = true; 194 143 195 144 data->card.dev = &pdev->dev; 196 145 data->card.owner = THIS_MODULE;