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