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

maya44.c (19774B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
      4 *
      5 *   Lowlevel functions for ESI Maya44 cards
      6 *
      7 *	Copyright (c) 2009 Takashi Iwai <tiwai@suse.de>
      8 *	Based on the patches by Rainer Zimmermann <mail@lightshed.de>
      9 */
     10
     11#include <linux/init.h>
     12#include <linux/slab.h>
     13#include <sound/core.h>
     14#include <sound/control.h>
     15#include <sound/pcm.h>
     16#include <sound/tlv.h>
     17
     18#include "ice1712.h"
     19#include "envy24ht.h"
     20#include "maya44.h"
     21
     22/* WM8776 register indexes */
     23#define WM8776_REG_HEADPHONE_L		0x00
     24#define WM8776_REG_HEADPHONE_R		0x01
     25#define WM8776_REG_HEADPHONE_MASTER	0x02
     26#define WM8776_REG_DAC_ATTEN_L		0x03
     27#define WM8776_REG_DAC_ATTEN_R		0x04
     28#define WM8776_REG_DAC_ATTEN_MASTER	0x05
     29#define WM8776_REG_DAC_PHASE		0x06
     30#define WM8776_REG_DAC_CONTROL		0x07
     31#define WM8776_REG_DAC_MUTE		0x08
     32#define WM8776_REG_DAC_DEEMPH		0x09
     33#define WM8776_REG_DAC_IF_CONTROL	0x0a
     34#define WM8776_REG_ADC_IF_CONTROL	0x0b
     35#define WM8776_REG_MASTER_MODE_CONTROL	0x0c
     36#define WM8776_REG_POWERDOWN		0x0d
     37#define WM8776_REG_ADC_ATTEN_L		0x0e
     38#define WM8776_REG_ADC_ATTEN_R		0x0f
     39#define WM8776_REG_ADC_ALC1		0x10
     40#define WM8776_REG_ADC_ALC2		0x11
     41#define WM8776_REG_ADC_ALC3		0x12
     42#define WM8776_REG_ADC_NOISE_GATE	0x13
     43#define WM8776_REG_ADC_LIMITER		0x14
     44#define WM8776_REG_ADC_MUX		0x15
     45#define WM8776_REG_OUTPUT_MUX		0x16
     46#define WM8776_REG_RESET		0x17
     47
     48#define WM8776_NUM_REGS			0x18
     49
     50/* clock ratio identifiers for snd_wm8776_set_rate() */
     51#define WM8776_CLOCK_RATIO_128FS	0
     52#define WM8776_CLOCK_RATIO_192FS	1
     53#define WM8776_CLOCK_RATIO_256FS	2
     54#define WM8776_CLOCK_RATIO_384FS	3
     55#define WM8776_CLOCK_RATIO_512FS	4
     56#define WM8776_CLOCK_RATIO_768FS	5
     57
     58enum { WM_VOL_HP, WM_VOL_DAC, WM_VOL_ADC, WM_NUM_VOLS };
     59enum { WM_SW_DAC, WM_SW_BYPASS, WM_NUM_SWITCHES };
     60
     61struct snd_wm8776 {
     62	unsigned char addr;
     63	unsigned short regs[WM8776_NUM_REGS];
     64	unsigned char volumes[WM_NUM_VOLS][2];
     65	unsigned int switch_bits;
     66};
     67
     68struct snd_maya44 {
     69	struct snd_ice1712 *ice;
     70	struct snd_wm8776 wm[2];
     71	struct mutex mutex;
     72};
     73
     74
     75/* write the given register and save the data to the cache */
     76static void wm8776_write(struct snd_ice1712 *ice, struct snd_wm8776 *wm,
     77			 unsigned char reg, unsigned short val)
     78{
     79	/*
     80	 * WM8776 registers are up to 9 bits wide, bit 8 is placed in the LSB
     81	 * of the address field
     82	 */
     83	snd_vt1724_write_i2c(ice, wm->addr,
     84			     (reg << 1) | ((val >> 8) & 1),
     85			     val & 0xff);
     86	wm->regs[reg] = val;
     87}
     88
     89/*
     90 * update the given register with and/or mask and save the data to the cache
     91 */
     92static int wm8776_write_bits(struct snd_ice1712 *ice, struct snd_wm8776 *wm,
     93			     unsigned char reg,
     94			     unsigned short mask, unsigned short val)
     95{
     96	val |= wm->regs[reg] & ~mask;
     97	if (val != wm->regs[reg]) {
     98		wm8776_write(ice, wm, reg, val);
     99		return 1;
    100	}
    101	return 0;
    102}
    103
    104
    105/*
    106 * WM8776 volume controls
    107 */
    108
    109struct maya_vol_info {
    110	unsigned int maxval;		/* volume range: 0..maxval */
    111	unsigned char regs[2];		/* left and right registers */
    112	unsigned short mask;		/* value mask */
    113	unsigned short offset;		/* zero-value offset */
    114	unsigned short mute;		/* mute bit */
    115	unsigned short update;		/* update bits */
    116	unsigned char mux_bits[2];	/* extra bits for ADC mute */
    117};
    118
    119static const struct maya_vol_info vol_info[WM_NUM_VOLS] = {
    120	[WM_VOL_HP] = {
    121		.maxval = 80,
    122		.regs = { WM8776_REG_HEADPHONE_L, WM8776_REG_HEADPHONE_R },
    123		.mask = 0x7f,
    124		.offset = 0x30,
    125		.mute = 0x00,
    126		.update = 0x180,	/* update and zero-cross enable */
    127	},
    128	[WM_VOL_DAC] = {
    129		.maxval = 255,
    130		.regs = { WM8776_REG_DAC_ATTEN_L, WM8776_REG_DAC_ATTEN_R },
    131		.mask = 0xff,
    132		.offset = 0x01,
    133		.mute = 0x00,
    134		.update = 0x100,	/* zero-cross enable */
    135	},
    136	[WM_VOL_ADC] = {
    137		.maxval = 91,
    138		.regs = { WM8776_REG_ADC_ATTEN_L, WM8776_REG_ADC_ATTEN_R },
    139		.mask = 0xff,
    140		.offset = 0xa5,
    141		.mute = 0xa5,
    142		.update = 0x100,	/* update */
    143		.mux_bits = { 0x80, 0x40 }, /* ADCMUX bits */
    144	},
    145};
    146
    147/*
    148 * dB tables
    149 */
    150/* headphone output: mute, -73..+6db (1db step) */
    151static const DECLARE_TLV_DB_SCALE(db_scale_hp, -7400, 100, 1);
    152/* DAC output: mute, -127..0db (0.5db step) */
    153static const DECLARE_TLV_DB_SCALE(db_scale_dac, -12750, 50, 1);
    154/* ADC gain: mute, -21..+24db (0.5db step) */
    155static const DECLARE_TLV_DB_SCALE(db_scale_adc, -2100, 50, 1);
    156
    157static int maya_vol_info(struct snd_kcontrol *kcontrol,
    158			 struct snd_ctl_elem_info *uinfo)
    159{
    160	unsigned int idx = kcontrol->private_value;
    161	const struct maya_vol_info *vol = &vol_info[idx];
    162
    163	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
    164	uinfo->count = 2;
    165	uinfo->value.integer.min = 0;
    166	uinfo->value.integer.max = vol->maxval;
    167	return 0;
    168}
    169
    170static int maya_vol_get(struct snd_kcontrol *kcontrol,
    171			struct snd_ctl_elem_value *ucontrol)
    172{
    173	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
    174	struct snd_wm8776 *wm =
    175		&chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
    176	unsigned int idx = kcontrol->private_value;
    177
    178	mutex_lock(&chip->mutex);
    179	ucontrol->value.integer.value[0] = wm->volumes[idx][0];
    180	ucontrol->value.integer.value[1] = wm->volumes[idx][1];
    181	mutex_unlock(&chip->mutex);
    182	return 0;
    183}
    184
    185static int maya_vol_put(struct snd_kcontrol *kcontrol,
    186			struct snd_ctl_elem_value *ucontrol)
    187{
    188	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
    189	struct snd_wm8776 *wm =
    190		&chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
    191	unsigned int idx = kcontrol->private_value;
    192	const struct maya_vol_info *vol = &vol_info[idx];
    193	unsigned int val, data;
    194	int ch, changed = 0;
    195
    196	mutex_lock(&chip->mutex);
    197	for (ch = 0; ch < 2; ch++) {
    198		val = ucontrol->value.integer.value[ch];
    199		if (val > vol->maxval)
    200			val = vol->maxval;
    201		if (val == wm->volumes[idx][ch])
    202			continue;
    203		if (!val)
    204			data = vol->mute;
    205		else
    206			data = (val - 1) + vol->offset;
    207		data |= vol->update;
    208		changed |= wm8776_write_bits(chip->ice, wm, vol->regs[ch],
    209					     vol->mask | vol->update, data);
    210		if (vol->mux_bits[ch])
    211			wm8776_write_bits(chip->ice, wm, WM8776_REG_ADC_MUX,
    212					  vol->mux_bits[ch],
    213					  val ? 0 : vol->mux_bits[ch]);
    214		wm->volumes[idx][ch] = val;
    215	}
    216	mutex_unlock(&chip->mutex);
    217	return changed;
    218}
    219
    220/*
    221 * WM8776 switch controls
    222 */
    223
    224#define COMPOSE_SW_VAL(idx, reg, mask)	((idx) | ((reg) << 8) | ((mask) << 16))
    225#define GET_SW_VAL_IDX(val)	((val) & 0xff)
    226#define GET_SW_VAL_REG(val)	(((val) >> 8) & 0xff)
    227#define GET_SW_VAL_MASK(val)	(((val) >> 16) & 0xff)
    228
    229#define maya_sw_info	snd_ctl_boolean_mono_info
    230
    231static int maya_sw_get(struct snd_kcontrol *kcontrol,
    232		       struct snd_ctl_elem_value *ucontrol)
    233{
    234	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
    235	struct snd_wm8776 *wm =
    236		&chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
    237	unsigned int idx = GET_SW_VAL_IDX(kcontrol->private_value);
    238
    239	ucontrol->value.integer.value[0] = (wm->switch_bits >> idx) & 1;
    240	return 0;
    241}
    242
    243static int maya_sw_put(struct snd_kcontrol *kcontrol,
    244		       struct snd_ctl_elem_value *ucontrol)
    245{
    246	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
    247	struct snd_wm8776 *wm =
    248		&chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
    249	unsigned int idx = GET_SW_VAL_IDX(kcontrol->private_value);
    250	unsigned int mask, val;
    251	int changed;
    252
    253	mutex_lock(&chip->mutex);
    254	mask = 1 << idx;
    255	wm->switch_bits &= ~mask;
    256	val = ucontrol->value.integer.value[0];
    257	if (val)
    258		wm->switch_bits |= mask;
    259	mask = GET_SW_VAL_MASK(kcontrol->private_value);
    260	changed = wm8776_write_bits(chip->ice, wm,
    261				    GET_SW_VAL_REG(kcontrol->private_value),
    262				    mask, val ? mask : 0);
    263	mutex_unlock(&chip->mutex);
    264	return changed;
    265}
    266
    267/*
    268 * GPIO pins (known ones for maya44)
    269 */
    270#define GPIO_PHANTOM_OFF	2
    271#define GPIO_MIC_RELAY		4
    272#define GPIO_SPDIF_IN_INV	5
    273#define GPIO_MUST_BE_0		7
    274
    275/*
    276 * GPIO switch controls
    277 */
    278
    279#define COMPOSE_GPIO_VAL(shift, inv)	((shift) | ((inv) << 8))
    280#define GET_GPIO_VAL_SHIFT(val)		((val) & 0xff)
    281#define GET_GPIO_VAL_INV(val)		(((val) >> 8) & 1)
    282
    283static int maya_set_gpio_bits(struct snd_ice1712 *ice, unsigned int mask,
    284			      unsigned int bits)
    285{
    286	unsigned int data;
    287	data = snd_ice1712_gpio_read(ice);
    288	if ((data & mask) == bits)
    289		return 0;
    290	snd_ice1712_gpio_write(ice, (data & ~mask) | bits);
    291	return 1;
    292}
    293
    294#define maya_gpio_sw_info	snd_ctl_boolean_mono_info
    295
    296static int maya_gpio_sw_get(struct snd_kcontrol *kcontrol,
    297			    struct snd_ctl_elem_value *ucontrol)
    298{
    299	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
    300	unsigned int shift = GET_GPIO_VAL_SHIFT(kcontrol->private_value);
    301	unsigned int val;
    302
    303	val = (snd_ice1712_gpio_read(chip->ice) >> shift) & 1;
    304	if (GET_GPIO_VAL_INV(kcontrol->private_value))
    305		val = !val;
    306	ucontrol->value.integer.value[0] = val;
    307	return 0;
    308}
    309
    310static int maya_gpio_sw_put(struct snd_kcontrol *kcontrol,
    311			    struct snd_ctl_elem_value *ucontrol)
    312{
    313	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
    314	unsigned int shift = GET_GPIO_VAL_SHIFT(kcontrol->private_value);
    315	unsigned int val, mask;
    316	int changed;
    317
    318	mutex_lock(&chip->mutex);
    319	mask = 1 << shift;
    320	val = ucontrol->value.integer.value[0];
    321	if (GET_GPIO_VAL_INV(kcontrol->private_value))
    322		val = !val;
    323	val = val ? mask : 0;
    324	changed = maya_set_gpio_bits(chip->ice, mask, val);
    325	mutex_unlock(&chip->mutex);
    326	return changed;
    327}
    328
    329/*
    330 * capture source selection
    331 */
    332
    333/* known working input slots (0-4) */
    334#define MAYA_LINE_IN	1	/* in-2 */
    335#define MAYA_MIC_IN	3	/* in-4 */
    336
    337static void wm8776_select_input(struct snd_maya44 *chip, int idx, int line)
    338{
    339	wm8776_write_bits(chip->ice, &chip->wm[idx], WM8776_REG_ADC_MUX,
    340			  0x1f, 1 << line);
    341}
    342
    343static int maya_rec_src_info(struct snd_kcontrol *kcontrol,
    344			     struct snd_ctl_elem_info *uinfo)
    345{
    346	static const char * const texts[] = { "Line", "Mic" };
    347
    348	return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
    349}
    350
    351static int maya_rec_src_get(struct snd_kcontrol *kcontrol,
    352			    struct snd_ctl_elem_value *ucontrol)
    353{
    354	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
    355	int sel;
    356
    357	if (snd_ice1712_gpio_read(chip->ice) & (1 << GPIO_MIC_RELAY))
    358		sel = 1;
    359	else
    360		sel = 0;
    361	ucontrol->value.enumerated.item[0] = sel;
    362	return 0;
    363}
    364
    365static int maya_rec_src_put(struct snd_kcontrol *kcontrol,
    366			    struct snd_ctl_elem_value *ucontrol)
    367{
    368	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
    369	int sel = ucontrol->value.enumerated.item[0];
    370	int changed;
    371
    372	mutex_lock(&chip->mutex);
    373	changed = maya_set_gpio_bits(chip->ice, 1 << GPIO_MIC_RELAY,
    374				     sel ? (1 << GPIO_MIC_RELAY) : 0);
    375	wm8776_select_input(chip, 0, sel ? MAYA_MIC_IN : MAYA_LINE_IN);
    376	mutex_unlock(&chip->mutex);
    377	return changed;
    378}
    379
    380/*
    381 * Maya44 routing switch settings have different meanings than the standard
    382 * ice1724 switches as defined in snd_vt1724_pro_route_info (ice1724.c).
    383 */
    384static int maya_pb_route_info(struct snd_kcontrol *kcontrol,
    385			      struct snd_ctl_elem_info *uinfo)
    386{
    387	static const char * const texts[] = {
    388		"PCM Out", /* 0 */
    389		"Input 1", "Input 2", "Input 3", "Input 4"
    390	};
    391
    392	return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
    393}
    394
    395static int maya_pb_route_shift(int idx)
    396{
    397	static const unsigned char shift[10] =
    398		{ 8, 20, 0, 3, 11, 23, 14, 26, 17, 29 };
    399	return shift[idx % 10];
    400}
    401
    402static int maya_pb_route_get(struct snd_kcontrol *kcontrol,
    403			     struct snd_ctl_elem_value *ucontrol)
    404{
    405	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
    406	int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
    407	ucontrol->value.enumerated.item[0] =
    408		snd_ice1724_get_route_val(chip->ice, maya_pb_route_shift(idx));
    409	return 0;
    410}
    411
    412static int maya_pb_route_put(struct snd_kcontrol *kcontrol,
    413			     struct snd_ctl_elem_value *ucontrol)
    414{
    415	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
    416	int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
    417	return snd_ice1724_put_route_val(chip->ice,
    418					 ucontrol->value.enumerated.item[0],
    419					 maya_pb_route_shift(idx));
    420}
    421
    422
    423/*
    424 * controls to be added
    425 */
    426
    427static const struct snd_kcontrol_new maya_controls[] = {
    428	{
    429		.name = "Crossmix Playback Volume",
    430		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    431		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
    432			SNDRV_CTL_ELEM_ACCESS_TLV_READ,
    433		.info = maya_vol_info,
    434		.get = maya_vol_get,
    435		.put = maya_vol_put,
    436		.tlv = { .p = db_scale_hp },
    437		.private_value = WM_VOL_HP,
    438		.count = 2,
    439	},
    440	{
    441		.name = "PCM Playback Volume",
    442		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    443		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
    444			SNDRV_CTL_ELEM_ACCESS_TLV_READ,
    445		.info = maya_vol_info,
    446		.get = maya_vol_get,
    447		.put = maya_vol_put,
    448		.tlv = { .p = db_scale_dac },
    449		.private_value = WM_VOL_DAC,
    450		.count = 2,
    451	},
    452	{
    453		.name = "Line Capture Volume",
    454		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    455		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
    456			SNDRV_CTL_ELEM_ACCESS_TLV_READ,
    457		.info = maya_vol_info,
    458		.get = maya_vol_get,
    459		.put = maya_vol_put,
    460		.tlv = { .p = db_scale_adc },
    461		.private_value = WM_VOL_ADC,
    462		.count = 2,
    463	},
    464	{
    465		.name = "PCM Playback Switch",
    466		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    467		.info = maya_sw_info,
    468		.get = maya_sw_get,
    469		.put = maya_sw_put,
    470		.private_value = COMPOSE_SW_VAL(WM_SW_DAC,
    471						WM8776_REG_OUTPUT_MUX, 0x01),
    472		.count = 2,
    473	},
    474	{
    475		.name = "Bypass Playback Switch",
    476		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    477		.info = maya_sw_info,
    478		.get = maya_sw_get,
    479		.put = maya_sw_put,
    480		.private_value = COMPOSE_SW_VAL(WM_SW_BYPASS,
    481						WM8776_REG_OUTPUT_MUX, 0x04),
    482		.count = 2,
    483	},
    484	{
    485		.name = "Capture Source",
    486		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    487		.info = maya_rec_src_info,
    488		.get = maya_rec_src_get,
    489		.put = maya_rec_src_put,
    490	},
    491	{
    492		.name = "Mic Phantom Power Switch",
    493		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    494		.info = maya_gpio_sw_info,
    495		.get = maya_gpio_sw_get,
    496		.put = maya_gpio_sw_put,
    497		.private_value = COMPOSE_GPIO_VAL(GPIO_PHANTOM_OFF, 1),
    498	},
    499	{
    500		.name = "SPDIF Capture Switch",
    501		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    502		.info = maya_gpio_sw_info,
    503		.get = maya_gpio_sw_get,
    504		.put = maya_gpio_sw_put,
    505		.private_value = COMPOSE_GPIO_VAL(GPIO_SPDIF_IN_INV, 1),
    506	},
    507	{
    508		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    509		.name = "H/W Playback Route",
    510		.info = maya_pb_route_info,
    511		.get = maya_pb_route_get,
    512		.put = maya_pb_route_put,
    513		.count = 4,  /* FIXME: do controls 5-9 have any meaning? */
    514	},
    515};
    516
    517static int maya44_add_controls(struct snd_ice1712 *ice)
    518{
    519	int err, i;
    520
    521	for (i = 0; i < ARRAY_SIZE(maya_controls); i++) {
    522		err = snd_ctl_add(ice->card, snd_ctl_new1(&maya_controls[i],
    523							  ice->spec));
    524		if (err < 0)
    525			return err;
    526	}
    527	return 0;
    528}
    529
    530
    531/*
    532 * initialize a wm8776 chip
    533 */
    534static void wm8776_init(struct snd_ice1712 *ice,
    535			struct snd_wm8776 *wm, unsigned int addr)
    536{
    537	static const unsigned short inits_wm8776[] = {
    538		0x02, 0x100, /* R2: headphone L+R muted + update */
    539		0x05, 0x100, /* R5: DAC output L+R muted + update */
    540		0x06, 0x000, /* R6: DAC output phase normal */
    541		0x07, 0x091, /* R7: DAC enable zero cross detection,
    542				normal output */
    543		0x08, 0x000, /* R8: DAC soft mute off */
    544		0x09, 0x000, /* R9: no deemph, DAC zero detect disabled */
    545		0x0a, 0x022, /* R10: DAC I2C mode, std polarities, 24bit */
    546		0x0b, 0x022, /* R11: ADC I2C mode, std polarities, 24bit,
    547				highpass filter enabled */
    548		0x0c, 0x042, /* R12: ADC+DAC slave, ADC+DAC 44,1kHz */
    549		0x0d, 0x000, /* R13: all power up */
    550		0x0e, 0x100, /* R14: ADC left muted,
    551				enable zero cross detection */
    552		0x0f, 0x100, /* R15: ADC right muted,
    553				enable zero cross detection */
    554			     /* R16: ALC...*/
    555		0x11, 0x000, /* R17: disable ALC */
    556			     /* R18: ALC...*/
    557			     /* R19: noise gate...*/
    558		0x15, 0x000, /* R21: ADC input mux init, mute all inputs */
    559		0x16, 0x001, /* R22: output mux, select DAC */
    560		0xff, 0xff
    561	};
    562
    563	const unsigned short *ptr;
    564	unsigned char reg;
    565	unsigned short data;
    566
    567	wm->addr = addr;
    568	/* enable DAC output; mute bypass, aux & all inputs */
    569	wm->switch_bits = (1 << WM_SW_DAC);
    570
    571	ptr = inits_wm8776;
    572	while (*ptr != 0xff) {
    573		reg = *ptr++;
    574		data = *ptr++;
    575		wm8776_write(ice, wm, reg, data);
    576	}
    577}
    578
    579
    580/*
    581 * change the rate on the WM8776 codecs.
    582 * this assumes that the VT17xx's rate is changed by the calling function.
    583 * NOTE: even though the WM8776's are running in slave mode and rate
    584 * selection is automatic, we need to call snd_wm8776_set_rate() here
    585 * to make sure some flags are set correctly.
    586 */
    587static void set_rate(struct snd_ice1712 *ice, unsigned int rate)
    588{
    589	struct snd_maya44 *chip = ice->spec;
    590	unsigned int ratio, adc_ratio, val;
    591	int i;
    592
    593	switch (rate) {
    594	case 192000:
    595		ratio = WM8776_CLOCK_RATIO_128FS;
    596		break;
    597	case 176400:
    598		ratio = WM8776_CLOCK_RATIO_128FS;
    599		break;
    600	case 96000:
    601		ratio = WM8776_CLOCK_RATIO_256FS;
    602		break;
    603	case 88200:
    604		ratio = WM8776_CLOCK_RATIO_384FS;
    605		break;
    606	case 48000:
    607		ratio = WM8776_CLOCK_RATIO_512FS;
    608		break;
    609	case 44100:
    610		ratio = WM8776_CLOCK_RATIO_512FS;
    611		break;
    612	case 32000:
    613		ratio = WM8776_CLOCK_RATIO_768FS;
    614		break;
    615	case 0:
    616		/* no hint - S/PDIF input is master, simply return */
    617		return;
    618	default:
    619		snd_BUG();
    620		return;
    621	}
    622
    623	/*
    624	 * this currently sets the same rate for ADC and DAC, but limits
    625	 * ADC rate to 256X (96kHz). For 256X mode (96kHz), this sets ADC
    626	 * oversampling to 64x, as recommended by WM8776 datasheet.
    627	 * Setting the rate is not really necessary in slave mode.
    628	 */
    629	adc_ratio = ratio;
    630	if (adc_ratio < WM8776_CLOCK_RATIO_256FS)
    631		adc_ratio = WM8776_CLOCK_RATIO_256FS;
    632
    633	val = adc_ratio;
    634	if (adc_ratio == WM8776_CLOCK_RATIO_256FS)
    635		val |= 8;
    636	val |= ratio << 4;
    637
    638	mutex_lock(&chip->mutex);
    639	for (i = 0; i < 2; i++)
    640		wm8776_write_bits(ice, &chip->wm[i],
    641				  WM8776_REG_MASTER_MODE_CONTROL,
    642				  0x180, val);
    643	mutex_unlock(&chip->mutex);
    644}
    645
    646/*
    647 * supported sample rates (to override the default one)
    648 */
    649
    650static const unsigned int rates[] = {
    651	32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000
    652};
    653
    654/* playback rates: 32..192 kHz */
    655static const struct snd_pcm_hw_constraint_list dac_rates = {
    656	.count = ARRAY_SIZE(rates),
    657	.list = rates,
    658	.mask = 0
    659};
    660
    661
    662/*
    663 * chip addresses on I2C bus
    664 */
    665static const unsigned char wm8776_addr[2] = {
    666	0x34, 0x36, /* codec 0 & 1 */
    667};
    668
    669/*
    670 * initialize the chip
    671 */
    672static int maya44_init(struct snd_ice1712 *ice)
    673{
    674	int i;
    675	struct snd_maya44 *chip;
    676
    677	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
    678	if (!chip)
    679		return -ENOMEM;
    680	mutex_init(&chip->mutex);
    681	chip->ice = ice;
    682	ice->spec = chip;
    683
    684	/* initialise codecs */
    685	ice->num_total_dacs = 4;
    686	ice->num_total_adcs = 4;
    687	ice->akm_codecs = 0;
    688
    689	for (i = 0; i < 2; i++) {
    690		wm8776_init(ice, &chip->wm[i], wm8776_addr[i]);
    691		wm8776_select_input(chip, i, MAYA_LINE_IN);
    692	}
    693
    694	/* set card specific rates */
    695	ice->hw_rates = &dac_rates;
    696
    697	/* register change rate notifier */
    698	ice->gpio.set_pro_rate = set_rate;
    699
    700	/* RDMA1 (2nd input channel) is used for ADC by default */
    701	ice->force_rdma1 = 1;
    702
    703	/* have an own routing control */
    704	ice->own_routing = 1;
    705
    706	return 0;
    707}
    708
    709
    710/*
    711 * Maya44 boards don't provide the EEPROM data except for the vendor IDs.
    712 * hence the driver needs to sets up it properly.
    713 */
    714
    715static const unsigned char maya44_eeprom[] = {
    716	[ICE_EEP2_SYSCONF]     = 0x45,
    717		/* clock xin1=49.152MHz, mpu401, 2 stereo ADCs+DACs */
    718	[ICE_EEP2_ACLINK]      = 0x80,
    719		/* I2S */
    720	[ICE_EEP2_I2S]         = 0xf8,
    721		/* vol, 96k, 24bit, 192k */
    722	[ICE_EEP2_SPDIF]       = 0xc3,
    723		/* enable spdif out, spdif out supp, spdif-in, ext spdif out */
    724	[ICE_EEP2_GPIO_DIR]    = 0xff,
    725	[ICE_EEP2_GPIO_DIR1]   = 0xff,
    726	[ICE_EEP2_GPIO_DIR2]   = 0xff,
    727	[ICE_EEP2_GPIO_MASK]   = 0/*0x9f*/,
    728	[ICE_EEP2_GPIO_MASK1]  = 0/*0xff*/,
    729	[ICE_EEP2_GPIO_MASK2]  = 0/*0x7f*/,
    730	[ICE_EEP2_GPIO_STATE]  = (1 << GPIO_PHANTOM_OFF) |
    731			(1 << GPIO_SPDIF_IN_INV),
    732	[ICE_EEP2_GPIO_STATE1] = 0x00,
    733	[ICE_EEP2_GPIO_STATE2] = 0x00,
    734};
    735
    736/* entry point */
    737struct snd_ice1712_card_info snd_vt1724_maya44_cards[] = {
    738	{
    739		.subvendor = VT1724_SUBDEVICE_MAYA44,
    740		.name = "ESI Maya44",
    741		.model = "maya44",
    742		.chip_init = maya44_init,
    743		.build_controls = maya44_add_controls,
    744		.eeprom_size = sizeof(maya44_eeprom),
    745		.eeprom_data = maya44_eeprom,
    746	},
    747	{ } /* terminator */
    748};