cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bebob_focusrite.c (8856B)


      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};