1 /* 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" 12 #include "audio_codec.h" 13 14 /* TODO: Split into separate calls */ 15 int 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; 20 u16 size; 21 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 } 47 EXPORT_SYMBOL_GPL(gb_audio_gb_get_topology); 48 49 int gb_audio_gb_get_control(struct gb_connection *connection, 50 u8 control_id, u8 index, 51 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 } 69 EXPORT_SYMBOL_GPL(gb_audio_gb_get_control); 70 71 int gb_audio_gb_set_control(struct gb_connection *connection, 72 u8 control_id, u8 index, 73 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 } 84 EXPORT_SYMBOL_GPL(gb_audio_gb_set_control); 85 86 int gb_audio_gb_enable_widget(struct gb_connection *connection, 87 u8 widget_id) 88 { 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 } 96 EXPORT_SYMBOL_GPL(gb_audio_gb_enable_widget); 97 98 int gb_audio_gb_disable_widget(struct gb_connection *connection, 99 u8 widget_id) 100 { 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 } 108 EXPORT_SYMBOL_GPL(gb_audio_gb_disable_widget); 109 110 int gb_audio_gb_get_pcm(struct gb_connection *connection, u16 data_cport, 111 u32 *format, u32 *rate, u8 *channels, 112 u8 *sig_bits) 113 { 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 } 132 EXPORT_SYMBOL_GPL(gb_audio_gb_get_pcm); 133 134 int gb_audio_gb_set_pcm(struct gb_connection *connection, u16 data_cport, 135 u32 format, u32 rate, u8 channels, 136 u8 sig_bits) 137 { 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 } 149 EXPORT_SYMBOL_GPL(gb_audio_gb_set_pcm); 150 151 int gb_audio_gb_set_tx_data_size(struct gb_connection *connection, 152 u16 data_cport, u16 size) 153 { 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 } 162 EXPORT_SYMBOL_GPL(gb_audio_gb_set_tx_data_size); 163 164 int gb_audio_gb_activate_tx(struct gb_connection *connection, 165 u16 data_cport) 166 { 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 } 174 EXPORT_SYMBOL_GPL(gb_audio_gb_activate_tx); 175 176 int gb_audio_gb_deactivate_tx(struct gb_connection *connection, 177 u16 data_cport) 178 { 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 } 186 EXPORT_SYMBOL_GPL(gb_audio_gb_deactivate_tx); 187 188 int gb_audio_gb_set_rx_data_size(struct gb_connection *connection, 189 u16 data_cport, u16 size) 190 { 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 } 199 EXPORT_SYMBOL_GPL(gb_audio_gb_set_rx_data_size); 200 201 int gb_audio_gb_activate_rx(struct gb_connection *connection, 202 u16 data_cport) 203 { 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 } 211 EXPORT_SYMBOL_GPL(gb_audio_gb_activate_rx); 212 213 int gb_audio_gb_deactivate_rx(struct gb_connection *connection, 214 u16 data_cport) 215 { 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 } 223 EXPORT_SYMBOL_GPL(gb_audio_gb_deactivate_rx); 224 225 MODULE_LICENSE("GPL v2"); 226 MODULE_ALIAS("greybus:audio-gb"); 227 MODULE_DESCRIPTION("Greybus Audio Device Class Protocol library"); 228 MODULE_AUTHOR("Mark Greer <mgreer@animalcreek.com>"); 229