1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Greybus Audio Device Class Protocol helpers
4 *
5 * Copyright 2015-2016 Google Inc.
6 */
7
8 #include <linux/greybus.h>
9 #include "audio_apbridgea.h"
10 #include "audio_codec.h"
11
gb_audio_apbridgea_set_config(struct gb_connection * connection,__u16 i2s_port,__u32 format,__u32 rate,__u32 mclk_freq)12 int gb_audio_apbridgea_set_config(struct gb_connection *connection,
13 __u16 i2s_port, __u32 format, __u32 rate,
14 __u32 mclk_freq)
15 {
16 struct audio_apbridgea_set_config_request req;
17
18 req.hdr.type = AUDIO_APBRIDGEA_TYPE_SET_CONFIG;
19 req.hdr.i2s_port = cpu_to_le16(i2s_port);
20 req.format = cpu_to_le32(format);
21 req.rate = cpu_to_le32(rate);
22 req.mclk_freq = cpu_to_le32(mclk_freq);
23
24 return gb_hd_output(connection->hd, &req, sizeof(req),
25 GB_APB_REQUEST_AUDIO_CONTROL, true);
26 }
27 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_config);
28
gb_audio_apbridgea_register_cport(struct gb_connection * connection,__u16 i2s_port,__u16 cportid,__u8 direction)29 int gb_audio_apbridgea_register_cport(struct gb_connection *connection,
30 __u16 i2s_port, __u16 cportid,
31 __u8 direction)
32 {
33 struct audio_apbridgea_register_cport_request req;
34 int ret;
35
36 req.hdr.type = AUDIO_APBRIDGEA_TYPE_REGISTER_CPORT;
37 req.hdr.i2s_port = cpu_to_le16(i2s_port);
38 req.cport = cpu_to_le16(cportid);
39 req.direction = direction;
40
41 ret = gb_pm_runtime_get_sync(connection->bundle);
42 if (ret)
43 return ret;
44
45 return gb_hd_output(connection->hd, &req, sizeof(req),
46 GB_APB_REQUEST_AUDIO_CONTROL, true);
47 }
48 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_register_cport);
49
gb_audio_apbridgea_unregister_cport(struct gb_connection * connection,__u16 i2s_port,__u16 cportid,__u8 direction)50 int gb_audio_apbridgea_unregister_cport(struct gb_connection *connection,
51 __u16 i2s_port, __u16 cportid,
52 __u8 direction)
53 {
54 struct audio_apbridgea_unregister_cport_request req;
55 int ret;
56
57 req.hdr.type = AUDIO_APBRIDGEA_TYPE_UNREGISTER_CPORT;
58 req.hdr.i2s_port = cpu_to_le16(i2s_port);
59 req.cport = cpu_to_le16(cportid);
60 req.direction = direction;
61
62 ret = gb_hd_output(connection->hd, &req, sizeof(req),
63 GB_APB_REQUEST_AUDIO_CONTROL, true);
64
65 gb_pm_runtime_put_autosuspend(connection->bundle);
66
67 return ret;
68 }
69 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_unregister_cport);
70
gb_audio_apbridgea_set_tx_data_size(struct gb_connection * connection,__u16 i2s_port,__u16 size)71 int gb_audio_apbridgea_set_tx_data_size(struct gb_connection *connection,
72 __u16 i2s_port, __u16 size)
73 {
74 struct audio_apbridgea_set_tx_data_size_request req;
75
76 req.hdr.type = AUDIO_APBRIDGEA_TYPE_SET_TX_DATA_SIZE;
77 req.hdr.i2s_port = cpu_to_le16(i2s_port);
78 req.size = cpu_to_le16(size);
79
80 return gb_hd_output(connection->hd, &req, sizeof(req),
81 GB_APB_REQUEST_AUDIO_CONTROL, true);
82 }
83 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_tx_data_size);
84
gb_audio_apbridgea_prepare_tx(struct gb_connection * connection,__u16 i2s_port)85 int gb_audio_apbridgea_prepare_tx(struct gb_connection *connection,
86 __u16 i2s_port)
87 {
88 struct audio_apbridgea_prepare_tx_request req;
89
90 req.hdr.type = AUDIO_APBRIDGEA_TYPE_PREPARE_TX;
91 req.hdr.i2s_port = cpu_to_le16(i2s_port);
92
93 return gb_hd_output(connection->hd, &req, sizeof(req),
94 GB_APB_REQUEST_AUDIO_CONTROL, true);
95 }
96 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_prepare_tx);
97
gb_audio_apbridgea_start_tx(struct gb_connection * connection,__u16 i2s_port,__u64 timestamp)98 int gb_audio_apbridgea_start_tx(struct gb_connection *connection,
99 __u16 i2s_port, __u64 timestamp)
100 {
101 struct audio_apbridgea_start_tx_request req;
102
103 req.hdr.type = AUDIO_APBRIDGEA_TYPE_START_TX;
104 req.hdr.i2s_port = cpu_to_le16(i2s_port);
105 req.timestamp = cpu_to_le64(timestamp);
106
107 return gb_hd_output(connection->hd, &req, sizeof(req),
108 GB_APB_REQUEST_AUDIO_CONTROL, true);
109 }
110 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_start_tx);
111
gb_audio_apbridgea_stop_tx(struct gb_connection * connection,__u16 i2s_port)112 int gb_audio_apbridgea_stop_tx(struct gb_connection *connection, __u16 i2s_port)
113 {
114 struct audio_apbridgea_stop_tx_request req;
115
116 req.hdr.type = AUDIO_APBRIDGEA_TYPE_STOP_TX;
117 req.hdr.i2s_port = cpu_to_le16(i2s_port);
118
119 return gb_hd_output(connection->hd, &req, sizeof(req),
120 GB_APB_REQUEST_AUDIO_CONTROL, true);
121 }
122 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_stop_tx);
123
gb_audio_apbridgea_shutdown_tx(struct gb_connection * connection,__u16 i2s_port)124 int gb_audio_apbridgea_shutdown_tx(struct gb_connection *connection,
125 __u16 i2s_port)
126 {
127 struct audio_apbridgea_shutdown_tx_request req;
128
129 req.hdr.type = AUDIO_APBRIDGEA_TYPE_SHUTDOWN_TX;
130 req.hdr.i2s_port = cpu_to_le16(i2s_port);
131
132 return gb_hd_output(connection->hd, &req, sizeof(req),
133 GB_APB_REQUEST_AUDIO_CONTROL, true);
134 }
135 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_shutdown_tx);
136
gb_audio_apbridgea_set_rx_data_size(struct gb_connection * connection,__u16 i2s_port,__u16 size)137 int gb_audio_apbridgea_set_rx_data_size(struct gb_connection *connection,
138 __u16 i2s_port, __u16 size)
139 {
140 struct audio_apbridgea_set_rx_data_size_request req;
141
142 req.hdr.type = AUDIO_APBRIDGEA_TYPE_SET_RX_DATA_SIZE;
143 req.hdr.i2s_port = cpu_to_le16(i2s_port);
144 req.size = cpu_to_le16(size);
145
146 return gb_hd_output(connection->hd, &req, sizeof(req),
147 GB_APB_REQUEST_AUDIO_CONTROL, true);
148 }
149 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_rx_data_size);
150
gb_audio_apbridgea_prepare_rx(struct gb_connection * connection,__u16 i2s_port)151 int gb_audio_apbridgea_prepare_rx(struct gb_connection *connection,
152 __u16 i2s_port)
153 {
154 struct audio_apbridgea_prepare_rx_request req;
155
156 req.hdr.type = AUDIO_APBRIDGEA_TYPE_PREPARE_RX;
157 req.hdr.i2s_port = cpu_to_le16(i2s_port);
158
159 return gb_hd_output(connection->hd, &req, sizeof(req),
160 GB_APB_REQUEST_AUDIO_CONTROL, true);
161 }
162 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_prepare_rx);
163
gb_audio_apbridgea_start_rx(struct gb_connection * connection,__u16 i2s_port)164 int gb_audio_apbridgea_start_rx(struct gb_connection *connection,
165 __u16 i2s_port)
166 {
167 struct audio_apbridgea_start_rx_request req;
168
169 req.hdr.type = AUDIO_APBRIDGEA_TYPE_START_RX;
170 req.hdr.i2s_port = cpu_to_le16(i2s_port);
171
172 return gb_hd_output(connection->hd, &req, sizeof(req),
173 GB_APB_REQUEST_AUDIO_CONTROL, true);
174 }
175 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_start_rx);
176
gb_audio_apbridgea_stop_rx(struct gb_connection * connection,__u16 i2s_port)177 int gb_audio_apbridgea_stop_rx(struct gb_connection *connection, __u16 i2s_port)
178 {
179 struct audio_apbridgea_stop_rx_request req;
180
181 req.hdr.type = AUDIO_APBRIDGEA_TYPE_STOP_RX;
182 req.hdr.i2s_port = cpu_to_le16(i2s_port);
183
184 return gb_hd_output(connection->hd, &req, sizeof(req),
185 GB_APB_REQUEST_AUDIO_CONTROL, true);
186 }
187 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_stop_rx);
188
gb_audio_apbridgea_shutdown_rx(struct gb_connection * connection,__u16 i2s_port)189 int gb_audio_apbridgea_shutdown_rx(struct gb_connection *connection,
190 __u16 i2s_port)
191 {
192 struct audio_apbridgea_shutdown_rx_request req;
193
194 req.hdr.type = AUDIO_APBRIDGEA_TYPE_SHUTDOWN_RX;
195 req.hdr.i2s_port = cpu_to_le16(i2s_port);
196
197 return gb_hd_output(connection->hd, &req, sizeof(req),
198 GB_APB_REQUEST_AUDIO_CONTROL, true);
199 }
200 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_shutdown_rx);
201
202 MODULE_LICENSE("GPL v2");
203 MODULE_ALIAS("greybus:audio-apbridgea");
204 MODULE_DESCRIPTION("Greybus Special APBridgeA Audio Protocol library");
205 MODULE_AUTHOR("Mark Greer <mgreer@animalcreek.com>");
206