Skip to content

Commit 8e3acba

Browse files
committed
ASoC: SOF: Add MFD support
Add MFD support in SOF with a single client device for audio. The audio client is a registered as a separate platform device under the SOF PCI device. This patch deals with partitioning the DSP hardware initialisation parts and the audio specific code. The hardware initialization, FW load/boot, IPC init is done at the top-level PCI device probe. The audio client platform device's probe deals with registering the component driver, creating the machine driver and loading the topology. The device hierarchy is altered with the addition of the platform device for the audio client. The machine driver and the component driver will now be children of the sof-audio platform device. Signed-off-by: Ranjani Sridharan <[email protected]>
1 parent f1c5cf5 commit 8e3acba

File tree

8 files changed

+218
-79
lines changed

8 files changed

+218
-79
lines changed

sound/soc/sof/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
ccflags-y += -DDEBUG
44

55
snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\
6-
control.o trace.o utils.o
6+
control.o trace.o utils.o sof-mfd.o sof-audio.o
77

88
snd-sof-pci-objs := sof-pci-dev.o
99
snd-sof-acpi-objs := sof-acpi-dev.o

sound/soc/sof/core.c

+6-76
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <sound/sof.h>
1616
#include "sof-priv.h"
1717
#include "ops.h"
18+
#include "sof-mfd.h"
1819

1920
/* see SOF_DBG_ flags */
2021
int sof_core_debug;
@@ -258,47 +259,9 @@ int snd_sof_create_page_table(struct snd_sof_dev *sdev,
258259
return pages;
259260
}
260261

261-
/*
262-
* SOF Driver enumeration.
263-
*/
264-
static int sof_machine_check(struct snd_sof_dev *sdev)
265-
{
266-
struct snd_sof_pdata *plat_data = sdev->pdata;
267-
#if IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC)
268-
struct snd_soc_acpi_mach *machine;
269-
int ret;
270-
#endif
271-
272-
if (plat_data->machine)
273-
return 0;
274-
275-
#if !IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC)
276-
dev_err(sdev->dev, "error: no matching ASoC machine driver found - aborting probe\n");
277-
return -ENODEV;
278-
#else
279-
/* fallback to nocodec mode */
280-
dev_warn(sdev->dev, "No ASoC machine driver found - using nocodec\n");
281-
machine = devm_kzalloc(sdev->dev, sizeof(*machine), GFP_KERNEL);
282-
if (!machine)
283-
return -ENOMEM;
284-
285-
ret = sof_nocodec_setup(sdev->dev, plat_data, machine,
286-
plat_data->desc, plat_data->desc->ops);
287-
if (ret < 0)
288-
return ret;
289-
290-
plat_data->machine = machine;
291-
292-
return 0;
293-
#endif
294-
}
295-
296262
static int sof_probe_continue(struct snd_sof_dev *sdev)
297263
{
298264
struct snd_sof_pdata *plat_data = sdev->pdata;
299-
const char *drv_name;
300-
const void *mach;
301-
int size;
302265
int ret;
303266

304267
/* probe the DSP hardware */
@@ -308,17 +271,6 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
308271
return ret;
309272
}
310273

311-
/* check machine info */
312-
ret = sof_machine_check(sdev);
313-
if (ret < 0) {
314-
dev_err(sdev->dev, "error: failed to get machine info %d\n",
315-
ret);
316-
goto dbg_err;
317-
}
318-
319-
/* set up platform component driver */
320-
snd_sof_new_platform_drv(sdev);
321-
322274
/* register any debug/trace capabilities */
323275
ret = snd_sof_dbg_init(sdev);
324276
if (ret < 0) {
@@ -374,32 +326,8 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
374326
/* hereafter all FW boot flows are for PM reasons */
375327
sdev->first_boot = false;
376328

377-
/* now register audio DSP platform driver and dai */
378-
ret = devm_snd_soc_register_component(sdev->dev, &sdev->plat_drv,
379-
sof_ops(sdev)->drv,
380-
sof_ops(sdev)->num_drv);
381-
if (ret < 0) {
382-
dev_err(sdev->dev,
383-
"error: failed to register DSP DAI driver %d\n", ret);
384-
goto fw_run_err;
385-
}
386-
387-
drv_name = plat_data->machine->drv_name;
388-
mach = (const void *)plat_data->machine;
389-
size = sizeof(*plat_data->machine);
390-
391-
/* register machine driver, pass machine info as pdata */
392-
plat_data->pdev_mach =
393-
platform_device_register_data(sdev->dev, drv_name,
394-
PLATFORM_DEVID_NONE, mach, size);
395-
396-
if (IS_ERR(plat_data->pdev_mach)) {
397-
ret = PTR_ERR(plat_data->pdev_mach);
398-
goto fw_run_err;
399-
}
400-
401-
dev_dbg(sdev->dev, "created machine %s\n",
402-
dev_name(&plat_data->pdev_mach->dev));
329+
/* register audio client */
330+
sof_client_dev_register(sdev, "sof-audio", &sdev->sof_audio.pdev);
403331

404332
if (plat_data->sof_probe_complete)
405333
plat_data->sof_probe_complete(sdev->dev);
@@ -423,7 +351,6 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
423351
* They will be released with an explicit call to
424352
* snd_sof_device_remove() when the PCI/ACPI device is removed
425353
*/
426-
427354
fw_run_err:
428355
fw_load_err:
429356
ipc_err:
@@ -511,6 +438,9 @@ int snd_sof_device_remove(struct device *dev)
511438
if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE))
512439
cancel_work_sync(&sdev->probe_work);
513440

