18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * bebob_focusrite.c - a part of driver for BeBoB based devices 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2013-2014 Takashi Sakamoto 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include "./bebob.h" 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#define ANA_IN "Analog In" 118c2ecf20Sopenharmony_ci#define DIG_IN "Digital In" 128c2ecf20Sopenharmony_ci#define ANA_OUT "Analog Out" 138c2ecf20Sopenharmony_ci#define DIG_OUT "Digital Out" 148c2ecf20Sopenharmony_ci#define STM_IN "Stream In" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#define SAFFIRE_ADDRESS_BASE 0x000100000000ULL 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define SAFFIRE_OFFSET_CLOCK_SOURCE 0x00f8 198c2ecf20Sopenharmony_ci#define SAFFIREPRO_OFFSET_CLOCK_SOURCE 0x0174 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci/* whether sync to external device or not */ 228c2ecf20Sopenharmony_ci#define SAFFIRE_OFFSET_CLOCK_SYNC_EXT 0x013c 238c2ecf20Sopenharmony_ci#define SAFFIRE_LE_OFFSET_CLOCK_SYNC_EXT 0x0432 248c2ecf20Sopenharmony_ci#define SAFFIREPRO_OFFSET_CLOCK_SYNC_EXT 0x0164 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define SAFFIRE_CLOCK_SOURCE_INTERNAL 0 278c2ecf20Sopenharmony_ci#define SAFFIRE_CLOCK_SOURCE_SPDIF 1 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci/* clock sources as returned from register of Saffire Pro 10 and 26 */ 308c2ecf20Sopenharmony_ci#define SAFFIREPRO_CLOCK_SOURCE_SELECT_MASK 0x000000ff 318c2ecf20Sopenharmony_ci#define SAFFIREPRO_CLOCK_SOURCE_DETECT_MASK 0x0000ff00 328c2ecf20Sopenharmony_ci#define SAFFIREPRO_CLOCK_SOURCE_INTERNAL 0 338c2ecf20Sopenharmony_ci#define SAFFIREPRO_CLOCK_SOURCE_SKIP 1 /* never used on hardware */ 348c2ecf20Sopenharmony_ci#define SAFFIREPRO_CLOCK_SOURCE_SPDIF 2 358c2ecf20Sopenharmony_ci#define SAFFIREPRO_CLOCK_SOURCE_ADAT1 3 /* not used on s.pro. 10 */ 368c2ecf20Sopenharmony_ci#define SAFFIREPRO_CLOCK_SOURCE_ADAT2 4 /* not used on s.pro. 10 */ 378c2ecf20Sopenharmony_ci#define SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK 5 388c2ecf20Sopenharmony_ci#define SAFFIREPRO_CLOCK_SOURCE_COUNT 6 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* S/PDIF, ADAT1, ADAT2 is enabled or not. three quadlets */ 418c2ecf20Sopenharmony_ci#define SAFFIREPRO_ENABLE_DIG_IFACES 0x01a4 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* saffirepro has its own parameter for sampling frequency */ 448c2ecf20Sopenharmony_ci#define SAFFIREPRO_RATE_NOREBOOT 0x01cc 458c2ecf20Sopenharmony_ci/* index is the value for this register */ 468c2ecf20Sopenharmony_cistatic const unsigned int rates[] = { 478c2ecf20Sopenharmony_ci [0] = 0, 488c2ecf20Sopenharmony_ci [1] = 44100, 498c2ecf20Sopenharmony_ci [2] = 48000, 508c2ecf20Sopenharmony_ci [3] = 88200, 518c2ecf20Sopenharmony_ci [4] = 96000, 528c2ecf20Sopenharmony_ci [5] = 176400, 538c2ecf20Sopenharmony_ci [6] = 192000 548c2ecf20Sopenharmony_ci}; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci/* saffire(no label)/saffire LE has metering */ 578c2ecf20Sopenharmony_ci#define SAFFIRE_OFFSET_METER 0x0100 588c2ecf20Sopenharmony_ci#define SAFFIRE_LE_OFFSET_METER 0x0168 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistatic inline int 618c2ecf20Sopenharmony_cisaffire_read_block(struct snd_bebob *bebob, u64 offset, 628c2ecf20Sopenharmony_ci u32 *buf, unsigned int size) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci unsigned int i; 658c2ecf20Sopenharmony_ci int err; 668c2ecf20Sopenharmony_ci __be32 *tmp = (__be32 *)buf; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci err = snd_fw_transaction(bebob->unit, TCODE_READ_BLOCK_REQUEST, 698c2ecf20Sopenharmony_ci SAFFIRE_ADDRESS_BASE + offset, 708c2ecf20Sopenharmony_ci tmp, size, 0); 718c2ecf20Sopenharmony_ci if (err < 0) 728c2ecf20Sopenharmony_ci goto end; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci for (i = 0; i < size / sizeof(u32); i++) 758c2ecf20Sopenharmony_ci buf[i] = be32_to_cpu(tmp[i]); 768c2ecf20Sopenharmony_ciend: 778c2ecf20Sopenharmony_ci return err; 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic inline int 818c2ecf20Sopenharmony_cisaffire_read_quad(struct snd_bebob *bebob, u64 offset, u32 *value) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci int err; 848c2ecf20Sopenharmony_ci __be32 tmp; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci err = snd_fw_transaction(bebob->unit, TCODE_READ_QUADLET_REQUEST, 878c2ecf20Sopenharmony_ci SAFFIRE_ADDRESS_BASE + offset, 888c2ecf20Sopenharmony_ci &tmp, sizeof(__be32), 0); 898c2ecf20Sopenharmony_ci if (err < 0) 908c2ecf20Sopenharmony_ci goto end; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci *value = be32_to_cpu(tmp); 938c2ecf20Sopenharmony_ciend: 948c2ecf20Sopenharmony_ci return err; 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistatic inline int 988c2ecf20Sopenharmony_cisaffire_write_quad(struct snd_bebob *bebob, u64 offset, u32 value) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci __be32 data = cpu_to_be32(value); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci return snd_fw_transaction(bebob->unit, TCODE_WRITE_QUADLET_REQUEST, 1038c2ecf20Sopenharmony_ci SAFFIRE_ADDRESS_BASE + offset, 1048c2ecf20Sopenharmony_ci &data, sizeof(__be32), 0); 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic const enum snd_bebob_clock_type saffirepro_10_clk_src_types[] = { 1088c2ecf20Sopenharmony_ci SND_BEBOB_CLOCK_TYPE_INTERNAL, 1098c2ecf20Sopenharmony_ci SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ 1108c2ecf20Sopenharmony_ci SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* Word Clock */ 1118c2ecf20Sopenharmony_ci}; 1128c2ecf20Sopenharmony_cistatic const enum snd_bebob_clock_type saffirepro_26_clk_src_types[] = { 1138c2ecf20Sopenharmony_ci SND_BEBOB_CLOCK_TYPE_INTERNAL, 1148c2ecf20Sopenharmony_ci SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ 1158c2ecf20Sopenharmony_ci SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* ADAT1 */ 1168c2ecf20Sopenharmony_ci SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* ADAT2 */ 1178c2ecf20Sopenharmony_ci SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* Word Clock */ 1188c2ecf20Sopenharmony_ci}; 1198c2ecf20Sopenharmony_ci/* Value maps between registers and labels for SaffirePro 10/26. */ 1208c2ecf20Sopenharmony_cistatic const signed char saffirepro_clk_maps[][SAFFIREPRO_CLOCK_SOURCE_COUNT] = { 1218c2ecf20Sopenharmony_ci /* SaffirePro 10 */ 1228c2ecf20Sopenharmony_ci [0] = { 1238c2ecf20Sopenharmony_ci [SAFFIREPRO_CLOCK_SOURCE_INTERNAL] = 0, 1248c2ecf20Sopenharmony_ci [SAFFIREPRO_CLOCK_SOURCE_SKIP] = -1, /* not supported */ 1258c2ecf20Sopenharmony_ci [SAFFIREPRO_CLOCK_SOURCE_SPDIF] = 1, 1268c2ecf20Sopenharmony_ci [SAFFIREPRO_CLOCK_SOURCE_ADAT1] = -1, /* not supported */ 1278c2ecf20Sopenharmony_ci [SAFFIREPRO_CLOCK_SOURCE_ADAT2] = -1, /* not supported */ 1288c2ecf20Sopenharmony_ci [SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] = 2, 1298c2ecf20Sopenharmony_ci }, 1308c2ecf20Sopenharmony_ci /* SaffirePro 26 */ 1318c2ecf20Sopenharmony_ci [1] = { 1328c2ecf20Sopenharmony_ci [SAFFIREPRO_CLOCK_SOURCE_INTERNAL] = 0, 1338c2ecf20Sopenharmony_ci [SAFFIREPRO_CLOCK_SOURCE_SKIP] = -1, /* not supported */ 1348c2ecf20Sopenharmony_ci [SAFFIREPRO_CLOCK_SOURCE_SPDIF] = 1, 1358c2ecf20Sopenharmony_ci [SAFFIREPRO_CLOCK_SOURCE_ADAT1] = 2, 1368c2ecf20Sopenharmony_ci [SAFFIREPRO_CLOCK_SOURCE_ADAT2] = 3, 1378c2ecf20Sopenharmony_ci [SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] = 4, 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci}; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_cistatic int 1428c2ecf20Sopenharmony_cisaffirepro_both_clk_freq_get(struct snd_bebob *bebob, unsigned int *rate) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci u32 id; 1458c2ecf20Sopenharmony_ci int err; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci err = saffire_read_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, &id); 1488c2ecf20Sopenharmony_ci if (err < 0) 1498c2ecf20Sopenharmony_ci goto end; 1508c2ecf20Sopenharmony_ci if (id >= ARRAY_SIZE(rates)) 1518c2ecf20Sopenharmony_ci err = -EIO; 1528c2ecf20Sopenharmony_ci else 1538c2ecf20Sopenharmony_ci *rate = rates[id]; 1548c2ecf20Sopenharmony_ciend: 1558c2ecf20Sopenharmony_ci return err; 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_cistatic int 1588c2ecf20Sopenharmony_cisaffirepro_both_clk_freq_set(struct snd_bebob *bebob, unsigned int rate) 1598c2ecf20Sopenharmony_ci{ 1608c2ecf20Sopenharmony_ci u32 id; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci for (id = 0; id < ARRAY_SIZE(rates); id++) { 1638c2ecf20Sopenharmony_ci if (rates[id] == rate) 1648c2ecf20Sopenharmony_ci break; 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci if (id == ARRAY_SIZE(rates)) 1678c2ecf20Sopenharmony_ci return -EINVAL; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci return saffire_write_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, id); 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci/* 1738c2ecf20Sopenharmony_ci * query hardware for current clock source, return our internally 1748c2ecf20Sopenharmony_ci * used clock index in *id, depending on hardware. 1758c2ecf20Sopenharmony_ci */ 1768c2ecf20Sopenharmony_cistatic int 1778c2ecf20Sopenharmony_cisaffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci int err; 1808c2ecf20Sopenharmony_ci u32 value; /* clock source read from hw register */ 1818c2ecf20Sopenharmony_ci const signed char *map; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci err = saffire_read_quad(bebob, SAFFIREPRO_OFFSET_CLOCK_SOURCE, &value); 1848c2ecf20Sopenharmony_ci if (err < 0) 1858c2ecf20Sopenharmony_ci goto end; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci /* depending on hardware, use a different mapping */ 1888c2ecf20Sopenharmony_ci if (bebob->spec->clock->types == saffirepro_10_clk_src_types) 1898c2ecf20Sopenharmony_ci map = saffirepro_clk_maps[0]; 1908c2ecf20Sopenharmony_ci else 1918c2ecf20Sopenharmony_ci map = saffirepro_clk_maps[1]; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci /* In a case that this driver cannot handle the value of register. */ 1948c2ecf20Sopenharmony_ci value &= SAFFIREPRO_CLOCK_SOURCE_SELECT_MASK; 1958c2ecf20Sopenharmony_ci if (value >= SAFFIREPRO_CLOCK_SOURCE_COUNT || map[value] < 0) { 1968c2ecf20Sopenharmony_ci err = -EIO; 1978c2ecf20Sopenharmony_ci goto end; 1988c2ecf20Sopenharmony_ci } 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci *id = (unsigned int)map[value]; 2018c2ecf20Sopenharmony_ciend: 2028c2ecf20Sopenharmony_ci return err; 2038c2ecf20Sopenharmony_ci} 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ciconst struct snd_bebob_spec saffire_le_spec; 2068c2ecf20Sopenharmony_cistatic const enum snd_bebob_clock_type saffire_both_clk_src_types[] = { 2078c2ecf20Sopenharmony_ci SND_BEBOB_CLOCK_TYPE_INTERNAL, 2088c2ecf20Sopenharmony_ci SND_BEBOB_CLOCK_TYPE_EXTERNAL, 2098c2ecf20Sopenharmony_ci}; 2108c2ecf20Sopenharmony_cistatic int 2118c2ecf20Sopenharmony_cisaffire_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci int err; 2148c2ecf20Sopenharmony_ci u32 value; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci err = saffire_read_quad(bebob, SAFFIRE_OFFSET_CLOCK_SOURCE, &value); 2178c2ecf20Sopenharmony_ci if (err >= 0) 2188c2ecf20Sopenharmony_ci *id = 0xff & value; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci return err; 2218c2ecf20Sopenharmony_ci}; 2228c2ecf20Sopenharmony_cistatic const char *const saffire_le_meter_labels[] = { 2238c2ecf20Sopenharmony_ci ANA_IN, ANA_IN, DIG_IN, 2248c2ecf20Sopenharmony_ci ANA_OUT, ANA_OUT, ANA_OUT, ANA_OUT, 2258c2ecf20Sopenharmony_ci STM_IN, STM_IN 2268c2ecf20Sopenharmony_ci}; 2278c2ecf20Sopenharmony_cistatic const char *const saffire_meter_labels[] = { 2288c2ecf20Sopenharmony_ci ANA_IN, ANA_IN, 2298c2ecf20Sopenharmony_ci STM_IN, STM_IN, STM_IN, STM_IN, STM_IN, 2308c2ecf20Sopenharmony_ci}; 2318c2ecf20Sopenharmony_cistatic int 2328c2ecf20Sopenharmony_cisaffire_meter_get(struct snd_bebob *bebob, u32 *buf, unsigned int size) 2338c2ecf20Sopenharmony_ci{ 2348c2ecf20Sopenharmony_ci const struct snd_bebob_meter_spec *spec = bebob->spec->meter; 2358c2ecf20Sopenharmony_ci unsigned int channels; 2368c2ecf20Sopenharmony_ci u64 offset; 2378c2ecf20Sopenharmony_ci int err; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci if (spec->labels == saffire_le_meter_labels) 2408c2ecf20Sopenharmony_ci offset = SAFFIRE_LE_OFFSET_METER; 2418c2ecf20Sopenharmony_ci else 2428c2ecf20Sopenharmony_ci offset = SAFFIRE_OFFSET_METER; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci channels = spec->num * 2; 2458c2ecf20Sopenharmony_ci if (size < channels * sizeof(u32)) 2468c2ecf20Sopenharmony_ci return -EIO; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci err = saffire_read_block(bebob, offset, buf, size); 2498c2ecf20Sopenharmony_ci if (err >= 0 && spec->labels == saffire_le_meter_labels) { 2508c2ecf20Sopenharmony_ci swap(buf[1], buf[3]); 2518c2ecf20Sopenharmony_ci swap(buf[2], buf[3]); 2528c2ecf20Sopenharmony_ci swap(buf[3], buf[4]); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci swap(buf[7], buf[10]); 2558c2ecf20Sopenharmony_ci swap(buf[8], buf[10]); 2568c2ecf20Sopenharmony_ci swap(buf[9], buf[11]); 2578c2ecf20Sopenharmony_ci swap(buf[11], buf[12]); 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci swap(buf[15], buf[16]); 2608c2ecf20Sopenharmony_ci } 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci return err; 2638c2ecf20Sopenharmony_ci} 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_cistatic const struct snd_bebob_rate_spec saffirepro_both_rate_spec = { 2668c2ecf20Sopenharmony_ci .get = &saffirepro_both_clk_freq_get, 2678c2ecf20Sopenharmony_ci .set = &saffirepro_both_clk_freq_set, 2688c2ecf20Sopenharmony_ci}; 2698c2ecf20Sopenharmony_ci/* Saffire Pro 26 I/O */ 2708c2ecf20Sopenharmony_cistatic const struct snd_bebob_clock_spec saffirepro_26_clk_spec = { 2718c2ecf20Sopenharmony_ci .num = ARRAY_SIZE(saffirepro_26_clk_src_types), 2728c2ecf20Sopenharmony_ci .types = saffirepro_26_clk_src_types, 2738c2ecf20Sopenharmony_ci .get = &saffirepro_both_clk_src_get, 2748c2ecf20Sopenharmony_ci}; 2758c2ecf20Sopenharmony_ciconst struct snd_bebob_spec saffirepro_26_spec = { 2768c2ecf20Sopenharmony_ci .clock = &saffirepro_26_clk_spec, 2778c2ecf20Sopenharmony_ci .rate = &saffirepro_both_rate_spec, 2788c2ecf20Sopenharmony_ci .meter = NULL 2798c2ecf20Sopenharmony_ci}; 2808c2ecf20Sopenharmony_ci/* Saffire Pro 10 I/O */ 2818c2ecf20Sopenharmony_cistatic const struct snd_bebob_clock_spec saffirepro_10_clk_spec = { 2828c2ecf20Sopenharmony_ci .num = ARRAY_SIZE(saffirepro_10_clk_src_types), 2838c2ecf20Sopenharmony_ci .types = saffirepro_10_clk_src_types, 2848c2ecf20Sopenharmony_ci .get = &saffirepro_both_clk_src_get, 2858c2ecf20Sopenharmony_ci}; 2868c2ecf20Sopenharmony_ciconst struct snd_bebob_spec saffirepro_10_spec = { 2878c2ecf20Sopenharmony_ci .clock = &saffirepro_10_clk_spec, 2888c2ecf20Sopenharmony_ci .rate = &saffirepro_both_rate_spec, 2898c2ecf20Sopenharmony_ci .meter = NULL 2908c2ecf20Sopenharmony_ci}; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_cistatic const struct snd_bebob_rate_spec saffire_both_rate_spec = { 2938c2ecf20Sopenharmony_ci .get = &snd_bebob_stream_get_rate, 2948c2ecf20Sopenharmony_ci .set = &snd_bebob_stream_set_rate, 2958c2ecf20Sopenharmony_ci}; 2968c2ecf20Sopenharmony_cistatic const struct snd_bebob_clock_spec saffire_both_clk_spec = { 2978c2ecf20Sopenharmony_ci .num = ARRAY_SIZE(saffire_both_clk_src_types), 2988c2ecf20Sopenharmony_ci .types = saffire_both_clk_src_types, 2998c2ecf20Sopenharmony_ci .get = &saffire_both_clk_src_get, 3008c2ecf20Sopenharmony_ci}; 3018c2ecf20Sopenharmony_ci/* Saffire LE */ 3028c2ecf20Sopenharmony_cistatic const struct snd_bebob_meter_spec saffire_le_meter_spec = { 3038c2ecf20Sopenharmony_ci .num = ARRAY_SIZE(saffire_le_meter_labels), 3048c2ecf20Sopenharmony_ci .labels = saffire_le_meter_labels, 3058c2ecf20Sopenharmony_ci .get = &saffire_meter_get, 3068c2ecf20Sopenharmony_ci}; 3078c2ecf20Sopenharmony_ciconst struct snd_bebob_spec saffire_le_spec = { 3088c2ecf20Sopenharmony_ci .clock = &saffire_both_clk_spec, 3098c2ecf20Sopenharmony_ci .rate = &saffire_both_rate_spec, 3108c2ecf20Sopenharmony_ci .meter = &saffire_le_meter_spec 3118c2ecf20Sopenharmony_ci}; 3128c2ecf20Sopenharmony_ci/* Saffire */ 3138c2ecf20Sopenharmony_cistatic const struct snd_bebob_meter_spec saffire_meter_spec = { 3148c2ecf20Sopenharmony_ci .num = ARRAY_SIZE(saffire_meter_labels), 3158c2ecf20Sopenharmony_ci .labels = saffire_meter_labels, 3168c2ecf20Sopenharmony_ci .get = &saffire_meter_get, 3178c2ecf20Sopenharmony_ci}; 3188c2ecf20Sopenharmony_ciconst struct snd_bebob_spec saffire_spec = { 3198c2ecf20Sopenharmony_ci .clock = &saffire_both_clk_spec, 3208c2ecf20Sopenharmony_ci .rate = &saffire_both_rate_spec, 3218c2ecf20Sopenharmony_ci .meter = &saffire_meter_spec 3228c2ecf20Sopenharmony_ci}; 323