~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/fsl/imx-audio-rpmsg.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0+
  2 // Copyright 2017-2020 NXP
  3 
  4 #include <linux/module.h>
  5 #include <linux/rpmsg.h>
  6 #include "imx-pcm-rpmsg.h"
  7 
  8 /*
  9  * struct imx_audio_rpmsg: private data
 10  *
 11  * @rpmsg_pdev: pointer of platform device
 12  */
 13 struct imx_audio_rpmsg {
 14         struct platform_device *rpmsg_pdev;
 15         struct platform_device *card_pdev;
 16 };
 17 
 18 static int imx_audio_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len,
 19                               void *priv, u32 src)
 20 {
 21         struct imx_audio_rpmsg *rpmsg = dev_get_drvdata(&rpdev->dev);
 22         struct rpmsg_r_msg *r_msg = (struct rpmsg_r_msg *)data;
 23         struct rpmsg_info *info;
 24         struct rpmsg_msg *msg;
 25         unsigned long flags;
 26 
 27         if (!rpmsg->rpmsg_pdev)
 28                 return 0;
 29 
 30         info = platform_get_drvdata(rpmsg->rpmsg_pdev);
 31 
 32         dev_dbg(&rpdev->dev, "get from%d: cmd:%d. %d\n",
 33                 src, r_msg->header.cmd, r_msg->param.resp);
 34 
 35         switch (r_msg->header.type) {
 36         case MSG_TYPE_C:
 37                 /* TYPE C is notification from M core */
 38                 switch (r_msg->header.cmd) {
 39                 case TX_PERIOD_DONE:
 40                         spin_lock_irqsave(&info->lock[TX], flags);
 41                         msg = &info->msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM];
 42                         msg->r_msg.param.buffer_tail =
 43                                                 r_msg->param.buffer_tail;
 44                         msg->r_msg.param.buffer_tail %= info->num_period[TX];
 45                         spin_unlock_irqrestore(&info->lock[TX], flags);
 46                         info->callback[TX](info->callback_param[TX]);
 47                         break;
 48                 case RX_PERIOD_DONE:
 49                         spin_lock_irqsave(&info->lock[RX], flags);
 50                         msg = &info->msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM];
 51                         msg->r_msg.param.buffer_tail =
 52                                                 r_msg->param.buffer_tail;
 53                         msg->r_msg.param.buffer_tail %= info->num_period[1];
 54                         spin_unlock_irqrestore(&info->lock[RX], flags);
 55                         info->callback[RX](info->callback_param[RX]);
 56                         break;
 57                 default:
 58                         dev_warn(&rpdev->dev, "unknown msg command\n");
 59                         break;
 60                 }
 61                 break;
 62         case MSG_TYPE_B:
 63                 /* TYPE B is response msg */
 64                 memcpy(&info->r_msg, r_msg, sizeof(struct rpmsg_r_msg));
 65                 complete(&info->cmd_complete);
 66                 break;
 67         default:
 68                 dev_warn(&rpdev->dev, "unknown msg type\n");
 69                 break;
 70         }
 71 
 72         return 0;
 73 }
 74 
 75 static int imx_audio_rpmsg_probe(struct rpmsg_device *rpdev)
 76 {
 77         struct imx_audio_rpmsg *data;
 78         int ret = 0;
 79 
 80         dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n",
 81                  rpdev->src, rpdev->dst);
 82 
 83         data = devm_kzalloc(&rpdev->dev, sizeof(*data), GFP_KERNEL);
 84         if (!data)
 85                 return -ENOMEM;
 86 
 87         dev_set_drvdata(&rpdev->dev, data);
 88 
 89         /* Register platform driver for rpmsg routine */
 90         data->rpmsg_pdev = platform_device_register_data(&rpdev->dev,
 91                                                          rpdev->id.name,
 92                                                          PLATFORM_DEVID_NONE,
 93                                                          NULL, 0);
 94         if (IS_ERR(data->rpmsg_pdev)) {
 95                 dev_err(&rpdev->dev, "failed to register rpmsg platform.\n");
 96                 ret = PTR_ERR(data->rpmsg_pdev);
 97         }
 98 
 99         data->card_pdev = platform_device_register_data(&rpdev->dev,
100                                                         "imx-audio-rpmsg",
101                                                         PLATFORM_DEVID_AUTO,
102                                                         rpdev->id.name,
103                                                         strlen(rpdev->id.name) + 1);
104         if (IS_ERR(data->card_pdev)) {
105                 dev_err(&rpdev->dev, "failed to register rpmsg card.\n");
106                 ret = PTR_ERR(data->card_pdev);
107         }
108 
109         return ret;
110 }
111 
112 static void imx_audio_rpmsg_remove(struct rpmsg_device *rpdev)
113 {
114         struct imx_audio_rpmsg *data = dev_get_drvdata(&rpdev->dev);
115 
116         if (data->rpmsg_pdev)
117                 platform_device_unregister(data->rpmsg_pdev);
118 
119         if (data->card_pdev)
120                 platform_device_unregister(data->card_pdev);
121 
122         dev_info(&rpdev->dev, "audio rpmsg driver is removed\n");
123 }
124 
125 static struct rpmsg_device_id imx_audio_rpmsg_id_table[] = {
126         { .name = "rpmsg-audio-channel" },
127         { .name = "rpmsg-micfil-channel" },
128         { },
129 };
130 MODULE_DEVICE_TABLE(rpmsg, imx_audio_rpmsg_id_table);
131 
132 static struct rpmsg_driver imx_audio_rpmsg_driver = {
133         .drv.name       = "imx_audio_rpmsg",
134         .id_table       = imx_audio_rpmsg_id_table,
135         .probe          = imx_audio_rpmsg_probe,
136         .callback       = imx_audio_rpmsg_cb,
137         .remove         = imx_audio_rpmsg_remove,
138 };
139 
140 module_rpmsg_driver(imx_audio_rpmsg_driver);
141 
142 MODULE_DESCRIPTION("Freescale SoC Audio RPMSG interface");
143 MODULE_AUTHOR("Shengjiu Wang <shengjiu.wang@nxp.com>");
144 MODULE_ALIAS("rpmsg:imx_audio_rpmsg");
145 MODULE_LICENSE("GPL v2");
146 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php