MA-17777 ASoC: imx-pcm-rpmsg: Move i2s rpmsg driver to individual file

Move i2s rpmsg driver to a new file: imx-i2s-rpmsg.c
This new driver should be probed after fsl_rpmsg_i2s, which
calls imx_rpmsg_platform_register (in imx-pcm-rpmsg) to fill
global variable: i2s_info_g.

Signed-off-by: Jindong <jindong.yue@nxp.com>
Reviewed-by: Shengjiu Wang <shengjiu.wang@nxp.com>
This commit is contained in:
Jindong 2020-08-26 10:22:40 +08:00
parent a8a7d970e2
commit 4e1aa17692
4 changed files with 177 additions and 160 deletions

View File

@ -143,6 +143,10 @@ config SND_SOC_IMX_PCM_RPMSG
depends on HAVE_IMX_RPMSG
select SND_SOC_GENERIC_DMAENGINE_PCM
config SND_SOC_IMX_I2S_RPMSG
tristate
depends on SND_SOC_FSL_RPMSG_I2S
config SND_SOC_IMX_AUDMUX
tristate "Digital Audio Mux module support"
help
@ -450,6 +454,7 @@ config SND_SOC_IMX_RPMSG
tristate "SoC Audio support for i.MX boards with rpmsg"
depends on HAVE_IMX_RPMSG
select SND_SOC_IMX_PCM_RPMSG
select SND_SOC_IMX_I2S_RPMSG
select SND_SOC_FSL_RPMSG_I2S
select SND_SOC_RPMSG_WM8960
select SND_SOC_RPMSG_AK4497

View File

@ -74,6 +74,7 @@ obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o imx-pcm-dma-v2.o
obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o
obj-$(CONFIG_SND_SOC_IMX_HDMI_DMA) += imx-hdmi-dma.o hdmi_pcm.o
obj-$(CONFIG_SND_SOC_IMX_PCM_RPMSG) += imx-pcm-rpmsg.o
obj-$(CONFIG_SND_SOC_IMX_I2S_RPMSG) += imx-i2s-rpmsg.o
# i.MX Machine Support
snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o

View File

