linux/sound/firewire/bebob/bebob_focusrite.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * bebob_focusrite.c - a part of driver for BeBoB based devices
   4 *
   5 * Copyright (c) 2013-2014 Takashi Sakamoto
   6 */
   7
   8#include "./bebob.h"
   9
  10#define ANA_IN  "Analog In"
  11#define DIG_IN  "Digital In"
  12#define ANA_OUT "Analog Out"
  13#define DIG_OUT "Digital Out"
  14#define STM_IN  "Stream In"
  15
  16#define SAFFIRE_ADDRESS_BASE                    0x000100000000ULL
  17
  18#define SAFFIRE_OFFSET_CLOCK_SOURCE             0x00f8
  19#define SAFFIREPRO_OFFSET_CLOCK_SOURCE          0x0174
  20
  21/* whether sync to external device or not */
  22#define SAFFIRE_OFFSET_CLOCK_SYNC_EXT           0x013c
  23#define SAFFIRE_LE_OFFSET_CLOCK_SYNC_EXT        0x0432
  24#define SAFFIREPRO_OFFSET_CLOCK_SYNC_EXT        0x0164
  25
  26#define SAFFIRE_CLOCK_SOURCE_INTERNAL           0
  27#define SAFFIRE_CLOCK_SOURCE_SPDIF              1
  28
  29/* clock sources as returned from register of Saffire Pro 10 and 26 */
  30#define SAFFIREPRO_CLOCK_SOURCE_INTERNAL        0
  31#define SAFFIREPRO_CLOCK_SOURCE_SKIP            1 /* never used on hardware */
  32#define SAFFIREPRO_CLOCK_SOURCE_SPDIF           2
  33#define SAFFIREPRO_CLOCK_SOURCE_ADAT1           3 /* not used on s.pro. 10 */
  34#define SAFFIREPRO_CLOCK_SOURCE_ADAT2           4 /* not used on s.pro. 10 */
  35#define SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK       5
  36#define SAFFIREPRO_CLOCK_SOURCE_COUNT           6
  37
  38/* S/PDIF, ADAT1, ADAT2 is enabled or not. three quadlets */
  39#define SAFFIREPRO_ENABLE_DIG_IFACES            0x01a4
  40
  41/* saffirepro has its own parameter for sampling frequency */
  42#define SAFFIREPRO_RATE_NOREBOOT                0x01cc
  43/* index is the value for this register */
  44static const unsigned int rates[] = {
  45        [0] = 0,
  46        [1] = 44100,
  47        [2] = 48000,
  48        [3] = 88200,
  49        [4] = 96000,
  50        [5] = 176400,
  51        [6] = 192000
  52};
  53
  54/* saffire(no label)/saffire LE has metering */
  55#define SAFFIRE_OFFSET_METER                    0x0100
  56#define SAFFIRE_LE_OFFSET_METER                 0x0168
  57
  58static inline int
  59saffire_read_block(struct snd_bebob *bebob, u64 offset,
  60                   u32 *buf, unsigned int size)
  61{
  62        unsigned int i;
  63        int err;
  64        __be32 *tmp = (__be32 *)buf;
  65
  66        err =  snd_fw_transaction(bebob->unit, TCODE_READ_BLOCK_REQUEST,
  67                                  SAFFIRE_ADDRESS_BASE + offset,
  68                                  tmp, size, 0);
  69        if (err < 0)
  70                goto end;
  71
  72        for (i = 0; i < size / sizeof(u32); i++)
  73                buf[i] = be32_to_cpu(tmp[i]);
  74end:
  75        return err;
  76}
  77
  78static inline int
  79saffire_read_quad(struct snd_bebob *bebob, u64 offset, u32 *value)
  80{
  81        int err;
  82        __be32 tmp;
  83
  84        err = snd_fw_transaction(bebob->unit, TCODE_READ_QUADLET_REQUEST,
  85                                 SAFFIRE_ADDRESS_BASE + offset,
  86                                 &tmp, sizeof(__be32), 0);
  87        if (err < 0)
  88                goto end;
  89
  90        *value = be32_to_cpu(tmp);
  91end:
  92        return err;
  93}
  94
  95static inline int
  96saffire_write_quad(struct snd_bebob *bebob, u64 offset, u32 value)
  97{
  98        __be32 data = cpu_to_be32(value);
  99
 100        return snd_fw_transaction(bebob->unit, TCODE_WRITE_QUADLET_REQUEST,
 101                                  SAFFIRE_ADDRESS_BASE + offset,
 102                                  &data, sizeof(__be32), 0);
 103}
 104
 105static const enum snd_bebob_clock_type saffirepro_10_clk_src_types[] = {
 106        SND_BEBOB_CLOCK_TYPE_INTERNAL,
 107        SND_BEBOB_CLOCK_TYPE_EXTERNAL,  /* S/PDIF */
 108        SND_BEBOB_CLOCK_TYPE_EXTERNAL,  /* Word Clock */
 109};
 110static const enum snd_bebob_clock_type saffirepro_26_clk_src_types[] = {
 111        SND_BEBOB_CLOCK_TYPE_INTERNAL,
 112        SND_BEBOB_CLOCK_TYPE_EXTERNAL,  /* S/PDIF */
 113        SND_BEBOB_CLOCK_TYPE_EXTERNAL,  /* ADAT1 */
 114        SND_BEBOB_CLOCK_TYPE_EXTERNAL,  /* ADAT2 */
 115        SND_BEBOB_CLOCK_TYPE_EXTERNAL,  /* Word Clock */
 116};
 117/* Value maps between registers and labels for SaffirePro 10/26. */
 118static const signed char saffirepro_clk_maps[][SAFFIREPRO_CLOCK_SOURCE_COUNT] = {
 119        /* SaffirePro 10 */
 120        [0] = {
 121                [SAFFIREPRO_CLOCK_SOURCE_INTERNAL]  =  0,
 122                [SAFFIREPRO_CLOCK_SOURCE_SKIP]      = -1, /* not supported */
 123                [SAFFIREPRO_CLOCK_SOURCE_SPDIF]     =  1,
 124                [SAFFIREPRO_CLOCK_SOURCE_ADAT1]     = -1, /* not supported */
 125                [SAFFIREPRO_CLOCK_SOURCE_ADAT2]     = -1, /* not supported */
 126                [SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] =  2,
 127        },
 128        /* SaffirePro 26 */
 129        [1] = {
 130                [SAFFIREPRO_CLOCK_SOURCE_INTERNAL]  =  0,
 131                [SAFFIREPRO_CLOCK_SOURCE_SKIP]      = -1, /* not supported */
 132                [SAFFIREPRO_CLOCK_SOURCE_SPDIF]     =  1,
 133                [SAFFIREPRO_CLOCK_SOURCE_ADAT1]     =  2,
 134                [SAFFIREPRO_CLOCK_SOURCE_ADAT2]     =  3,
 135                [SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] =  4,
 136        }
 137};
 138
 139static int
 140saffirepro_both_clk_freq_get(struct snd_bebob *bebob, unsigned int *rate)
 141{
 142        u32 id;
 143        int err;
 144
 145        err = saffire_read_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, &id);
 146        if (err < 0)
 147                goto end;
 148        if (id >= ARRAY_SIZE(rates))
 149                err = -EIO;
 150        else
 151                *rate = rates[id];
 152end:
 153        return err;
 154}
 155static int
 156saffirepro_both_clk_freq_set(struct snd_bebob *bebob, unsigned int rate)
 157{
 158        u32 id;
 159
 160        for (id = 0; id < ARRAY_SIZE(rates); id++) {
 161                if (rates[id] == rate)
 162                        break;
 163        }
 164        if (id == ARRAY_SIZE(rates))
 165                return -EINVAL;
 166
 167        return saffire_write_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, id);
 168}
 169
 170/*
 171 * query hardware for current clock source, return our internally
 172 * used clock index in *id, depending on hardware.
 173 */
 174static int
 175saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
 176{
 177        int err;
 178        u32 value;       /* clock source read from hw register */
 179        const signed char *map;
 180
 181        err = saffire_read_quad(bebob, SAFFIREPRO_OFFSET_CLOCK_SOURCE, &value);
 182        if (err < 0)
 183                goto end;
 184
 185        /* depending on hardware, use a different mapping */
 186        if (bebob->spec->clock->types == saffirepro_10_clk_src_types)
 187                map = saffirepro_clk_maps[0];
 188        else
 189                map = saffirepro_clk_maps[1];
 190
 191        /* In a case that this driver cannot handle the value of register. */
 192        if (value >= SAFFIREPRO_CLOCK_SOURCE_COUNT || map[value] < 0) {
 193                err = -EIO;
 194                goto end;
 195        }
 196
 197        *id = (unsigned int)map[value];
 198end:
 199        return err;
 200}
 201
 202const struct snd_bebob_spec saffire_le_spec;
 203static const enum snd_bebob_clock_type saffire_both_clk_src_types[] = {
 204        SND_BEBOB_CLOCK_TYPE_INTERNAL,
 205        SND_BEBOB_CLOCK_TYPE_EXTERNAL,
 206};
 207static int
 208saffire_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
 209{
 210        int err;
 211        u32 value;
 212
 213        err = saffire_read_quad(bebob, SAFFIRE_OFFSET_CLOCK_SOURCE, &value);
 214        if (err >= 0)
 215                *id = 0xff & value;
 216
 217        return err;
 218};
 219static const char *const saffire_le_meter_labels[] = {
 220        ANA_IN, ANA_IN, DIG_IN,
 221        ANA_OUT, ANA_OUT, ANA_OUT, ANA_OUT,
 222        STM_IN, STM_IN
 223};
 224static const char *const saffire_meter_labels[] = {
 225        ANA_IN, ANA_IN,
 226        STM_IN, STM_IN, STM_IN, STM_IN, STM_IN,
 227};
 228static int
 229saffire_meter_get(struct snd_bebob *bebob, u32 *buf, unsigned int size)
 230{
 231        const struct snd_bebob_meter_spec *spec = bebob->spec->meter;
 232        unsigned int channels;
 233        u64 offset;
 234        int err;
 235
 236        if (spec->labels == saffire_le_meter_labels)
 237                offset = SAFFIRE_LE_OFFSET_METER;
 238        else
 239                offset = SAFFIRE_OFFSET_METER;
 240
 241        channels = spec->num * 2;
 242        if (size < channels * sizeof(u32))
 243                return -EIO;
 244
 245        err = saffire_read_block(bebob, offset, buf, size);
 246        if (err >= 0 && spec->labels == saffire_le_meter_labels) {
 247                swap(buf[1], buf[3]);
 248                swap(buf[2], buf[3]);
 249                swap(buf[3], buf[4]);
 250
 251                swap(buf[7], buf[10]);
 252                swap(buf[8], buf[10]);
 253                swap(buf[9], buf[11]);
 254                swap(buf[11], buf[12]);
 255
 256                swap(buf[15], buf[16]);
 257        }
 258
 259        return err;
 260}
 261
 262static const struct snd_bebob_rate_spec saffirepro_both_rate_spec = {
 263        .get    = &saffirepro_both_clk_freq_get,
 264        .set    = &saffirepro_both_clk_freq_set,
 265};
 266/* Saffire Pro 26 I/O  */
 267static const struct snd_bebob_clock_spec saffirepro_26_clk_spec = {
 268        .num    = ARRAY_SIZE(saffirepro_26_clk_src_types),
 269        .types  = saffirepro_26_clk_src_types,
 270        .get    = &saffirepro_both_clk_src_get,
 271};
 272const struct snd_bebob_spec saffirepro_26_spec = {
 273        .clock  = &saffirepro_26_clk_spec,
 274        .rate   = &saffirepro_both_rate_spec,
 275        .meter  = NULL
 276};
 277/* Saffire Pro 10 I/O */
 278static const struct snd_bebob_clock_spec saffirepro_10_clk_spec = {
 279        .num    = ARRAY_SIZE(saffirepro_10_clk_src_types),
 280        .types  = saffirepro_10_clk_src_types,
 281        .get    = &saffirepro_both_clk_src_get,
 282};
 283const struct snd_bebob_spec saffirepro_10_spec = {
 284        .clock  = &saffirepro_10_clk_spec,
 285        .rate   = &saffirepro_both_rate_spec,
 286        .meter  = NULL
 287};
 288
 289static const struct snd_bebob_rate_spec saffire_both_rate_spec = {
 290        .get    = &snd_bebob_stream_get_rate,
 291        .set    = &snd_bebob_stream_set_rate,
 292};
 293static const struct snd_bebob_clock_spec saffire_both_clk_spec = {
 294        .num    = ARRAY_SIZE(saffire_both_clk_src_types),
 295        .types  = saffire_both_clk_src_types,
 296        .get    = &saffire_both_clk_src_get,
 297};
 298/* Saffire LE */
 299static const struct snd_bebob_meter_spec saffire_le_meter_spec = {
 300        .num    = ARRAY_SIZE(saffire_le_meter_labels),
 301        .labels = saffire_le_meter_labels,
 302        .get    = &saffire_meter_get,
 303};
 304const struct snd_bebob_spec saffire_le_spec = {
 305        .clock  = &saffire_both_clk_spec,
 306        .rate   = &saffire_both_rate_spec,
 307        .meter  = &saffire_le_meter_spec
 308};
 309/* Saffire */
 310static const struct snd_bebob_meter_spec saffire_meter_spec = {
 311        .num    = ARRAY_SIZE(saffire_meter_labels),
 312        .labels = saffire_meter_labels,
 313        .get    = &saffire_meter_get,
 314};
 315const struct snd_bebob_spec saffire_spec = {
 316        .clock  = &saffire_both_clk_spec,
 317        .rate   = &saffire_both_rate_spec,
 318        .meter  = &saffire_meter_spec
 319};
 320