441+
/* unregister audio client device */
442+
sof_client_dev_unregister(&sdev->sof_audio.pdev);
443+
514444
snd_sof_fw_unload(sdev);
515445
snd_sof_ipc_free(sdev);
516446
snd_sof_free_debug(sdev);

sound/soc/sof/sof-audio.c

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2+
//
3+
// This file is provided under a dual BSD/GPLv2 license. When using or
4+
// redistributing this file, you may do so under either license.
5+
//
6+
// Copyright(c) 2019 Intel Corporation. All rights reserved.
7+
//
8+
// Author: Ranjani Sridharan <[email protected]>
9+
//
10+
11+
#include <linux/device.h>
12+
#include <linux/module.h>
13+
#include <linux/platform_device.h>
14+
#include <linux/pm_runtime.h>
15+
#include <sound/sof.h>
16+
#include "sof-priv.h"
17+
#include "ops.h"
18+
19+
/*
20+
* SOF Driver enumeration.
21+
*/
22+
static int sof_machine_check(struct snd_sof_dev *sdev)
23+
{
24+
struct snd_sof_pdata *plat_data = sdev->pdata;
25+
#if IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC)
26+
struct snd_soc_acpi_mach *machine;
27+
int ret;
28+
#endif
29+
30+
if (plat_data->machine)
31+
return 0;
32+
33+
#if !IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC)
34+
dev_err(sdev->dev, "error: no matching ASoC machine driver found - aborting probe\n");
35+
return -ENODEV;
36+
#else
37+
/* fallback to nocodec mode */
38+
dev_warn(sdev->dev, "No ASoC machine driver found - using nocodec\n");
39+
machine = devm_kzalloc(sdev->dev, sizeof(*machine), GFP_KERNEL);
40+
if (!machine)
41+
return -ENOMEM;
42+
43+
ret = sof_nocodec_setup(sdev->dev, plat_data, machine,
44+
plat_data->desc, plat_data->desc->ops);
45+
if (ret < 0)
46+
return ret;
47+
48+
plat_data->machine = machine;
49+
50+
return 0;
51+
#endif
52+
}
53+
54+
static int sof_audio_probe(struct platform_device *pdev)
55+
{
56+
struct snd_sof_dev *sdev = dev_get_drvdata(&pdev->dev);
57+
struct snd_sof_pdata *plat_data = sdev->pdata;
58+
struct snd_soc_acpi_mach *machine = plat_data->machine;
59+
const char *drv_name;
60+
int size;
61+
int ret;
62+
63+
/* check machine info */
64+
ret = sof_machine_check(sdev);
65+
if (ret < 0) {
66+
dev_err(&pdev->dev, "error: failed to get machine info %d\n",
67+
ret);
68+
goto err;
69+
}
70+
71+
/* set platform name */
72+
machine->mach_params.platform = dev_name(&pdev->dev);
73+
plat_data->platform = dev_name(&pdev->dev);
74+
75+
/* set up platform component driver */
76+
snd_sof_new_platform_drv(sdev);
77+
78+
/* now register audio DSP platform driver and dai */
79+
ret = devm_snd_soc_register_component(&pdev->dev, &sdev->plat_drv,
80+
sof_ops(sdev)->drv,
81+
sof_ops(sdev)->num_drv);
82+
if (ret < 0) {
83+
dev_err(&pdev->dev,
84+
"error: failed to register DSP DAI driver %d\n", ret);
85+
goto err;
86+
}
87+
88+
drv_name = plat_data->machine->drv_name;
89+
size = sizeof(*plat_data->machine);
90+
91+
/* register machine driver, pass machine info as pdata */
92+
plat_data->pdev_mach =
93+
platform_device_register_data(&pdev->dev, drv_name,
94+
PLATFORM_DEVID_NONE,
95+
(const void *)machine, size);
96+
97+
if (IS_ERR(plat_data->pdev_mach)) {
98+
ret = PTR_ERR(plat_data->pdev_mach);
99+
goto err;
100+
}
101+
102+
dev_dbg(&pdev->dev, "created machine %s\n",
103+
dev_name(&plat_data->pdev_mach->dev));
104+
105+
/* enable runtime PM */
106+
pm_runtime_set_autosuspend_delay(&pdev->dev, SND_SOF_SUSPEND_DELAY_MS);
107+
pm_runtime_use_autosuspend(&pdev->dev);
108+
109+
pm_runtime_enable(&pdev->dev);
110+
111+
pm_runtime_mark_last_busy(&pdev->dev);
112+
113+
pm_runtime_put_noidle(&pdev->dev);
114+
115+
return 0;
116+
117+
err:
118+
snd_sof_remove(sdev);
119+
snd_sof_fw_unload(sdev);
120+
snd_sof_ipc_free(sdev);
121+
snd_sof_free_debug(sdev);
122+
return ret;
123+
}
124+
125+
static struct platform_driver sof_audio_driver = {
126+
.driver = {
127+
.name = "sof-audio",
128+
},
129+
130+
.probe = sof_audio_probe,
131+
};
132+
133+
module_platform_driver(sof_audio_driver);
134+
135+
MODULE_DESCRIPTION("SOF Audio Client Platform Driver");
136+
MODULE_LICENSE("Dual BSD/GPL");
137+
MODULE_ALIAS("platform:sof-audio");

