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