root/sound/firewire/bebob/bebob_focusrite.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. saffire_read_block
  2. saffire_read_quad
  3. saffire_write_quad
  4. saffirepro_both_clk_freq_get
  5. saffirepro_both_clk_freq_set
  6. saffirepro_both_clk_src_get
  7. saffire_both_clk_src_get
  8. saffire_meter_get

   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 */
  46 static 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 
  60 static inline int
  61 saffire_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]);
  76 end:
  77         return err;
  78 }
  79 
  80 static inline int
  81 saffire_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);
  93 end:
  94         return err;
  95 }
  96 
  97 static inline int
  98 saffire_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 
 107 static 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 };
 112 static 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. */
 120 static 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 
 141 static int
 142 saffirepro_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];
 154 end:
 155         return err;
 156 }
 157 static int
 158 saffirepro_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  */
 176 static int
 177 saffirepro_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];
 201 end:
 202         return err;
 203 }
 204 
 205 const struct snd_bebob_spec saffire_le_spec;
 206 static const enum snd_bebob_clock_type saffire_both_clk_src_types[] = {
 207         SND_BEBOB_CLOCK_TYPE_INTERNAL,
 208         SND_BEBOB_CLOCK_TYPE_EXTERNAL,
 209 };
 210 static int
 211 saffire_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 };
 222 static 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 };
 227 static const char *const saffire_meter_labels[] = {
 228         ANA_IN, ANA_IN,
 229         STM_IN, STM_IN, STM_IN, STM_IN, STM_IN,
 230 };
 231 static int
 232 saffire_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 
 265 static 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  */
 270 static 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 };
 275 const 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 */
 281 static 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 };
 286 const struct snd_bebob_spec saffirepro_10_spec = {
 287         .clock  = &saffirepro_10_clk_spec,
 288         .rate   = &saffirepro_both_rate_spec,
 289         .meter  = NULL
 290 };
 291 
 292 static 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 };
 296 static 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 */
 302 static 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 };
 307 const 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 */
 313 static 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 };
 318 const struct snd_bebob_spec saffire_spec = {
 319         .clock  = &saffire_both_clk_spec,
 320         .rate   = &saffire_both_rate_spec,
 321         .meter  = &saffire_meter_spec
 322 };

/* [<][>][^][v][top][bottom][index][help] */