@ -0,0 +1,170 @@
// SPDX-License-Identifier: GPL-2.0+
// Copyright 2020 NXP
#include <linux/module.h>
#include <linux/rpmsg.h>
#include <linux/imx_rpmsg.h>
#include "fsl_rpmsg_i2s.h"
extern struct i2s_info *i2s_info_g;
static int i2s_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len,
void *priv, u32 src)
{
struct i2s_rpmsg_r *msg = (struct i2s_rpmsg_r *)data;
struct i2s_rpmsg *rpmsg;
unsigned long flags;
dev_dbg(&rpdev->dev, "get from%d: cmd:%d. %d\n",
src, msg->header.cmd, msg->param.resp);
if (msg->header.type == I2S_TYPE_C) {
if (msg->header.cmd == I2S_TX_PERIOD_DONE) {
spin_lock_irqsave(&i2s_info_g->lock[0], flags);
rpmsg = &i2s_info_g->rpmsg[I2S_TX_PERIOD_DONE + I2S_TYPE_A_NUM];
if (msg->header.major == 1 && msg->header.minor == 2)
rpmsg->recv_msg.param.buffer_tail =
msg->param.buffer_tail;
else
rpmsg->recv_msg.param.buffer_tail++;
rpmsg->recv_msg.param.buffer_tail %=
i2s_info_g->num_period[0];
spin_unlock_irqrestore(&i2s_info_g->lock[0], flags);
i2s_info_g->callback[0](i2s_info_g->callback_param[0]);
} else if (msg->header.cmd == I2S_RX_PERIOD_DONE) {
spin_lock_irqsave(&i2s_info_g->lock[1], flags);
rpmsg = &i2s_info_g->rpmsg[I2S_RX_PERIOD_DONE + I2S_TYPE_A_NUM];
if (msg->header.major == 1 && msg->header.minor == 2)
rpmsg->recv_msg.param.buffer_tail =
msg->param.buffer_tail;
else
rpmsg->recv_msg.param.buffer_tail++;
rpmsg->recv_msg.param.buffer_tail %=
i2s_info_g->num_period[1];
spin_unlock_irqrestore(&i2s_info_g->lock[1], flags);
i2s_info_g->callback[1](i2s_info_g->callback_param[1]);
}
}
if (msg->header.type == I2S_TYPE_B) {
memcpy(&i2s_info_g->recv_msg, msg, sizeof(struct i2s_rpmsg_r));
complete(&i2s_info_g->cmd_complete);
}
return 0;
}
static int i2s_rpmsg_probe(struct rpmsg_device *rpdev)
{
struct platform_device *codec_pdev;
struct fsl_rpmsg_i2s *rpmsg_i2s = NULL;
struct fsl_rpmsg_codec rpmsg_codec[3];
int ret;
if (!i2s_info_g)
return 0;
i2s_info_g->rpdev = rpdev;
init_completion(&i2s_info_g->cmd_complete);
dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n",
rpdev->src, rpdev->dst);
rpmsg_i2s = container_of(i2s_info_g, struct fsl_rpmsg_i2s, i2s_info);
if (rpmsg_i2s->codec_in_dt)
return 0;
if (rpmsg_i2s->codec_wm8960) {
rpmsg_codec[0].audioindex = rpmsg_i2s->codec_wm8960 >> 16;
rpmsg_codec[0].shared_lrclk = true;
rpmsg_codec[0].capless = false;
codec_pdev = platform_device_register_data(
&rpmsg_i2s->pdev->dev,
RPMSG_CODEC_DRV_NAME_WM8960,
PLATFORM_DEVID_NONE,
&rpmsg_codec[0], sizeof(struct fsl_rpmsg_codec));
if (IS_ERR(codec_pdev)) {
dev_err(&rpdev->dev,
"failed to register rpmsg audio codec\n");
ret = PTR_ERR(codec_pdev);
return ret;
}
}
if (rpmsg_i2s->codec_cs42888) {
rpmsg_codec[1].audioindex = rpmsg_i2s->codec_cs42888 >> 16;
strcpy(rpmsg_codec[1].name, "cs42888");
rpmsg_codec[1].num_adcs = 2;
codec_pdev = platform_device_register_data(
&rpmsg_i2s->pdev->dev,
RPMSG_CODEC_DRV_NAME_CS42888,
PLATFORM_DEVID_NONE,
&rpmsg_codec[1], sizeof(struct fsl_rpmsg_codec));
if (IS_ERR(codec_pdev)) {
dev_err(&rpdev->dev,
"failed to register rpmsg audio codec\n");
ret = PTR_ERR(codec_pdev);
return ret;
}
}
if (rpmsg_i2s->codec_ak4497) {
rpmsg_codec[2].audioindex = rpmsg_i2s->codec_ak4497 >> 16;
codec_pdev = platform_device_register_data(
&rpmsg_i2s->pdev->dev,
RPMSG_CODEC_DRV_NAME_AK4497,
PLATFORM_DEVID_NONE,
&rpmsg_codec[2], sizeof(struct fsl_rpmsg_codec));
if (IS_ERR(codec_pdev)) {
dev_err(&rpdev->dev,
"failed to register rpmsg audio codec\n");
ret = PTR_ERR(codec_pdev);
return ret;
}
}
return 0;
}
static void i2s_rpmsg_remove(struct rpmsg_device *rpdev)
{
dev_info(&rpdev->dev, "i2s rpmsg driver is removed\n");
}
static struct rpmsg_device_id i2s_rpmsg_id_table[] = {
{ .name = "rpmsg-audio-channel" },
{ },
};
static struct rpmsg_driver i2s_rpmsg_driver = {
.drv.name = "i2s_rpmsg",
.drv.owner = THIS_MODULE,
.id_table = i2s_rpmsg_id_table,
.probe = i2s_rpmsg_probe,
.callback = i2s_rpmsg_cb,
.remove = i2s_rpmsg_remove,
};
static int __init i2s_rpmsg_init(void)
{
return register_rpmsg_driver(&i2s_rpmsg_driver);
}
static void __exit i2s_rpmsg_exit(void)
{
unregister_rpmsg_driver(&i2s_rpmsg_driver);
}
module_init(i2s_rpmsg_init);
module_exit(i2s_rpmsg_exit);
MODULE_LICENSE("GPL v2");

View File

