GNU Linux-libre 4.19.245-gnu1
[releases.git] / drivers / staging / greybus / audio_gb.c
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 "greybus.h"
9 #include "greybus_protocols.h"
10 #include "operation.h"
11 #include "audio_codec.h"
12
13 /* TODO: Split into separate calls */
14 int 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 }
46 EXPORT_SYMBOL_GPL(gb_audio_gb_get_topology);
47
48 int 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 }
68 EXPORT_SYMBOL_GPL(gb_audio_gb_get_control);
69
70 int 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 }
83 EXPORT_SYMBOL_GPL(gb_audio_gb_set_control);
84
85 int 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 }
95 EXPORT_SYMBOL_GPL(gb_audio_gb_enable_widget);
96
97 int 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 }
107 EXPORT_SYMBOL_GPL(gb_audio_gb_disable_widget);
108
109 int 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 }
131 EXPORT_SYMBOL_GPL(gb_audio_gb_get_pcm);
132
133 int 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 }
148 EXPORT_SYMBOL_GPL(gb_audio_gb_set_pcm);
149
150 int 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 }
161 EXPORT_SYMBOL_GPL(gb_audio_gb_set_tx_data_size);
162
163 int 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 }
173 EXPORT_SYMBOL_GPL(gb_audio_gb_activate_tx);
174
175 int 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 }
185 EXPORT_SYMBOL_GPL(gb_audio_gb_deactivate_tx);
186
187 int 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 }
198 EXPORT_SYMBOL_GPL(gb_audio_gb_set_rx_data_size);
199
200 int 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 }
210 EXPORT_SYMBOL_GPL(gb_audio_gb_activate_rx);
211
212 int 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 }
222 EXPORT_SYMBOL_GPL(gb_audio_gb_deactivate_rx);
223
224 MODULE_LICENSE("GPL v2");
225 MODULE_ALIAS("greybus:audio-gb");
226 MODULE_DESCRIPTION("Greybus Audio Device Class Protocol library");
227 MODULE_AUTHOR("Mark Greer <mgreer@animalcreek.com>");