From 4e1aa17692fb8e9fc6354dd42699813be787862a Mon Sep 17 00:00:00 2001 From: Jindong Date: Wed, 26 Aug 2020 10:22:40 +0800 Subject: 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 Reviewed-by: Shengjiu Wang --- sound/soc/fsl/imx-i2s-rpmsg.c | 170 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 sound/soc/fsl/imx-i2s-rpmsg.c (limited to 'sound/soc/fsl/imx-i2s-rpmsg.c') diff --git a/sound/soc/fsl/imx-i2s-rpmsg.c b/sound/soc/fsl/imx-i2s-rpmsg.c new file mode 100644 index 000000000000..4e75394d0294 --- /dev/null +++ b/sound/soc/fsl/imx-i2s-rpmsg.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright 2020 NXP + +#include +#include +#include + +#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"); -- cgit v1.2.3