@ -11,8 +11,6 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/rpmsg.h>
#include <linux/imx_rpmsg.h>
#include <linux/delay.h>
#include <sound/core.h>
#include <sound/pcm.h>
@ -27,6 +25,7 @@
#define DRV_NAME "imx_pcm_rpmsg"
struct i2s_info *i2s_info_g;
EXPORT_SYMBOL(i2s_info_g);
static struct snd_pcm_hardware imx_rpmsg_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
@ -735,162 +734,4 @@ int imx_rpmsg_platform_register(struct device *dev)
}
EXPORT_SYMBOL_GPL(imx_rpmsg_platform_register);
static int i2s_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len,
void *priv, u32 src)
{
struct i2s_rpmsg_r *msg = (struct i2s_rpmsg_r *)data;
struct i2s_rpmsg *rpmsg;
unsigned long flags;
dev_dbg(&rpdev->dev, "get from%d: cmd:%d. %d\n",
src, msg->header.cmd, msg->param.resp);
if (msg->header.type == I2S_TYPE_C) {
if (msg->header.cmd == I2S_TX_PERIOD_DONE) {
spin_lock_irqsave(&i2s_info_g->lock[0], flags);
rpmsg = &i2s_info_g->rpmsg[I2S_TX_PERIOD_DONE + I2S_TYPE_A_NUM];
if (msg->header.major == 1 && msg->header.minor == 2)
rpmsg->recv_msg.param.buffer_tail =
msg->param.buffer_tail;
else
rpmsg->recv_msg.param.buffer_tail++;
rpmsg->recv_msg.param.buffer_tail %=
i2s_info_g->num_period[0];
spin_unlock_irqrestore(&i2s_info_g->lock[0], flags);
i2s_info_g->callback[0](i2s_info_g->callback_param[0]);
} else if (msg->header.cmd == I2S_RX_PERIOD_DONE) {
spin_lock_irqsave(&i2s_info_g->lock[1], flags);
rpmsg = &i2s_info_g->rpmsg[I2S_RX_PERIOD_DONE + I2S_TYPE_A_NUM];
if (msg->header.major == 1 && msg->header.minor == 2)
rpmsg->recv_msg.param.buffer_tail =
msg->param.buffer_tail;
else
rpmsg->recv_msg.param.buffer_tail++;
rpmsg->recv_msg.param.buffer_tail %=
i2s_info_g->num_period[1];
spin_unlock_irqrestore(&i2s_info_g->lock[1], flags);
i2s_info_g->callback[1](i2s_info_g->callback_param[1]);
}
}
if (msg->header.type == I2S_TYPE_B) {
memcpy(&i2s_info_g->recv_msg, msg, sizeof(struct i2s_rpmsg_r));
complete(&i2s_info_g->cmd_complete);
}
return 0;
}
static int i2s_rpmsg_probe(struct rpmsg_device *rpdev)
{
struct platform_device *codec_pdev;
struct fsl_rpmsg_i2s *rpmsg_i2s = NULL;
struct fsl_rpmsg_codec rpmsg_codec[3];
int ret;
if (!i2s_info_g)
return 0;
i2s_info_g->rpdev = rpdev;
init_completion(&i2s_info_g->cmd_complete);
dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n",
rpdev->src, rpdev->dst);
rpmsg_i2s = container_of(i2s_info_g, struct fsl_rpmsg_i2s, i2s_info);
if (rpmsg_i2s->codec_in_dt)
return 0;
if (rpmsg_i2s->codec_wm8960) {
rpmsg_codec[0].audioindex = rpmsg_i2s->codec_wm8960 >> 16;
rpmsg_codec[0].shared_lrclk = true;
rpmsg_codec[0].capless = false;
codec_pdev = platform_device_register_data(
&rpmsg_i2s->pdev->dev,
RPMSG_CODEC_DRV_NAME_WM8960,
PLATFORM_DEVID_NONE,
&rpmsg_codec[0], sizeof(struct fsl_rpmsg_codec));
if (IS_ERR(codec_pdev)) {
dev_err(&rpdev->dev,
"failed to register rpmsg audio codec\n");
ret = PTR_ERR(codec_pdev);
return ret;
}
}
if (rpmsg_i2s->codec_cs42888) {
rpmsg_codec[1].audioindex = rpmsg_i2s->codec_cs42888 >> 16;
strcpy(rpmsg_codec[1].name, "cs42888");
rpmsg_codec[1].num_adcs = 2;
codec_pdev = platform_device_register_data(
&rpmsg_i2s->pdev->dev,
RPMSG_CODEC_DRV_NAME_CS42888,
PLATFORM_DEVID_NONE,
&rpmsg_codec[1], sizeof(struct fsl_rpmsg_codec));
if (IS_ERR(codec_pdev)) {
dev_err(&rpdev->dev,
"failed to register rpmsg audio codec\n");
ret = PTR_ERR(codec_pdev);
return ret;
}
}
if (rpmsg_i2s->codec_ak4497) {
rpmsg_codec[2].audioindex = rpmsg_i2s->codec_ak4497 >> 16;
codec_pdev = platform_device_register_data(
&rpmsg_i2s->pdev->dev,
RPMSG_CODEC_DRV_NAME_AK4497,
PLATFORM_DEVID_NONE,
&rpmsg_codec[2], sizeof(struct fsl_rpmsg_codec));
if (IS_ERR(codec_pdev)) {
dev_err(&rpdev->dev,
"failed to register rpmsg audio codec\n");
ret = PTR_ERR(codec_pdev);
return ret;
}
}
return 0;
}
static void i2s_rpmsg_remove(struct rpmsg_device *rpdev)
{
dev_info(&rpdev->dev, "i2s rpmsg driver is removed\n");
}
static struct rpmsg_device_id i2s_rpmsg_id_table[] = {
{ .name = "rpmsg-audio-channel" },
{ },
};
static struct rpmsg_driver i2s_rpmsg_driver = {
.drv.name = "i2s_rpmsg",
.drv.owner = THIS_MODULE,
.id_table = i2s_rpmsg_id_table,
.probe = i2s_rpmsg_probe,
.callback = i2s_rpmsg_cb,
.remove = i2s_rpmsg_remove,
};
static int __init i2s_rpmsg_init(void)
{
return register_rpmsg_driver(&i2s_rpmsg_driver);
}
static void __exit i2s_rpmsg_exit(void)
{
unregister_rpmsg_driver(&i2s_rpmsg_driver);
}
module_init(i2s_rpmsg_init);
module_exit(i2s_rpmsg_exit);
MODULE_LICENSE("GPL");