Unverified Commit ef71b330 authored by Mark Brown's avatar Mark Brown
Browse files

ASoC: fsl: Support register and unregister rpmsg

Merge series from Chancel Liu <chancel.liu@nxp.com>:

	echo /lib/firmware/fw.elf > /sys/class/remoteproc/remoteproc0/firmware
(A)	echo start > /sys/class/remoteproc/remoteproc0/state
(B)	echo stop > /sys/class/remoteproc/remoteproc0/state

The rpmsg sound card is registered in (A) and unregistered in (B).
After "start", imx-audio-rpmsg registers devices for ASoC platform driver
and machine driver. Then sound card is registered. After "stop",
imx-audio-rpmsg unregisters devices for ASoC platform driver and machine
driver. Then sound card is unregistered.
parents 22247e40 c14445bd
Loading
Loading
Loading
Loading
+26 −17
Original line number Diff line number Diff line
@@ -135,7 +135,6 @@ static struct snd_soc_dai_driver fsl_rpmsg_dai = {

static const struct snd_soc_component_driver fsl_component = {
	.name			= "fsl-rpmsg",
	.legacy_dai_naming	= 1,
};

static const struct fsl_rpmsg_soc_data imx7ulp_data = {
@@ -190,19 +189,40 @@ MODULE_DEVICE_TABLE(of, fsl_rpmsg_ids);
static int fsl_rpmsg_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct snd_soc_dai_driver *dai_drv;
	const char *dai_name;
	struct fsl_rpmsg *rpmsg;
	int ret;

	dai_drv = devm_kzalloc(&pdev->dev, sizeof(struct snd_soc_dai_driver), GFP_KERNEL);
	if (!dai_drv)
		return -ENOMEM;
	memcpy(dai_drv, &fsl_rpmsg_dai, sizeof(fsl_rpmsg_dai));

	rpmsg = devm_kzalloc(&pdev->dev, sizeof(struct fsl_rpmsg), GFP_KERNEL);
	if (!rpmsg)
		return -ENOMEM;

	rpmsg->soc_data = of_device_get_match_data(&pdev->dev);

	fsl_rpmsg_dai.playback.rates = rpmsg->soc_data->rates;
	fsl_rpmsg_dai.capture.rates = rpmsg->soc_data->rates;
	fsl_rpmsg_dai.playback.formats = rpmsg->soc_data->formats;
	fsl_rpmsg_dai.capture.formats = rpmsg->soc_data->formats;
	if (rpmsg->soc_data) {
		dai_drv->playback.rates = rpmsg->soc_data->rates;
		dai_drv->capture.rates = rpmsg->soc_data->rates;
		dai_drv->playback.formats = rpmsg->soc_data->formats;
		dai_drv->capture.formats = rpmsg->soc_data->formats;
	}

	/* Use rpmsg channel name as cpu dai name */
	ret = of_property_read_string(np, "fsl,rpmsg-channel-name", &dai_name);
	if (ret) {
		if (ret == -EINVAL) {
			dai_name = "rpmsg-audio-channel";
		} else {
			dev_err(&pdev->dev, "Failed to get rpmsg channel name: %d!\n", ret);
			return ret;
		}
	}
	dai_drv->name = dai_name;

	if (of_property_read_bool(np, "fsl,enable-lpa")) {
		rpmsg->enable_lpa = 1;
@@ -236,21 +256,10 @@ static int fsl_rpmsg_probe(struct platform_device *pdev)
	pm_runtime_enable(&pdev->dev);

	ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,
					      &fsl_rpmsg_dai, 1);
					      dai_drv, 1);
	if (ret)
		goto err_pm_disable;

	rpmsg->card_pdev = platform_device_register_data(&pdev->dev,
							 "imx-audio-rpmsg",
							 PLATFORM_DEVID_AUTO,
							 NULL,
							 0);
	if (IS_ERR(rpmsg->card_pdev)) {
		dev_err(&pdev->dev, "failed to register rpmsg card\n");
		ret = PTR_ERR(rpmsg->card_pdev);
		goto err_pm_disable;
	}

	return 0;

err_pm_disable:
+18 −3
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
 */
struct imx_audio_rpmsg {
	struct platform_device *rpmsg_pdev;
	struct platform_device *card_pdev;
};

static int imx_audio_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len,
@@ -87,14 +88,24 @@ static int imx_audio_rpmsg_probe(struct rpmsg_device *rpdev)

	/* Register platform driver for rpmsg routine */
	data->rpmsg_pdev = platform_device_register_data(&rpdev->dev,
							 IMX_PCM_DRV_NAME,
							 PLATFORM_DEVID_AUTO,
							 rpdev->id.name,
							 PLATFORM_DEVID_NONE,
							 NULL, 0);
	if (IS_ERR(data->rpmsg_pdev)) {
		dev_err(&rpdev->dev, "failed to register rpmsg platform.\n");
		ret = PTR_ERR(data->rpmsg_pdev);
	}

	data->card_pdev = platform_device_register_data(&rpdev->dev,
							"imx-audio-rpmsg",
							PLATFORM_DEVID_AUTO,
							rpdev->id.name,
							strlen(rpdev->id.name) + 1);
	if (IS_ERR(data->card_pdev)) {
		dev_err(&rpdev->dev, "failed to register rpmsg card.\n");
		ret = PTR_ERR(data->card_pdev);
	}

	return ret;
}

