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