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>"); 228