mirror of
https://github.com/torvalds/linux.git
synced 2026-09-26 01:52:03 +02:00
greybus: audio: Add Greybus Audio Device Class Protocol helper routines
Add helper routines to make communicating with audio modules easier. Signed-off-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
parent
ba4144afde
commit
184992e305
|
|
@ -30,6 +30,7 @@ gb-hid-y := hid.o
|
||||||
gb-es2-y := es2.o
|
gb-es2-y := es2.o
|
||||||
gb-arche-y := arche-platform.o arche-apb-ctrl.o
|
gb-arche-y := arche-platform.o arche-apb-ctrl.o
|
||||||
gb-audio-codec-y := audio_codec.o
|
gb-audio-codec-y := audio_codec.o
|
||||||
|
gb-audio-gb-y := audio_gb.o
|
||||||
gb-camera-y := camera.o
|
gb-camera-y := camera.o
|
||||||
|
|
||||||
obj-m += greybus.o
|
obj-m += greybus.o
|
||||||
|
|
@ -44,6 +45,7 @@ obj-m += gb-es2.o
|
||||||
obj-m += gb-arche.o
|
obj-m += gb-arche.o
|
||||||
obj-m += gb-audio-codec.o
|
obj-m += gb-audio-codec.o
|
||||||
obj-m += gb-camera.o
|
obj-m += gb-camera.o
|
||||||
|
obj-m += gb-audio-gb.o
|
||||||
|
|
||||||
KERNELVER ?= $(shell uname -r)
|
KERNELVER ?= $(shell uname -r)
|
||||||
KERNELDIR ?= /lib/modules/$(KERNELVER)/build
|
KERNELDIR ?= /lib/modules/$(KERNELVER)/build
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,9 @@
|
||||||
|
|
||||||
#include <sound/soc.h>
|
#include <sound/soc.h>
|
||||||
|
|
||||||
|
#include "greybus.h"
|
||||||
|
#include "greybus_protocols.h"
|
||||||
|
|
||||||
#define NAME_SIZE 32
|
#define NAME_SIZE 32
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
@ -82,5 +85,42 @@ struct gbaudio_codec_info {
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern int gb_audio_gb_get_topology(struct gb_connection *connection,
|
||||||
|
struct gb_audio_topology **topology);
|
||||||
|
extern int gb_audio_gb_get_control(struct gb_connection *connection,
|
||||||
|
uint8_t control_id, uint8_t index,
|
||||||
|
struct gb_audio_ctl_elem_value *value);
|
||||||
|
extern int gb_audio_gb_set_control(struct gb_connection *connection,
|
||||||
|
uint8_t control_id, uint8_t index,
|
||||||
|
struct gb_audio_ctl_elem_value *value);
|
||||||
|
extern int gb_audio_gb_enable_widget(struct gb_connection *connection,
|
||||||
|
uint8_t widget_id);
|
||||||
|
extern int gb_audio_gb_disable_widget(struct gb_connection *connection,
|
||||||
|
uint8_t widget_id);
|
||||||
|
extern int gb_audio_gb_get_pcm(struct gb_connection *connection,
|
||||||
|
uint16_t data_cport, uint32_t *format,
|
||||||
|
uint32_t *rate, uint8_t *channels,
|
||||||
|
uint8_t *sig_bits);
|
||||||
|
extern int gb_audio_gb_set_pcm(struct gb_connection *connection,
|
||||||
|
uint16_t data_cport, uint32_t format,
|
||||||
|
uint32_t rate, uint8_t channels,
|
||||||
|
uint8_t sig_bits);
|
||||||
|
extern int gb_audio_gb_set_tx_data_size(struct gb_connection *connection,
|
||||||
|
uint16_t data_cport, uint16_t size);
|
||||||
|
extern int gb_audio_gb_get_tx_delay(struct gb_connection *connection,
|
||||||
|
uint16_t data_cport, uint32_t *delay);
|
||||||
|
extern int gb_audio_gb_activate_tx(struct gb_connection *connection,
|
||||||
|
uint16_t data_cport);
|
||||||
|
extern int gb_audio_gb_deactivate_tx(struct gb_connection *connection,
|
||||||
|
uint16_t data_cport);
|
||||||
|
extern int gb_audio_gb_set_rx_data_size(struct gb_connection *connection,
|
||||||
|
uint16_t data_cport, uint16_t size);
|
||||||
|
extern int gb_audio_gb_get_rx_delay(struct gb_connection *connection,
|
||||||
|
uint16_t data_cport, uint32_t *delay);
|
||||||
|
extern int gb_audio_gb_activate_rx(struct gb_connection *connection,
|
||||||
|
uint16_t data_cport);
|
||||||
|
extern int gb_audio_gb_deactivate_rx(struct gb_connection *connection,
|
||||||
|
uint16_t data_cport);
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
#endif /* __LINUX_GBAUDIO_H */
|
#endif /* __LINUX_GBAUDIO_H */
|
||||||
|
|
|
||||||
267
drivers/staging/greybus/audio_gb.c
Normal file
267
drivers/staging/greybus/audio_gb.c
Normal file
|
|
@ -0,0 +1,267 @@
|
||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
uint16_t 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,
|
||||||
|
uint8_t control_id, uint8_t 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,
|
||||||
|
uint8_t control_id, uint8_t 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,
|
||||||
|
uint8_t 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,
|
||||||
|
uint8_t 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, uint16_t data_cport,
|
||||||
|
uint32_t *format, uint32_t *rate, uint8_t *channels,
|
||||||
|
uint8_t *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, uint16_t data_cport,
|
||||||
|
uint32_t format, uint32_t rate, uint8_t channels,
|
||||||
|
uint8_t 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,
|
||||||
|
uint16_t data_cport, uint16_t 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_get_tx_delay(struct gb_connection *connection,
|
||||||
|
uint16_t data_cport, uint32_t *delay)
|
||||||
|
{
|
||||||
|
struct gb_audio_get_tx_delay_request req;
|
||||||
|
struct gb_audio_get_tx_delay_response resp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
req.data_cport = cpu_to_le16(data_cport);
|
||||||
|
|
||||||
|
ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_TX_DELAY,
|
||||||
|
&req, sizeof(req), &resp, sizeof(resp));
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
*delay = le32_to_cpu(resp.delay);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(gb_audio_gb_get_tx_delay);
|
||||||
|
|
||||||
|
int gb_audio_gb_activate_tx(struct gb_connection *connection,
|
||||||
|
uint16_t 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,
|
||||||
|
uint16_t 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,
|
||||||
|
uint16_t data_cport, uint16_t 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_get_rx_delay(struct gb_connection *connection,
|
||||||
|
uint16_t data_cport, uint32_t *delay)
|
||||||
|
{
|
||||||
|
struct gb_audio_get_rx_delay_request req;
|
||||||
|
struct gb_audio_get_rx_delay_response resp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
req.data_cport = cpu_to_le16(data_cport);
|
||||||
|
|
||||||
|
ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_RX_DELAY,
|
||||||
|
&req, sizeof(req), &resp, sizeof(resp));
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
*delay = le32_to_cpu(resp.delay);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(gb_audio_gb_get_rx_delay);
|
||||||
|
|
||||||
|
int gb_audio_gb_activate_rx(struct gb_connection *connection,
|
||||||
|
uint16_t 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,
|
||||||
|
uint16_t 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>");
|
||||||
Loading…
Reference in New Issue
Block a user