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 | |
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(hd: connection->hd, req: &req, size: sizeof(req), |
25 | GB_APB_REQUEST_AUDIO_CONTROL, in_irq: true); |
26 | } |
27 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_config); |
28 | |
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(bundle: connection->bundle); |
42 | if (ret) |
43 | return ret; |
44 | |
45 | return gb_hd_output(hd: connection->hd, req: &req, size: sizeof(req), |
46 | GB_APB_REQUEST_AUDIO_CONTROL, in_irq: true); |
47 | } |
48 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_register_cport); |
49 | |
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(hd: connection->hd, req: &req, size: sizeof(req), |
63 | GB_APB_REQUEST_AUDIO_CONTROL, in_irq: true); |
64 | |
65 | gb_pm_runtime_put_autosuspend(bundle: connection->bundle); |
66 | |
67 | return ret; |
68 | } |
69 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_unregister_cport); |
70 | |
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(hd: connection->hd, req: &req, size: sizeof(req), |
81 | GB_APB_REQUEST_AUDIO_CONTROL, in_irq: true); |
82 | } |
83 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_tx_data_size); |
84 | |
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(hd: connection->hd, req: &req, size: sizeof(req), |
94 | GB_APB_REQUEST_AUDIO_CONTROL, in_irq: true); |
95 | } |
96 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_prepare_tx); |
97 | |
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(hd: connection->hd, req: &req, size: sizeof(req), |
108 | GB_APB_REQUEST_AUDIO_CONTROL, in_irq: true); |
109 | } |
110 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_start_tx); |
111 | |
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(hd: connection->hd, req: &req, size: sizeof(req), |
120 | GB_APB_REQUEST_AUDIO_CONTROL, in_irq: true); |
121 | } |
122 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_stop_tx); |
123 | |
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(hd: connection->hd, req: &req, size: sizeof(req), |
133 | GB_APB_REQUEST_AUDIO_CONTROL, in_irq: true); |
134 | } |
135 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_shutdown_tx); |
136 | |
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(hd: connection->hd, req: &req, size: sizeof(req), |
147 | GB_APB_REQUEST_AUDIO_CONTROL, in_irq: true); |
148 | } |
149 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_rx_data_size); |
150 | |
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(hd: connection->hd, req: &req, size: sizeof(req), |
160 | GB_APB_REQUEST_AUDIO_CONTROL, in_irq: true); |
161 | } |
162 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_prepare_rx); |
163 | |
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(hd: connection->hd, req: &req, size: sizeof(req), |
173 | GB_APB_REQUEST_AUDIO_CONTROL, in_irq: true); |
174 | } |
175 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_start_rx); |
176 | |
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(hd: connection->hd, req: &req, size: sizeof(req), |
185 | GB_APB_REQUEST_AUDIO_CONTROL, in_irq: true); |
186 | } |
187 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_stop_rx); |
188 | |
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(hd: connection->hd, req: &req, size: sizeof(req), |
198 | GB_APB_REQUEST_AUDIO_CONTROL, in_irq: 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 | |