sound/soc/sof/sof-mfd.c

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2+
//
3+
// This file is provided under a dual BSD/GPLv2 license. When using or
4+
// redistributing this file, you may do so under either license.
5+
//
6+
// Copyright(c) 2019 Intel Corporation. All rights reserved.
7+
//
8+
// Author: Ranjani Sridharan <[email protected]>
9+
//
10+
#include <linux/device.h>
11+
#include "sof-mfd.h"
12+
13+
void sof_client_dev_register(struct snd_sof_dev *sdev, const char *name,
14+
struct platform_device *pdev)
15+
{
16+
int ret;
17+
18+
pdev = platform_device_alloc(name, -1);
19+
if (!pdev) {
20+
dev_err(sdev->dev, "error: Failed to allocate %s\n", name);
21+
return;
22+
}
23+
24+
pdev->dev.parent = sdev->dev;
25+
dev_set_drvdata(&pdev->dev, sdev);
26+
ret = platform_device_add(pdev);
27+
if (ret) {
28+
dev_err(sdev->dev, "error: Failed to register %s: %d\n", name,
29+
ret);
30+
platform_device_put(pdev);
31+
pdev = NULL;
32+
}
33+
dev_dbg(sdev->dev, "%s client registered\n", name);
34+
}
35+
EXPORT_SYMBOL(sof_client_dev_register);
36+
37+
void sof_client_dev_unregister(struct platform_device *pdev)
38+
{
39+
platform_device_del(pdev);
40+
}
41+
EXPORT_SYMBOL(sof_client_dev_unregister);

sound/soc/sof/sof-mfd.h

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
2+
/*
3+
* This file is provided under a dual BSD/GPLv2 license. When using or
4+
* redistributing this file, you may do so under either license.
5+
*
6+
* Copyright(c) 2019 Intel Corporation. All rights reserved.
7+
*
8+
* Author: Ranjani Sridharan <[email protected]>
9+
*/
10+
#include <linux/platform_device.h>
11+
#include "sof-priv.h"
12+
13+
#ifndef __SOUND_SOC_SOF_MFD_H
14+
#define __SOUND_SOC_SOF_MFD_H
15+
16+
/* client register/unregister */
17+
void sof_client_dev_register(struct snd_sof_dev *sdev, const char *name,
18+
struct platform_device *pdev);
19+
void sof_client_dev_unregister(struct platform_device *pdev);
20+
21+
#endif

sound/soc/sof/sof-pci-dev.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ static int sof_pci_probe(struct pci_dev *pci,
326326
dev_warn(dev, "warning: No matching ASoC machine driver found\n");
327327
} else {
328328
mach->mach_params.platform = dev_name(dev);
329+
dev_dbg(dev, "ranjani %s\n", dev_name(dev));
329330
sof_pdata->fw_filename = mach->sof_fw_filename;
330331
sof_pdata->tplg_filename = mach->sof_tplg_filename;
331332
}
@@ -335,7 +336,6 @@ static int sof_pci_probe(struct pci_dev *pci,
335336
sof_pdata->machine = mach;
336337
sof_pdata->desc = (struct sof_dev_desc *)pci_id->driver_data;
337338
sof_pdata->dev = dev;
338-
sof_pdata->platform = dev_name(dev);
339339

340340
/* alternate fw and tplg filenames ? */
341341
if (fw_path)

sound/soc/sof/sof-priv.h

+8
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,11 @@ struct snd_sof_dai {
370370
struct list_head list; /* list in sdev dai list */
371371
};
372372

373+
/* SOF MFD client device */
374+
struct sof_mfd_client {
375+
struct platform_device pdev;
376+
};
377+
373378
/*
374379
* SOF Device Level.
375380
*/
@@ -458,6 +463,9 @@ struct snd_sof_dev {
458463

459464
bool msi_enabled;
460465

466+
/* client devices */
467+
struct sof_mfd_client sof_audio;
468+
461469
void *private; /* core does not touch this */
462470
};
463471

sound/soc/sof/topology.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -2844,7 +2844,9 @@ static int sof_link_load(struct snd_soc_component *scomp, int index,
28442844
dev_err(sdev->dev, "error: no platforms\n");
28452845
return -EINVAL;
28462846
}
2847-
link->platforms->name = dev_name(sdev->dev);
2847+
2848+
/* set platform name */
2849+
link->platforms->name = dev_name(scomp->dev);
28482850

28492851
/*
28502852
* Set nonatomic property for FE dai links as their trigger action

0 commit comments

Comments
 (0)