diff options
Diffstat (limited to 'drivers/staging/greybus/audio_gb.c')
-rw-r--r-- | drivers/staging/greybus/audio_gb.c | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/drivers/staging/greybus/audio_gb.c b/drivers/staging/greybus/audio_gb.c new file mode 100644 index 0000000..42f287d --- /dev/null +++ b/drivers/staging/greybus/audio_gb.c @@ -0,0 +1,228 @@ +/* + * Greybus Audio Device Class Protocol helpers + * + * Copyright 2015-2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" +#include "greybus_protocols.h" +#include "operation.h" +#include "audio_codec.h" + +/* TODO: Split into separate calls */ +int gb_audio_gb_get_topology(struct gb_connection *connection, + struct gb_audio_topology **topology) +{ + struct gb_audio_get_topology_size_response size_resp; + struct gb_audio_topology *topo; + u16 size; + int ret; + + ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_TOPOLOGY_SIZE, + NULL, 0, &size_resp, sizeof(size_resp)); + if (ret) + return ret; + + size = le16_to_cpu(size_resp.size); + if (size < sizeof(*topo)) + return -ENODATA; + + topo = kzalloc(size, GFP_KERNEL); + if (!topo) + return -ENOMEM; + + ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_TOPOLOGY, NULL, 0, + topo, size); + if (ret) { + kfree(topo); + return ret; + } + + *topology = topo; + + return 0; +} +EXPORT_SYMBOL_GPL(gb_audio_gb_get_topology); + +int gb_audio_gb_get_control(struct gb_connection *connection, + u8 control_id, u8 index, + struct gb_audio_ctl_elem_value *value) +{ + struct gb_audio_get_control_request req; + struct gb_audio_get_control_response resp; + int ret; + + req.control_id = control_id; + req.index = index; + + ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_CONTROL, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret) + return ret; + + memcpy(value, &resp.value, sizeof(*value)); + + return 0; +} +EXPORT_SYMBOL_GPL(gb_audio_gb_get_control); + +int gb_audio_gb_set_control(struct gb_connection *connection, + u8 control_id, u8 index, + struct gb_audio_ctl_elem_value *value) +{ + struct gb_audio_set_control_request req; + + req.control_id = control_id; + req.index = index; + memcpy(&req.value, value, sizeof(req.value)); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_CONTROL, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_set_control); + +int gb_audio_gb_enable_widget(struct gb_connection *connection, + u8 widget_id) +{ + struct gb_audio_enable_widget_request req; + + req.widget_id = widget_id; + + return gb_operation_sync(connection, GB_AUDIO_TYPE_ENABLE_WIDGET, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_enable_widget); + +int gb_audio_gb_disable_widget(struct gb_connection *connection, + u8 widget_id) +{ + struct gb_audio_disable_widget_request req; + + req.widget_id = widget_id; + + return gb_operation_sync(connection, GB_AUDIO_TYPE_DISABLE_WIDGET, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_disable_widget); + +int gb_audio_gb_get_pcm(struct gb_connection *connection, u16 data_cport, + uint32_t *format, uint32_t *rate, u8 *channels, + u8 *sig_bits) +{ + struct gb_audio_get_pcm_request req; + struct gb_audio_get_pcm_response resp; + int ret; + + req.data_cport = cpu_to_le16(data_cport); + + ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_PCM, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret) + return ret; + + *format = le32_to_cpu(resp.format); + *rate = le32_to_cpu(resp.rate); + *channels = resp.channels; + *sig_bits = resp.sig_bits; + + return 0; +} +EXPORT_SYMBOL_GPL(gb_audio_gb_get_pcm); + +int gb_audio_gb_set_pcm(struct gb_connection *connection, u16 data_cport, + uint32_t format, uint32_t rate, u8 channels, + u8 sig_bits) +{ + struct gb_audio_set_pcm_request req; + + req.data_cport = cpu_to_le16(data_cport); + req.format = cpu_to_le32(format); + req.rate = cpu_to_le32(rate); + req.channels = channels; + req.sig_bits = sig_bits; + + return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_PCM, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_set_pcm); + +int gb_audio_gb_set_tx_data_size(struct gb_connection *connection, + u16 data_cport, u16 size) +{ + struct gb_audio_set_tx_data_size_request req; + + req.data_cport = cpu_to_le16(data_cport); + req.size = cpu_to_le16(size); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_TX_DATA_SIZE, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_set_tx_data_size); + +int gb_audio_gb_activate_tx(struct gb_connection *connection, + u16 data_cport) +{ + struct gb_audio_activate_tx_request req; + + req.data_cport = cpu_to_le16(data_cport); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_ACTIVATE_TX, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_activate_tx); + +int gb_audio_gb_deactivate_tx(struct gb_connection *connection, + u16 data_cport) +{ + struct gb_audio_deactivate_tx_request req; + + req.data_cport = cpu_to_le16(data_cport); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_DEACTIVATE_TX, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_deactivate_tx); + +int gb_audio_gb_set_rx_data_size(struct gb_connection *connection, + u16 data_cport, u16 size) +{ + struct gb_audio_set_rx_data_size_request req; + + req.data_cport = cpu_to_le16(data_cport); + req.size = cpu_to_le16(size); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_RX_DATA_SIZE, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_set_rx_data_size); + +int gb_audio_gb_activate_rx(struct gb_connection *connection, + u16 data_cport) +{ + struct gb_audio_activate_rx_request req; + + req.data_cport = cpu_to_le16(data_cport); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_ACTIVATE_RX, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_activate_rx); + +int gb_audio_gb_deactivate_rx(struct gb_connection *connection, + u16 data_cport) +{ + struct gb_audio_deactivate_rx_request req; + + req.data_cport = cpu_to_le16(data_cport); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_DEACTIVATE_RX, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_deactivate_rx); + +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("greybus:audio-gb"); +MODULE_DESCRIPTION("Greybus Audio Device Class Protocol library"); +MODULE_AUTHOR("Mark Greer <mgreer@animalcreek.com>"); |