linux/drivers/staging/greybus/audio_gb.c
<<
>>
Prefs
   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>");
 226