@@ -105,6 +116,9 @@ static void imx_audio_rpmsg_remove(struct rpmsg_device *rpdev)
	if (data->rpmsg_pdev)
		platform_device_unregister(data->rpmsg_pdev);

	if (data->card_pdev)
		platform_device_unregister(data->card_pdev);

	dev_info(&rpdev->dev, "audio rpmsg driver is removed\n");
}

@@ -113,6 +127,7 @@ static struct rpmsg_device_id imx_audio_rpmsg_id_table[] = {
	{ .name = "rpmsg-micfil-channel" },
	{ },
};
MODULE_DEVICE_TABLE(rpmsg, imx_audio_rpmsg_id_table);

static struct rpmsg_driver imx_audio_rpmsg_driver = {
	.drv.name	= "imx_audio_rpmsg",
@@ -126,5 +141,5 @@ module_rpmsg_driver(imx_audio_rpmsg_driver);

MODULE_DESCRIPTION("Freescale SoC Audio RPMSG interface");
MODULE_AUTHOR("Shengjiu Wang <shengjiu.wang@nxp.com>");
MODULE_ALIAS("platform:imx_audio_rpmsg");
MODULE_ALIAS("rpmsg:imx_audio_rpmsg");
MODULE_LICENSE("GPL v2");
+8 −3
Original line number Diff line number Diff line
@@ -732,9 +732,6 @@ static int imx_rpmsg_pcm_probe(struct platform_device *pdev)
		goto fail;
	}

	/* platform component name is used by machine driver to link with */
	component->name = info->rpdev->id.name;

#ifdef CONFIG_DEBUG_FS
	component->debugfs_prefix = "rpmsg";
#endif
@@ -822,9 +819,17 @@ static const struct dev_pm_ops imx_rpmsg_pcm_pm_ops = {
				imx_rpmsg_pcm_resume)
};

static const struct platform_device_id imx_rpmsg_pcm_id_table[] = {
	{ .name	= "rpmsg-audio-channel" },
	{ .name	= "rpmsg-micfil-channel" },
	{ },
};
MODULE_DEVICE_TABLE(platform, imx_rpmsg_pcm_id_table);

static struct platform_driver imx_pcm_rpmsg_driver = {
	.probe  = imx_rpmsg_pcm_probe,
	.remove_new = imx_rpmsg_pcm_remove,
	.id_table = imx_rpmsg_pcm_id_table,
	.driver = {
		.name = IMX_PCM_DRV_NAME,
		.pm = &imx_rpmsg_pcm_pm_ops,
+19 −9
Original line number Diff line number Diff line
@@ -108,10 +108,8 @@ static int imx_rpmsg_late_probe(struct snd_soc_card *card)
static int imx_rpmsg_probe(struct platform_device *pdev)
{
	struct snd_soc_dai_link_component *dlc;
	struct device *dev = pdev->dev.parent;
	/* rpmsg_pdev is the platform device for the rpmsg node that probed us */
	struct platform_device *rpmsg_pdev = to_platform_device(dev);
	struct device_node *np = rpmsg_pdev->dev.of_node;
	struct snd_soc_dai *cpu_dai;
	struct device_node *np = NULL;
	struct of_phandle_args args;
	const char *platform_name;
	struct imx_rpmsg *data;
@@ -127,10 +125,6 @@ static int imx_rpmsg_probe(struct platform_device *pdev)
		goto fail;
	}

	ret = of_reserved_mem_device_init_by_idx(&pdev->dev, np, 0);
	if (ret)
		dev_warn(&pdev->dev, "no reserved DMA memory\n");

	data->dai.cpus = &dlc[0];
	data->dai.num_cpus = 1;
	data->dai.platforms = &dlc[1];
@@ -152,6 +146,23 @@ static int imx_rpmsg_probe(struct platform_device *pdev)
	 */
	data->dai.ignore_pmdown_time = 1;

	data->dai.cpus->dai_name = pdev->dev.platform_data;
	cpu_dai = snd_soc_find_dai(data->dai.cpus);
	if (!cpu_dai) {
		ret = -EPROBE_DEFER;
		goto fail;
	}
	np = cpu_dai->dev->of_node;
	if (!np) {
		dev_err(&pdev->dev, "failed to parse CPU DAI device node\n");
		ret = -ENODEV;
		goto fail;
	}

	ret = of_reserved_mem_device_init_by_idx(&pdev->dev, np, 0);
	if (ret)
		dev_warn(&pdev->dev, "no reserved DMA memory\n");

	/* Optional codec node */
	ret = of_parse_phandle_with_fixed_args(np, "audio-codec", 0, 0, &args);
	if (ret) {
@@ -170,7 +181,6 @@ static int imx_rpmsg_probe(struct platform_device *pdev)
			data->sysclk = clk_get_rate(clk);
	}

	data->dai.cpus->dai_name = dev_name(&rpmsg_pdev->dev);
	if (!of_property_read_string(np, "fsl,rpmsg-channel-name", &platform_name))
		data->dai.platforms->name = platform_name;
	else