1
2
3
4
5
6
7
8#include "greybus.h"
9#include "greybus_protocols.h"
10#include "operation.h"
11#include "audio_codec.h"
12
13
14int gb_audio_gb_get_topology(struct gb_connection *connection,
15 struct gb_audio_topology **topology)
16{
17 struct gb_audio_get_topology_size_response size_resp;
18 struct gb_audio_topology *topo;
19 u16 size;
20 int ret;
21
22 ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_TOPOLOGY_SIZE,
23 NULL, 0, &size_resp, sizeof(size_resp));
24 if (ret)
25 return ret;
26
27 size = le16_to_cpu(size_resp.size);
28 if (size < sizeof(*topo))
29 return -ENODATA;
30
31 topo = kzalloc(size, GFP_KERNEL);
32 if (!topo)
33 return -ENOMEM;
34
35 ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_TOPOLOGY, NULL, 0,
36 topo, size);
37 if (ret) {
38 kfree(topo);
39 return ret;
40 }
41
42 *topology = topo;
43
44 return 0;
45}
46EXPORT_SYMBOL_GPL(gb_audio_gb_get_topology);
47
48int gb_audio_gb_get_control(struct gb_connection *connection,
49 u8 control_id, u8 index,
50 struct gb_audio_ctl_elem_value *value)
51{
52 struct gb_audio_get_control_request req;
53 struct gb_audio_get_control_response resp;
54 int ret;
55
56 req.control_id = control_id;
57 req.index = index;
58
59 ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_CONTROL,
60 &req, sizeof(req), &resp, sizeof(resp));
61 if (ret)
62 return ret;
63
64 memcpy(value, &resp.value, sizeof(*value));
65
66 return 0;
67}
68EXPORT_SYMBOL_GPL(gb_audio_gb_get_control);
69
70int gb_audio_gb_set_control(struct gb_connection *connection,
71 u8 control_id, u8 index,
72 struct gb_audio_ctl_elem_value *value)
73{
74 struct gb_audio_set_control_request req;
75
76 req.control_id = control_id;
77 req.index = index;
78 memcpy(&req.value, value, sizeof(req.value));
79
80 return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_CONTROL,
81 &req, sizeof(req), NULL, 0);
82}
83EXPORT_SYMBOL_GPL(gb_audio_gb_set_control);
84
85int gb_audio_gb_enable_widget(struct gb_connection *connection,
86 u8 widget_id)
87{
88 struct gb_audio_enable_widget_request req;
89
90 req.widget_id = widget_id;
91
92 return gb_operation_sync(connection, GB_AUDIO_TYPE_ENABLE_WIDGET,
93 &req, sizeof(req), NULL, 0);
94}
95EXPORT_SYMBOL_GPL(gb_audio_gb_enable_widget);
96
97int gb_audio_gb_disable_widget(struct gb_connection *connection,
98 u8 widget_id)
99{
100 struct gb_audio_disable_widget_request req;
101
102 req.widget_id = widget_id;
103
104 return gb_operation_sync(connection, GB_AUDIO_TYPE_DISABLE_WIDGET,
105 &req, sizeof(req), NULL, 0);
106}
107EXPORT_SYMBOL_GPL(gb_audio_gb_disable_widget);
108
109int gb_audio_gb_get_pcm(struct gb_connection *connection, u16 data_cport,
110 u32 *format, u32 *rate, u8 *channels,
111 u8 *sig_bits)
112{
113 struct gb_audio_get_pcm_request req;
114 struct gb_audio_get_pcm_response resp;
115 int ret;
116
117 req.data_cport = cpu_to_le16(data_cport);
118
119 ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_PCM,
120 &req, sizeof(req), &resp, sizeof(resp));
121 if (ret)
122 return ret;
123
124 *format = le32_to_cpu(resp.format);
125 *rate = le32_to_cpu(resp.rate);
126 *channels = resp.channels;
127 *sig_bits = resp.sig_bits;
128
129 return 0;
130}
131EXPORT_SYMBOL_GPL(gb_audio_gb_get_pcm);
132
133int gb_audio_gb_set_pcm(struct gb_connection *connection, u16 data_cport,
134 u32 format, u32 rate, u8 channels,
135 u8 sig_bits)
136{
137 struct gb_audio_set_pcm_request req;
138
139 req.data_cport = cpu_to_le16(data_cport);
140 req.format = cpu_to_le32(format);
141 req.rate = cpu_to_le32(rate);
142 req.channels = channels;
143 req.sig_bits = sig_bits;
144
145 return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_PCM,
146 &req, sizeof(req), NULL, 0);
147}
148EXPORT_SYMBOL_GPL(gb_audio_gb_set_pcm);
149
150int gb_audio_gb_set_tx_data_size(struct gb_connection *connection,
151 u16 data_cport, u16 size)
152{
153 struct gb_audio_set_tx_data_size_request req;
154
155 req.data_cport = cpu_to_le16(data_cport);
156 req.size = cpu_to_le16(size);
157
158 return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_TX_DATA_SIZE,
159 &req, sizeof(req), NULL, 0);
160}
161EXPORT_SYMBOL_GPL(gb_audio_gb_set_tx_data_size);
162
163int gb_audio_gb_activate_tx(struct gb_connection *connection,
164 u16 data_cport)
165{
166 struct gb_audio_activate_tx_request req;
167
168 req.data_cport = cpu_to_le16(data_cport);
169
170 return gb_operation_sync(connection, GB_AUDIO_TYPE_ACTIVATE_TX,
171 &req, sizeof(req), NULL, 0);
172}
173EXPORT_SYMBOL_GPL(gb_audio_gb_activate_tx);
174
175int gb_audio_gb_deactivate_tx(struct gb_connection *connection,
176 u16 data_cport)
177{
178 struct gb_audio_deactivate_tx_request req;
179
180 req.data_cport = cpu_to_le16(data_cport);
181
182 return gb_operation_sync(connection, GB_AUDIO_TYPE_DEACTIVATE_TX,
183 &req, sizeof(req), NULL, 0);
184}
185EXPORT_SYMBOL_GPL(gb_audio_gb_deactivate_tx);
186
187int gb_audio_gb_set_rx_data_size(struct gb_connection *connection,
188 u16 data_cport, u16 size)
189{
190 struct gb_audio_set_rx_data_size_request req;
191
192 req.data_cport = cpu_to_le16(data_cport);
193 req.size = cpu_to_le16(size);
194
195 return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_RX_DATA_SIZE,
196 &req, sizeof(req), NULL, 0);
197}
198EXPORT_SYMBOL_GPL(gb_audio_gb_set_rx_data_size);
199
200int gb_audio_gb_activate_rx(struct gb_connection *connection,
201 u16 data_cport)
202{
203 struct gb_audio_activate_rx_request req;
204
205 req.data_cport = cpu_to_le16(data_cport);
206
207 return gb_operation_sync(connection, GB_AUDIO_TYPE_ACTIVATE_RX,
208 &req, sizeof(req), NULL, 0);
209}
210EXPORT_SYMBOL_GPL(gb_audio_gb_activate_rx);
211
212int gb_audio_gb_deactivate_rx(struct gb_connection *connection,
213 u16 data_cport)
214{
215 struct gb_audio_deactivate_rx_request req;
216
217 req.data_cport = cpu_to_le16(data_cport);
218
219 return gb_operation_sync(connection, GB_AUDIO_TYPE_DEACTIVATE_RX,
220 &req, sizeof(req), NULL, 0);
221}
222EXPORT_SYMBOL_GPL(gb_audio_gb_deactivate_rx);
223
224MODULE_LICENSE("GPL v2");
225MODULE_ALIAS("greybus:audio-gb");
226MODULE_DESCRIPTION("Greybus Audio Device Class Protocol library");
227MODULE_AUTHOR("Mark Greer <mgreer@animalcreek.com>");
228