audio_gb.c (5819B)
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 */ 12int 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} 44EXPORT_SYMBOL_GPL(gb_audio_gb_get_topology); 45 46int 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} 66EXPORT_SYMBOL_GPL(gb_audio_gb_get_control); 67 68int 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} 81EXPORT_SYMBOL_GPL(gb_audio_gb_set_control); 82 83int 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} 93EXPORT_SYMBOL_GPL(gb_audio_gb_enable_widget); 94 95int 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} 105EXPORT_SYMBOL_GPL(gb_audio_gb_disable_widget); 106 107int 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} 129EXPORT_SYMBOL_GPL(gb_audio_gb_get_pcm); 130 131int 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} 146EXPORT_SYMBOL_GPL(gb_audio_gb_set_pcm); 147 148int 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} 159EXPORT_SYMBOL_GPL(gb_audio_gb_set_tx_data_size); 160 161int 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} 171EXPORT_SYMBOL_GPL(gb_audio_gb_activate_tx); 172 173int 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} 183EXPORT_SYMBOL_GPL(gb_audio_gb_deactivate_tx); 184 185int 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} 196EXPORT_SYMBOL_GPL(gb_audio_gb_set_rx_data_size); 197 198int 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} 208EXPORT_SYMBOL_GPL(gb_audio_gb_activate_rx); 209 210int 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} 220EXPORT_SYMBOL_GPL(gb_audio_gb_deactivate_rx); 221 222MODULE_LICENSE("GPL v2"); 223MODULE_ALIAS("greybus:audio-gb"); 224MODULE_DESCRIPTION("Greybus Audio Device Class Protocol library"); 225MODULE_AUTHOR("Mark Greer <mgreer@animalcreek.com>");