Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/fsl/imx-audio-rpmsg.c
26428 views
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 <[email protected]>");
144
MODULE_ALIAS("rpmsg:imx_audio_rpmsg");
145
MODULE_LICENSE("GPL v2");
146
147