Skip to content

Commit

Permalink
From patchwork series 377117
Browse files Browse the repository at this point in the history
  • Loading branch information
Fox Snowpatch committed Oct 11, 2023
1 parent b8b05bc commit 6a71c76
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 0 deletions.
14 changes: 14 additions & 0 deletions Documentation/devicetree/bindings/sound/sound-card-common.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@ properties:
pair of strings, the first being the connection's sink, the second
being the connection's source.
lpa-widgets:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
description: |
A list of DAPM endpoints which mark paths between these endpoints should
not be disabled when system enters in suspend state. LPA means low power
audio case. For example on asymmetric multiprocessor, there are Cortex-A
core and Cortex-M core, Linux is running on Cortex-A core, RTOS or other
OS is running on Cortex-M core. The audio hardware devices can be
controlled by Cortex-M. LPA can be explained as a mechanism that Cortex-A
allocates a large buffer and fill audio data, then Cortex-A can enter
into suspend for the purpose of power saving. Cortex-M continues to play
the sound during suspend phase of Cortex-A. LPA requires some audio paths
still enabled when Cortex-A enters into suspend.
model:
$ref: /schemas/types.yaml#/definitions/string
description: User specified audio sound card name
Expand Down
58 changes: 58 additions & 0 deletions sound/soc/fsl/imx-rpmsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ struct imx_rpmsg {
struct snd_soc_dai_link dai;
struct snd_soc_card card;
unsigned long sysclk;
bool lpa;
};

static struct dev_pm_ops lpa_pm;

static const struct snd_soc_dapm_widget imx_rpmsg_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_SPK("Ext Spk", NULL),
Expand All @@ -38,6 +41,58 @@ static int imx_rpmsg_late_probe(struct snd_soc_card *card)
struct device *dev = card->dev;
int ret;

if (data->lpa) {
struct snd_soc_component *codec_comp;
struct device_node *codec_np;
struct device_driver *codec_drv;
struct device *codec_dev = NULL;

codec_np = data->dai.codecs->of_node;
if (codec_np) {
struct platform_device *codec_pdev;
struct i2c_client *codec_i2c;

codec_i2c = of_find_i2c_device_by_node(codec_np);
if (codec_i2c)
codec_dev = &codec_i2c->dev;
if (!codec_dev) {
codec_pdev = of_find_device_by_node(codec_np);
if (codec_pdev)
codec_dev = &codec_pdev->dev;
}
}
if (codec_dev) {
codec_comp = snd_soc_lookup_component_nolocked(codec_dev, NULL);
if (codec_comp) {
int i, num_widgets;
const char *widgets;
struct snd_soc_dapm_context *dapm;

num_widgets = of_property_count_strings(data->card.dev->of_node,
"lpa-widgets");
for (i = 0; i < num_widgets; i++) {
of_property_read_string_index(data->card.dev->of_node,
"lpa-widgets",
i, &widgets);
dapm = snd_soc_component_get_dapm(codec_comp);
snd_soc_dapm_ignore_suspend(dapm, widgets);
}
}
codec_drv = codec_dev->driver;
if (codec_drv->pm) {
memcpy(&lpa_pm, codec_drv->pm, sizeof(lpa_pm));
lpa_pm.suspend = NULL;
lpa_pm.resume = NULL;
lpa_pm.freeze = NULL;
lpa_pm.thaw = NULL;
lpa_pm.poweroff = NULL;
lpa_pm.restore = NULL;
codec_drv->pm = &lpa_pm;
}
put_device(codec_dev);
}
}

if (!data->sysclk)
return 0;

Expand Down Expand Up @@ -137,6 +192,9 @@ static int imx_rpmsg_probe(struct platform_device *pdev)
goto fail;
}

if (of_property_read_bool(np, "fsl,enable-lpa"))
data->lpa = true;

data->card.dev = &pdev->dev;
data->card.owner = THIS_MODULE;
data->card.dapm_widgets = imx_rpmsg_dapm_widgets;
Expand Down

0 comments on commit 6a71c76

Please sign in to comment.