blob: 42f287dd7b84c384004e8bee95bfeeb8cf0b38eb [file] [log] [blame]
Mark Greer184992e2016-01-13 14:07:46 -07001/*
2 * Greybus Audio Device Class Protocol helpers
3 *
4 * Copyright 2015-2016 Google Inc.
5 *
6 * Released under the GPLv2 only.
7 */
8
9#include "greybus.h"
10#include "greybus_protocols.h"
11#include "operation.h"
Viresh Kumar10454512016-01-28 15:50:47 +053012#include "audio_codec.h"
Mark Greer184992e2016-01-13 14:07:46 -070013
14/* TODO: Split into separate calls */
15int gb_audio_gb_get_topology(struct gb_connection *connection,
16 struct gb_audio_topology **topology)
17{
18 struct gb_audio_get_topology_size_response size_resp;
19 struct gb_audio_topology *topo;
Chaehyun Lim79cb2b22016-09-20 09:47:30 +090020 u16 size;
Mark Greer184992e2016-01-13 14:07:46 -070021 int ret;
22
23 ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_TOPOLOGY_SIZE,
24 NULL, 0, &size_resp, sizeof(size_resp));
25 if (ret)
26 return ret;
27
28 size = le16_to_cpu(size_resp.size);
29 if (size < sizeof(*topo))
30 return -ENODATA;
31
32 topo = kzalloc(size, GFP_KERNEL);
33 if (!topo)
34 return -ENOMEM;
35
36 ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_TOPOLOGY, NULL, 0,
37 topo, size);
38 if (ret) {
39 kfree(topo);
40 return ret;
41 }
42
43 *topology = topo;
44
45 return 0;
46}
47EXPORT_SYMBOL_GPL(gb_audio_gb_get_topology);
48
49int gb_audio_gb_get_control(struct gb_connection *connection,
Chaehyun Lim31959392016-09-20 09:47:29 +090050 u8 control_id, u8 index,
Mark Greer184992e2016-01-13 14:07:46 -070051 struct gb_audio_ctl_elem_value *value)
52{
53 struct gb_audio_get_control_request req;
54 struct gb_audio_get_control_response resp;
55 int ret;
56
57 req.control_id = control_id;
58 req.index = index;
59
60 ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_CONTROL,
61 &req, sizeof(req), &resp, sizeof(resp));
62 if (ret)
63 return ret;
64
65 memcpy(value, &resp.value, sizeof(*value));
66
67 return 0;
68}
69EXPORT_SYMBOL_GPL(gb_audio_gb_get_control);
70
71int gb_audio_gb_set_control(struct gb_connection *connection,
Chaehyun Lim31959392016-09-20 09:47:29 +090072 u8 control_id, u8 index,
Mark Greer184992e2016-01-13 14:07:46 -070073 struct gb_audio_ctl_elem_value *value)
74{
75 struct gb_audio_set_control_request req;
76
77 req.control_id = control_id;
78 req.index = index;
79 memcpy(&req.value, value, sizeof(req.value));
80
81 return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_CONTROL,
82 &req, sizeof(req), NULL, 0);
83}
84EXPORT_SYMBOL_GPL(gb_audio_gb_set_control);
85
86int gb_audio_gb_enable_widget(struct gb_connection *connection,
Chaehyun Lim31959392016-09-20 09:47:29 +090087 u8 widget_id)
Mark Greer184992e2016-01-13 14:07:46 -070088{
89 struct gb_audio_enable_widget_request req;
90
91 req.widget_id = widget_id;
92
93 return gb_operation_sync(connection, GB_AUDIO_TYPE_ENABLE_WIDGET,
94 &req, sizeof(req), NULL, 0);
95}
96EXPORT_SYMBOL_GPL(gb_audio_gb_enable_widget);
97
98int gb_audio_gb_disable_widget(struct gb_connection *connection,
Chaehyun Lim31959392016-09-20 09:47:29 +090099 u8 widget_id)
Mark Greer184992e2016-01-13 14:07:46 -0700100{
101 struct gb_audio_disable_widget_request req;
102
103 req.widget_id = widget_id;
104
105 return gb_operation_sync(connection, GB_AUDIO_TYPE_DISABLE_WIDGET,
106 &req, sizeof(req), NULL, 0);
107}
108EXPORT_SYMBOL_GPL(gb_audio_gb_disable_widget);
109
Chaehyun Lim79cb2b22016-09-20 09:47:30 +0900110int gb_audio_gb_get_pcm(struct gb_connection *connection, u16 data_cport,
Chaehyun Lim31959392016-09-20 09:47:29 +0900111 uint32_t *format, uint32_t *rate, u8 *channels,
112 u8 *sig_bits)
Mark Greer184992e2016-01-13 14:07:46 -0700113{
114 struct gb_audio_get_pcm_request req;
115 struct gb_audio_get_pcm_response resp;
116 int ret;
117
118 req.data_cport = cpu_to_le16(data_cport);
119
120 ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_PCM,
121 &req, sizeof(req), &resp, sizeof(resp));
122 if (ret)
123 return ret;
124
125 *format = le32_to_cpu(resp.format);
126 *rate = le32_to_cpu(resp.rate);
127 *channels = resp.channels;
128 *sig_bits = resp.sig_bits;
129
130 return 0;
131}
132EXPORT_SYMBOL_GPL(gb_audio_gb_get_pcm);
133
Chaehyun Lim79cb2b22016-09-20 09:47:30 +0900134int gb_audio_gb_set_pcm(struct gb_connection *connection, u16 data_cport,
Chaehyun Lim31959392016-09-20 09:47:29 +0900135 uint32_t format, uint32_t rate, u8 channels,
136 u8 sig_bits)
Mark Greer184992e2016-01-13 14:07:46 -0700137{
138 struct gb_audio_set_pcm_request req;
139
140 req.data_cport = cpu_to_le16(data_cport);
141 req.format = cpu_to_le32(format);
142 req.rate = cpu_to_le32(rate);
143 req.channels = channels;
144 req.sig_bits = sig_bits;
145
146 return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_PCM,
147 &req, sizeof(req), NULL, 0);
148}
149EXPORT_SYMBOL_GPL(gb_audio_gb_set_pcm);
150
151int gb_audio_gb_set_tx_data_size(struct gb_connection *connection,
Chaehyun Lim79cb2b22016-09-20 09:47:30 +0900152 u16 data_cport, u16 size)
Mark Greer184992e2016-01-13 14:07:46 -0700153{
154 struct gb_audio_set_tx_data_size_request req;
155
156 req.data_cport = cpu_to_le16(data_cport);
157 req.size = cpu_to_le16(size);
158
159 return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_TX_DATA_SIZE,
160 &req, sizeof(req), NULL, 0);
161}
162EXPORT_SYMBOL_GPL(gb_audio_gb_set_tx_data_size);
163
Mark Greer184992e2016-01-13 14:07:46 -0700164int gb_audio_gb_activate_tx(struct gb_connection *connection,
Chaehyun Lim79cb2b22016-09-20 09:47:30 +0900165 u16 data_cport)
Mark Greer184992e2016-01-13 14:07:46 -0700166{
167 struct gb_audio_activate_tx_request req;
168
169 req.data_cport = cpu_to_le16(data_cport);
170
171 return gb_operation_sync(connection, GB_AUDIO_TYPE_ACTIVATE_TX,
172 &req, sizeof(req), NULL, 0);
173}
174EXPORT_SYMBOL_GPL(gb_audio_gb_activate_tx);
175
176int gb_audio_gb_deactivate_tx(struct gb_connection *connection,
Chaehyun Lim79cb2b22016-09-20 09:47:30 +0900177 u16 data_cport)
Mark Greer184992e2016-01-13 14:07:46 -0700178{
179 struct gb_audio_deactivate_tx_request req;
180
181 req.data_cport = cpu_to_le16(data_cport);
182
183 return gb_operation_sync(connection, GB_AUDIO_TYPE_DEACTIVATE_TX,
184 &req, sizeof(req), NULL, 0);
185}
186EXPORT_SYMBOL_GPL(gb_audio_gb_deactivate_tx);
187
188int gb_audio_gb_set_rx_data_size(struct gb_connection *connection,
Chaehyun Lim79cb2b22016-09-20 09:47:30 +0900189 u16 data_cport, u16 size)
Mark Greer184992e2016-01-13 14:07:46 -0700190{
191 struct gb_audio_set_rx_data_size_request req;
192
193 req.data_cport = cpu_to_le16(data_cport);
194 req.size = cpu_to_le16(size);
195
196 return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_RX_DATA_SIZE,
197 &req, sizeof(req), NULL, 0);
198}
199EXPORT_SYMBOL_GPL(gb_audio_gb_set_rx_data_size);
200
Mark Greer184992e2016-01-13 14:07:46 -0700201int gb_audio_gb_activate_rx(struct gb_connection *connection,
Chaehyun Lim79cb2b22016-09-20 09:47:30 +0900202 u16 data_cport)
Mark Greer184992e2016-01-13 14:07:46 -0700203{
204 struct gb_audio_activate_rx_request req;
205
206 req.data_cport = cpu_to_le16(data_cport);
207
208 return gb_operation_sync(connection, GB_AUDIO_TYPE_ACTIVATE_RX,
209 &req, sizeof(req), NULL, 0);
210}
211EXPORT_SYMBOL_GPL(gb_audio_gb_activate_rx);
212
213int gb_audio_gb_deactivate_rx(struct gb_connection *connection,
Chaehyun Lim79cb2b22016-09-20 09:47:30 +0900214 u16 data_cport)
Mark Greer184992e2016-01-13 14:07:46 -0700215{
216 struct gb_audio_deactivate_rx_request req;
217
218 req.data_cport = cpu_to_le16(data_cport);
219
220 return gb_operation_sync(connection, GB_AUDIO_TYPE_DEACTIVATE_RX,
221 &req, sizeof(req), NULL, 0);
222}
223EXPORT_SYMBOL_GPL(gb_audio_gb_deactivate_rx);
224
225MODULE_LICENSE("GPL v2");
226MODULE_ALIAS("greybus:audio-gb");
227MODULE_DESCRIPTION("Greybus Audio Device Class Protocol library");
228MODULE_AUTHOR("Mark Greer <mgreer@animalcreek.com>");