brintos

brintos / linux-shallow public Read only

0
0
Text · 31.3 KiB · 9aa12a6 Raw
1266 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *   ALSA driver for ICEnsemble VT1724 (Envy24HT)4 *5 *   Lowlevel functions for Audiotrak Prodigy 7.1 Hifi6 *   based on pontis.c7 *8 *      Copyright (c) 2007 Julian Scheel <julian@jusst.de>9 *      Copyright (c) 2007 allank10 *      Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>11 */12 13 14#include <linux/delay.h>15#include <linux/interrupt.h>16#include <linux/init.h>17#include <linux/slab.h>18#include <linux/mutex.h>19 20#include <sound/core.h>21#include <sound/info.h>22#include <sound/tlv.h>23 24#include "ice1712.h"25#include "envy24ht.h"26#include "prodigy_hifi.h"27 28struct prodigy_hifi_spec {29	unsigned short master[2];30	unsigned short vol[8];31};32 33/* I2C addresses */34#define WM_DEV		0x3435 36/* WM8776 registers */37#define WM_HP_ATTEN_L		0x00	/* headphone left attenuation */38#define WM_HP_ATTEN_R		0x01	/* headphone left attenuation */39#define WM_HP_MASTER		0x02	/* headphone master (both channels),40						override LLR */41#define WM_DAC_ATTEN_L		0x03	/* digital left attenuation */42#define WM_DAC_ATTEN_R		0x0443#define WM_DAC_MASTER		0x0544#define WM_PHASE_SWAP		0x06	/* DAC phase swap */45#define WM_DAC_CTRL1		0x0746#define WM_DAC_MUTE		0x0847#define WM_DAC_CTRL2		0x0948#define WM_DAC_INT		0x0a49#define WM_ADC_INT		0x0b50#define WM_MASTER_CTRL		0x0c51#define WM_POWERDOWN		0x0d52#define WM_ADC_ATTEN_L		0x0e53#define WM_ADC_ATTEN_R		0x0f54#define WM_ALC_CTRL1		0x1055#define WM_ALC_CTRL2		0x1156#define WM_ALC_CTRL3		0x1257#define WM_NOISE_GATE		0x1358#define WM_LIMITER		0x1459#define WM_ADC_MUX		0x1560#define WM_OUT_MUX		0x1661#define WM_RESET		0x1762 63/* Analog Recording Source :- Mic, LineIn, CD/Video, */64 65/* implement capture source select control for WM8776 */66 67#define WM_AIN1 "AIN1"68#define WM_AIN2 "AIN2"69#define WM_AIN3 "AIN3"70#define WM_AIN4 "AIN4"71#define WM_AIN5 "AIN5"72 73/* GPIO pins of envy24ht connected to wm8766 */74#define WM8766_SPI_CLK	 (1<<17) /* CLK, Pin97 on ICE1724 */75#define WM8766_SPI_MD	  (1<<16) /* DATA VT1724 -> WM8766, Pin96 */76#define WM8766_SPI_ML	  (1<<18) /* Latch, Pin98 */77 78/* WM8766 registers */79#define WM8766_DAC_CTRL	 0x02   /* DAC Control */80#define WM8766_INT_CTRL	 0x03   /* Interface Control */81#define WM8766_DAC_CTRL2	0x0982#define WM8766_DAC_CTRL3	0x0a83#define WM8766_RESET	    0x1f84#define WM8766_LDA1	     0x0085#define WM8766_LDA2	     0x0486#define WM8766_LDA3	     0x0687#define WM8766_RDA1	     0x0188#define WM8766_RDA2	     0x0589#define WM8766_RDA3	     0x0790#define WM8766_MUTE1	    0x0C91#define WM8766_MUTE2	    0x0F92 93 94/*95 * Prodigy HD296 */97#define AK4396_ADDR    0x0098#define AK4396_CSN    (1 << 8)    /* CSN->GPIO8, pin 75 */99#define AK4396_CCLK   (1 << 9)    /* CCLK->GPIO9, pin 76 */100#define AK4396_CDTI   (1 << 10)   /* CDTI->GPIO10, pin 77 */101 102/* ak4396 registers */103#define AK4396_CTRL1	    0x00104#define AK4396_CTRL2	    0x01105#define AK4396_CTRL3	    0x02106#define AK4396_LCH_ATT	  0x03107#define AK4396_RCH_ATT	  0x04108 109 110/*111 * get the current register value of WM codec112 */113static unsigned short wm_get(struct snd_ice1712 *ice, int reg)114{115	reg <<= 1;116	return ((unsigned short)ice->akm[0].images[reg] << 8) |117		ice->akm[0].images[reg + 1];118}119 120/*121 * set the register value of WM codec and remember it122 */123static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)124{125	unsigned short cval;126	cval = (reg << 9) | val;127	snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff);128}129 130static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)131{132	wm_put_nocache(ice, reg, val);133	reg <<= 1;134	ice->akm[0].images[reg] = val >> 8;135	ice->akm[0].images[reg + 1] = val;136}137 138/*139 * write data in the SPI mode140 */141 142static void set_gpio_bit(struct snd_ice1712 *ice, unsigned int bit, int val)143{144	unsigned int tmp = snd_ice1712_gpio_read(ice);145	if (val)146		tmp |= bit;147	else148		tmp &= ~bit;149	snd_ice1712_gpio_write(ice, tmp);150}151 152/*153 * SPI implementation for WM8766 codec - only writing supported, no readback154 */155 156static void wm8766_spi_send_word(struct snd_ice1712 *ice, unsigned int data)157{158	int i;159	for (i = 0; i < 16; i++) {160		set_gpio_bit(ice, WM8766_SPI_CLK, 0);161		udelay(1);162		set_gpio_bit(ice, WM8766_SPI_MD, data & 0x8000);163		udelay(1);164		set_gpio_bit(ice, WM8766_SPI_CLK, 1);165		udelay(1);166		data <<= 1;167	}168}169 170static void wm8766_spi_write(struct snd_ice1712 *ice, unsigned int reg,171			     unsigned int data)172{173	unsigned int block;174 175	snd_ice1712_gpio_set_dir(ice, WM8766_SPI_MD|176					WM8766_SPI_CLK|WM8766_SPI_ML);177	snd_ice1712_gpio_set_mask(ice, ~(WM8766_SPI_MD|178					WM8766_SPI_CLK|WM8766_SPI_ML));179	/* latch must be low when writing */180	set_gpio_bit(ice, WM8766_SPI_ML, 0);181	block = (reg << 9) | (data & 0x1ff);182	wm8766_spi_send_word(ice, block); /* REGISTER ADDRESS */183	/* release latch */184	set_gpio_bit(ice, WM8766_SPI_ML, 1);185	udelay(1);186	/* restore */187	snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);188	snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);189}190 191 192/*193 * serial interface for ak4396 - only writing supported, no readback194 */195 196static void ak4396_send_word(struct snd_ice1712 *ice, unsigned int data)197{198	int i;199	for (i = 0; i < 16; i++) {200		set_gpio_bit(ice, AK4396_CCLK, 0);201		udelay(1);202		set_gpio_bit(ice, AK4396_CDTI, data & 0x8000);203		udelay(1);204		set_gpio_bit(ice, AK4396_CCLK, 1);205		udelay(1);206		data <<= 1;207	}208}209 210static void ak4396_write(struct snd_ice1712 *ice, unsigned int reg,211			 unsigned int data)212{213	unsigned int block;214 215	snd_ice1712_gpio_set_dir(ice, AK4396_CSN|AK4396_CCLK|AK4396_CDTI);216	snd_ice1712_gpio_set_mask(ice, ~(AK4396_CSN|AK4396_CCLK|AK4396_CDTI));217	/* latch must be low when writing */218	set_gpio_bit(ice, AK4396_CSN, 0); 219	block =  ((AK4396_ADDR & 0x03) << 14) | (1 << 13) |220			((reg & 0x1f) << 8) | (data & 0xff);221	ak4396_send_word(ice, block); /* REGISTER ADDRESS */222	/* release latch */223	set_gpio_bit(ice, AK4396_CSN, 1);224	udelay(1);225	/* restore */226	snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);227	snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);228}229 230 231/*232 * ak4396 mixers233 */234 235 236 237/*238 * DAC volume attenuation mixer control (-64dB to 0dB)239 */240 241static int ak4396_dac_vol_info(struct snd_kcontrol *kcontrol,242			       struct snd_ctl_elem_info *uinfo)243{244	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;245	uinfo->count = 2;246	uinfo->value.integer.min = 0;   /* mute */247	uinfo->value.integer.max = 0xFF; /* linear */248	return 0;249}250 251static int ak4396_dac_vol_get(struct snd_kcontrol *kcontrol,252			      struct snd_ctl_elem_value *ucontrol)253{254	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);255	struct prodigy_hifi_spec *spec = ice->spec;256	int i;257	258	for (i = 0; i < 2; i++)259		ucontrol->value.integer.value[i] = spec->vol[i];260 261	return 0;262}263 264static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)265{266	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);267	struct prodigy_hifi_spec *spec = ice->spec;268	int i;269	int change = 0;270	271	mutex_lock(&ice->gpio_mutex);272	for (i = 0; i < 2; i++) {273		if (ucontrol->value.integer.value[i] != spec->vol[i]) {274			spec->vol[i] = ucontrol->value.integer.value[i];275			ak4396_write(ice, AK4396_LCH_ATT + i,276				     spec->vol[i] & 0xff);277			change = 1;278		}279	}280	mutex_unlock(&ice->gpio_mutex);281	return change;282}283 284static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);285static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);286 287static const struct snd_kcontrol_new prodigy_hd2_controls[] = {288    {289	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,290	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |291		SNDRV_CTL_ELEM_ACCESS_TLV_READ),292	.name = "Front Playback Volume",293	.info = ak4396_dac_vol_info,294	.get = ak4396_dac_vol_get,295	.put = ak4396_dac_vol_put,296	.tlv = { .p = ak4396_db_scale },297    },298};299 300 301/* --------------- */302 303#define WM_VOL_MAX	255304#define WM_VOL_MUTE	0x8000305 306 307#define DAC_0dB	0xff308#define DAC_RES	128309#define DAC_MIN	(DAC_0dB - DAC_RES)310 311 312static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index,313		       unsigned short vol, unsigned short master)314{315	unsigned char nvol;316	317	if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))318		nvol = 0;319	else {320		nvol = (((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 128)321				& WM_VOL_MAX;322		nvol = (nvol ? (nvol + DAC_MIN) : 0) & 0xff;323	}324	325	wm_put(ice, index, nvol);326	wm_put_nocache(ice, index, 0x100 | nvol);327}328 329static void wm8766_set_vol(struct snd_ice1712 *ice, unsigned int index,330			   unsigned short vol, unsigned short master)331{332	unsigned char nvol;333	334	if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))335		nvol = 0;336	else {337		nvol = (((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 128)338				& WM_VOL_MAX;339		nvol = (nvol ? (nvol + DAC_MIN) : 0) & 0xff;340	}341 342	wm8766_spi_write(ice, index, (0x0100 | nvol));343}344 345 346/*347 * DAC volume attenuation mixer control (-64dB to 0dB)348 */349 350static int wm_dac_vol_info(struct snd_kcontrol *kcontrol,351			   struct snd_ctl_elem_info *uinfo)352{353	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;354	uinfo->count = 2;355	uinfo->value.integer.min = 0;	/* mute */356	uinfo->value.integer.max = DAC_RES;	/* 0dB, 0.5dB step */357	return 0;358}359 360static int wm_dac_vol_get(struct snd_kcontrol *kcontrol,361			  struct snd_ctl_elem_value *ucontrol)362{363	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);364	struct prodigy_hifi_spec *spec = ice->spec;365	int i;366 367	for (i = 0; i < 2; i++)368		ucontrol->value.integer.value[i] =369			spec->vol[2 + i] & ~WM_VOL_MUTE;370	return 0;371}372 373static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)374{375	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);376	struct prodigy_hifi_spec *spec = ice->spec;377	int i, idx, change = 0;378 379	mutex_lock(&ice->gpio_mutex);380	for (i = 0; i < 2; i++) {381		if (ucontrol->value.integer.value[i] != spec->vol[2 + i]) {382			idx = WM_DAC_ATTEN_L + i;383			spec->vol[2 + i] &= WM_VOL_MUTE;384			spec->vol[2 + i] |= ucontrol->value.integer.value[i];385			wm_set_vol(ice, idx, spec->vol[2 + i], spec->master[i]);386			change = 1;387		}388	}389	mutex_unlock(&ice->gpio_mutex);390	return change;391}392 393 394/*395 * WM8766 DAC volume attenuation mixer control396 */397static int wm8766_vol_info(struct snd_kcontrol *kcontrol,398			   struct snd_ctl_elem_info *uinfo)399{400	int voices = kcontrol->private_value >> 8;401	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;402	uinfo->count = voices;403	uinfo->value.integer.min = 0;		/* mute */404	uinfo->value.integer.max = DAC_RES;	/* 0dB */405	return 0;406}407 408static int wm8766_vol_get(struct snd_kcontrol *kcontrol,409			  struct snd_ctl_elem_value *ucontrol)410{411	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);412	struct prodigy_hifi_spec *spec = ice->spec;413	int i, ofs, voices;414 415	voices = kcontrol->private_value >> 8;416	ofs = kcontrol->private_value & 0xff;417	for (i = 0; i < voices; i++)418		ucontrol->value.integer.value[i] = spec->vol[ofs + i];419	return 0;420}421 422static int wm8766_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)423{424	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);425	struct prodigy_hifi_spec *spec = ice->spec;426	int i, idx, ofs, voices;427	int change = 0;428 429	voices = kcontrol->private_value >> 8;430	ofs = kcontrol->private_value & 0xff;431	mutex_lock(&ice->gpio_mutex);432	for (i = 0; i < voices; i++) {433		if (ucontrol->value.integer.value[i] != spec->vol[ofs + i]) {434			idx = WM8766_LDA1 + ofs + i;435			spec->vol[ofs + i] &= WM_VOL_MUTE;436			spec->vol[ofs + i] |= ucontrol->value.integer.value[i];437			wm8766_set_vol(ice, idx,438				       spec->vol[ofs + i], spec->master[i]);439			change = 1;440		}441	}442	mutex_unlock(&ice->gpio_mutex);443	return change;444}445 446/*447 * Master volume attenuation mixer control / applied to WM8776+WM8766448 */449static int wm_master_vol_info(struct snd_kcontrol *kcontrol,450			      struct snd_ctl_elem_info *uinfo)451{452	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;453	uinfo->count = 2;454	uinfo->value.integer.min = 0;455	uinfo->value.integer.max = DAC_RES;456	return 0;457}458 459static int wm_master_vol_get(struct snd_kcontrol *kcontrol,460			     struct snd_ctl_elem_value *ucontrol)461{462	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);463	struct prodigy_hifi_spec *spec = ice->spec;464	int i;465	for (i = 0; i < 2; i++)466		ucontrol->value.integer.value[i] = spec->master[i];467	return 0;468}469 470static int wm_master_vol_put(struct snd_kcontrol *kcontrol,471			     struct snd_ctl_elem_value *ucontrol)472{473	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);474	struct prodigy_hifi_spec *spec = ice->spec;475	int ch, change = 0;476 477	mutex_lock(&ice->gpio_mutex);478	for (ch = 0; ch < 2; ch++) {479		if (ucontrol->value.integer.value[ch] != spec->master[ch]) {480			spec->master[ch] = ucontrol->value.integer.value[ch];481 482			/* Apply to front DAC */483			wm_set_vol(ice, WM_DAC_ATTEN_L + ch,484				   spec->vol[2 + ch], spec->master[ch]);485 486			wm8766_set_vol(ice, WM8766_LDA1 + ch,487				       spec->vol[0 + ch], spec->master[ch]);488 489			wm8766_set_vol(ice, WM8766_LDA2 + ch,490				       spec->vol[4 + ch], spec->master[ch]);491 492			wm8766_set_vol(ice, WM8766_LDA3 + ch,493				       spec->vol[6 + ch], spec->master[ch]);494			change = 1;495		}496	}497	mutex_unlock(&ice->gpio_mutex);	498	return change;499}500 501 502/* KONSTI */503 504static int wm_adc_mux_enum_info(struct snd_kcontrol *kcontrol,505				struct snd_ctl_elem_info *uinfo)506{507	static const char * const texts[32] = {508		"NULL", WM_AIN1, WM_AIN2, WM_AIN1 "+" WM_AIN2,509		WM_AIN3, WM_AIN1 "+" WM_AIN3, WM_AIN2 "+" WM_AIN3,510		WM_AIN1 "+" WM_AIN2 "+" WM_AIN3,511		WM_AIN4, WM_AIN1 "+" WM_AIN4, WM_AIN2 "+" WM_AIN4,512		WM_AIN1 "+" WM_AIN2 "+" WM_AIN4,513		WM_AIN3 "+" WM_AIN4, WM_AIN1 "+" WM_AIN3 "+" WM_AIN4,514		WM_AIN2 "+" WM_AIN3 "+" WM_AIN4,515		WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN4,516		WM_AIN5, WM_AIN1 "+" WM_AIN5, WM_AIN2 "+" WM_AIN5,517		WM_AIN1 "+" WM_AIN2 "+" WM_AIN5,518		WM_AIN3 "+" WM_AIN5, WM_AIN1 "+" WM_AIN3 "+" WM_AIN5,519		WM_AIN2 "+" WM_AIN3 "+" WM_AIN5,520		WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN5,521		WM_AIN4 "+" WM_AIN5, WM_AIN1 "+" WM_AIN4 "+" WM_AIN5,522		WM_AIN2 "+" WM_AIN4 "+" WM_AIN5,523		WM_AIN1 "+" WM_AIN2 "+" WM_AIN4 "+" WM_AIN5,524		WM_AIN3 "+" WM_AIN4 "+" WM_AIN5,525		WM_AIN1 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5,526		WM_AIN2 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5,527		WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5528	};529 530	return snd_ctl_enum_info(uinfo, 1, 32, texts);531}532 533static int wm_adc_mux_enum_get(struct snd_kcontrol *kcontrol,534			       struct snd_ctl_elem_value *ucontrol)535{536	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);537 538	mutex_lock(&ice->gpio_mutex);539	ucontrol->value.enumerated.item[0] = wm_get(ice, WM_ADC_MUX) & 0x1f;540	mutex_unlock(&ice->gpio_mutex);541	return 0;542}543 544static int wm_adc_mux_enum_put(struct snd_kcontrol *kcontrol,545			       struct snd_ctl_elem_value *ucontrol)546{547	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);548	unsigned short oval, nval;549	int change = 0;550 551	mutex_lock(&ice->gpio_mutex);552	oval = wm_get(ice, WM_ADC_MUX);553	nval = (oval & 0xe0) | ucontrol->value.enumerated.item[0];554	if (nval != oval) {555		wm_put(ice, WM_ADC_MUX, nval);556		change = 1;557	}558	mutex_unlock(&ice->gpio_mutex);559	return change;560}561 562/* KONSTI */563 564/*565 * ADC gain mixer control (-64dB to 0dB)566 */567 568#define ADC_0dB	0xcf569#define ADC_RES	128570#define ADC_MIN	(ADC_0dB - ADC_RES)571 572static int wm_adc_vol_info(struct snd_kcontrol *kcontrol,573			   struct snd_ctl_elem_info *uinfo)574{575	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;576	uinfo->count = 2;577	uinfo->value.integer.min = 0;	/* mute (-64dB) */578	uinfo->value.integer.max = ADC_RES;	/* 0dB, 0.5dB step */579	return 0;580}581 582static int wm_adc_vol_get(struct snd_kcontrol *kcontrol,583			  struct snd_ctl_elem_value *ucontrol)584{585	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);586	unsigned short val;587	int i;588 589	mutex_lock(&ice->gpio_mutex);590	for (i = 0; i < 2; i++) {591		val = wm_get(ice, WM_ADC_ATTEN_L + i) & 0xff;592		val = val > ADC_MIN ? (val - ADC_MIN) : 0;593		ucontrol->value.integer.value[i] = val;594	}595	mutex_unlock(&ice->gpio_mutex);596	return 0;597}598 599static int wm_adc_vol_put(struct snd_kcontrol *kcontrol,600			  struct snd_ctl_elem_value *ucontrol)601{602	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);603	unsigned short ovol, nvol;604	int i, idx, change = 0;605 606	mutex_lock(&ice->gpio_mutex);607	for (i = 0; i < 2; i++) {608		nvol = ucontrol->value.integer.value[i];609		nvol = nvol ? (nvol + ADC_MIN) : 0;610		idx  = WM_ADC_ATTEN_L + i;611		ovol = wm_get(ice, idx) & 0xff;612		if (ovol != nvol) {613			wm_put(ice, idx, nvol);614			change = 1;615		}616	}617	mutex_unlock(&ice->gpio_mutex);618	return change;619}620 621/*622 * ADC input mux mixer control623 */624#define wm_adc_mux_info		snd_ctl_boolean_mono_info625 626static int wm_adc_mux_get(struct snd_kcontrol *kcontrol,627			  struct snd_ctl_elem_value *ucontrol)628{629	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);630	int bit = kcontrol->private_value;631 632	mutex_lock(&ice->gpio_mutex);633	ucontrol->value.integer.value[0] =634		(wm_get(ice, WM_ADC_MUX) & (1 << bit)) ? 1 : 0;635	mutex_unlock(&ice->gpio_mutex);636	return 0;637}638 639static int wm_adc_mux_put(struct snd_kcontrol *kcontrol,640			  struct snd_ctl_elem_value *ucontrol)641{642	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);643	int bit = kcontrol->private_value;644	unsigned short oval, nval;645	int change;646 647	mutex_lock(&ice->gpio_mutex);648	nval = oval = wm_get(ice, WM_ADC_MUX);649	if (ucontrol->value.integer.value[0])650		nval |= (1 << bit);651	else652		nval &= ~(1 << bit);653	change = nval != oval;654	if (change) {655		wm_put(ice, WM_ADC_MUX, nval);656	}657	mutex_unlock(&ice->gpio_mutex);658	return 0;659}660 661/*662 * Analog bypass (In -> Out)663 */664#define wm_bypass_info		snd_ctl_boolean_mono_info665 666static int wm_bypass_get(struct snd_kcontrol *kcontrol,667			 struct snd_ctl_elem_value *ucontrol)668{669	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);670 671	mutex_lock(&ice->gpio_mutex);672	ucontrol->value.integer.value[0] =673		(wm_get(ice, WM_OUT_MUX) & 0x04) ? 1 : 0;674	mutex_unlock(&ice->gpio_mutex);675	return 0;676}677 678static int wm_bypass_put(struct snd_kcontrol *kcontrol,679			 struct snd_ctl_elem_value *ucontrol)680{681	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);682	unsigned short val, oval;683	int change = 0;684 685	mutex_lock(&ice->gpio_mutex);686	val = oval = wm_get(ice, WM_OUT_MUX);687	if (ucontrol->value.integer.value[0])688		val |= 0x04;689	else690		val &= ~0x04;691	if (val != oval) {692		wm_put(ice, WM_OUT_MUX, val);693		change = 1;694	}695	mutex_unlock(&ice->gpio_mutex);696	return change;697}698 699/*700 * Left/Right swap701 */702#define wm_chswap_info		snd_ctl_boolean_mono_info703 704static int wm_chswap_get(struct snd_kcontrol *kcontrol,705			 struct snd_ctl_elem_value *ucontrol)706{707	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);708 709	mutex_lock(&ice->gpio_mutex);710	ucontrol->value.integer.value[0] =711			(wm_get(ice, WM_DAC_CTRL1) & 0xf0) != 0x90;712	mutex_unlock(&ice->gpio_mutex);713	return 0;714}715 716static int wm_chswap_put(struct snd_kcontrol *kcontrol,717			 struct snd_ctl_elem_value *ucontrol)718{719	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);720	unsigned short val, oval;721	int change = 0;722 723	mutex_lock(&ice->gpio_mutex);724	oval = wm_get(ice, WM_DAC_CTRL1);725	val = oval & 0x0f;726	if (ucontrol->value.integer.value[0])727		val |= 0x60;728	else729		val |= 0x90;730	if (val != oval) {731		wm_put(ice, WM_DAC_CTRL1, val);732		wm_put_nocache(ice, WM_DAC_CTRL1, val);733		change = 1;734	}735	mutex_unlock(&ice->gpio_mutex);736	return change;737}738 739 740/*741 * mixers742 */743 744static const struct snd_kcontrol_new prodigy_hifi_controls[] = {745	{746		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,747		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |748			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),749		.name = "Master Playback Volume",750		.info = wm_master_vol_info,751		.get = wm_master_vol_get,752		.put = wm_master_vol_put,753		.tlv = { .p = db_scale_wm_dac }754	},755	{756		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,757		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |758			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),759		.name = "Front Playback Volume",760		.info = wm_dac_vol_info,761		.get = wm_dac_vol_get,762		.put = wm_dac_vol_put,763		.tlv = { .p = db_scale_wm_dac },764	},765	{766		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,767		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |768			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),769		.name = "Rear Playback Volume",770		.info = wm8766_vol_info,771		.get = wm8766_vol_get,772		.put = wm8766_vol_put,773		.private_value = (2 << 8) | 0,774		.tlv = { .p = db_scale_wm_dac },775	},776	{777		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,778		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |779			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),780		.name = "Center Playback Volume",781		.info = wm8766_vol_info,782		.get = wm8766_vol_get,783		.put = wm8766_vol_put,784		.private_value = (1 << 8) | 4,785		.tlv = { .p = db_scale_wm_dac }786	},787	{788		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,789		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |790			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),791		.name = "LFE Playback Volume",792		.info = wm8766_vol_info,793		.get = wm8766_vol_get,794		.put = wm8766_vol_put,795		.private_value = (1 << 8) | 5,796		.tlv = { .p = db_scale_wm_dac }797	},798	{799		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,800		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |801			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),802		.name = "Side Playback Volume",803		.info = wm8766_vol_info,804		.get = wm8766_vol_get,805		.put = wm8766_vol_put,806		.private_value = (2 << 8) | 6,807		.tlv = { .p = db_scale_wm_dac },808	},809	{810		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,811		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |812			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),813		.name = "Capture Volume",814		.info = wm_adc_vol_info,815		.get = wm_adc_vol_get,816		.put = wm_adc_vol_put,817		.tlv = { .p = db_scale_wm_dac },818	},819	{820		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,821		.name = "CD Capture Switch",822		.info = wm_adc_mux_info,823		.get = wm_adc_mux_get,824		.put = wm_adc_mux_put,825		.private_value = 0,826	},827	{828		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,829		.name = "Line Capture Switch",830		.info = wm_adc_mux_info,831		.get = wm_adc_mux_get,832		.put = wm_adc_mux_put,833		.private_value = 1,834	},835	{836		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,837		.name = "Analog Bypass Switch",838		.info = wm_bypass_info,839		.get = wm_bypass_get,840		.put = wm_bypass_put,841	},842	{843		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,844		.name = "Swap Output Channels",845		.info = wm_chswap_info,846		.get = wm_chswap_get,847		.put = wm_chswap_put,848	},849	{850		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,851		.name = "Analog Capture Source",852		.info = wm_adc_mux_enum_info,853		.get = wm_adc_mux_enum_get,854		.put = wm_adc_mux_enum_put,855	},856};857 858/*859 * WM codec registers860 */861static void wm_proc_regs_write(struct snd_info_entry *entry,862			       struct snd_info_buffer *buffer)863{864	struct snd_ice1712 *ice = entry->private_data;865	char line[64];866	unsigned int reg, val;867	mutex_lock(&ice->gpio_mutex);868	while (!snd_info_get_line(buffer, line, sizeof(line))) {869		if (sscanf(line, "%x %x", &reg, &val) != 2)870			continue;871		if (reg <= 0x17 && val <= 0xffff)872			wm_put(ice, reg, val);873	}874	mutex_unlock(&ice->gpio_mutex);875}876 877static void wm_proc_regs_read(struct snd_info_entry *entry,878			      struct snd_info_buffer *buffer)879{880	struct snd_ice1712 *ice = entry->private_data;881	int reg, val;882 883	mutex_lock(&ice->gpio_mutex);884	for (reg = 0; reg <= 0x17; reg++) {885		val = wm_get(ice, reg);886		snd_iprintf(buffer, "%02x = %04x\n", reg, val);887	}888	mutex_unlock(&ice->gpio_mutex);889}890 891static void wm_proc_init(struct snd_ice1712 *ice)892{893	snd_card_rw_proc_new(ice->card, "wm_codec", ice, wm_proc_regs_read,894			     wm_proc_regs_write);895}896 897static int prodigy_hifi_add_controls(struct snd_ice1712 *ice)898{899	unsigned int i;900	int err;901 902	for (i = 0; i < ARRAY_SIZE(prodigy_hifi_controls); i++) {903		err = snd_ctl_add(ice->card,904				  snd_ctl_new1(&prodigy_hifi_controls[i], ice));905		if (err < 0)906			return err;907	}908 909	wm_proc_init(ice);910 911	return 0;912}913 914static int prodigy_hd2_add_controls(struct snd_ice1712 *ice)915{916	unsigned int i;917	int err;918 919	for (i = 0; i < ARRAY_SIZE(prodigy_hd2_controls); i++) {920		err = snd_ctl_add(ice->card,921				  snd_ctl_new1(&prodigy_hd2_controls[i], ice));922		if (err < 0)923			return err;924	}925 926	wm_proc_init(ice);927 928	return 0;929}930 931static void wm8766_init(struct snd_ice1712 *ice)932{933	static const unsigned short wm8766_inits[] = {934		WM8766_RESET,	   0x0000,935		WM8766_DAC_CTRL,	0x0120,936		WM8766_INT_CTRL,	0x0022, /* I2S Normal Mode, 24 bit */937		WM8766_DAC_CTRL2,       0x0001,938		WM8766_DAC_CTRL3,       0x0080,939		WM8766_LDA1,	    0x0100,940		WM8766_LDA2,	    0x0100,941		WM8766_LDA3,	    0x0100,942		WM8766_RDA1,	    0x0100,943		WM8766_RDA2,	    0x0100,944		WM8766_RDA3,	    0x0100,945		WM8766_MUTE1,	   0x0000,946		WM8766_MUTE2,	   0x0000,947	};948	unsigned int i;949 950	for (i = 0; i < ARRAY_SIZE(wm8766_inits); i += 2)951		wm8766_spi_write(ice, wm8766_inits[i], wm8766_inits[i + 1]);952}953 954static void wm8776_init(struct snd_ice1712 *ice)955{956	static const unsigned short wm8776_inits[] = {957		/* These come first to reduce init pop noise */958		WM_ADC_MUX,	0x0003,	/* ADC mute */959		/* 0x00c0 replaced by 0x0003 */960		961		WM_DAC_MUTE,	0x0001,	/* DAC softmute */962		WM_DAC_CTRL1,	0x0000,	/* DAC mute */963 964		WM_POWERDOWN,	0x0008,	/* All power-up except HP */965		WM_RESET,	0x0000,	/* reset */966	};967	unsigned int i;968 969	for (i = 0; i < ARRAY_SIZE(wm8776_inits); i += 2)970		wm_put(ice, wm8776_inits[i], wm8776_inits[i + 1]);971}972 973#ifdef CONFIG_PM_SLEEP974static int prodigy_hifi_resume(struct snd_ice1712 *ice)975{976	static const unsigned short wm8776_reinit_registers[] = {977		WM_MASTER_CTRL,978		WM_DAC_INT,979		WM_ADC_INT,980		WM_OUT_MUX,981		WM_HP_ATTEN_L,982		WM_HP_ATTEN_R,983		WM_PHASE_SWAP,984		WM_DAC_CTRL2,985		WM_ADC_ATTEN_L,986		WM_ADC_ATTEN_R,987		WM_ALC_CTRL1,988		WM_ALC_CTRL2,989		WM_ALC_CTRL3,990		WM_NOISE_GATE,991		WM_ADC_MUX,992		/* no DAC attenuation here */993	};994	struct prodigy_hifi_spec *spec = ice->spec;995	int i, ch;996 997	mutex_lock(&ice->gpio_mutex);998 999	/* reinitialize WM8776 and re-apply old register values */1000	wm8776_init(ice);1001	schedule_timeout_uninterruptible(1);1002	for (i = 0; i < ARRAY_SIZE(wm8776_reinit_registers); i++)1003		wm_put(ice, wm8776_reinit_registers[i],1004		       wm_get(ice, wm8776_reinit_registers[i]));1005 1006	/* reinitialize WM8766 and re-apply volumes for all DACs */1007	wm8766_init(ice);1008	for (ch = 0; ch < 2; ch++) {1009		wm_set_vol(ice, WM_DAC_ATTEN_L + ch,1010			   spec->vol[2 + ch], spec->master[ch]);1011 1012		wm8766_set_vol(ice, WM8766_LDA1 + ch,1013			       spec->vol[0 + ch], spec->master[ch]);1014 1015		wm8766_set_vol(ice, WM8766_LDA2 + ch,1016			       spec->vol[4 + ch], spec->master[ch]);1017 1018		wm8766_set_vol(ice, WM8766_LDA3 + ch,1019			       spec->vol[6 + ch], spec->master[ch]);1020	}1021 1022	/* unmute WM8776 DAC */1023	wm_put(ice, WM_DAC_MUTE, 0x00);1024	wm_put(ice, WM_DAC_CTRL1, 0x90);1025 1026	mutex_unlock(&ice->gpio_mutex);1027	return 0;1028}1029#endif1030 1031/*1032 * initialize the chip1033 */1034static int prodigy_hifi_init(struct snd_ice1712 *ice)1035{1036	static const unsigned short wm8776_defaults[] = {1037		WM_MASTER_CTRL,  0x0022, /* 256fs, slave mode */1038		WM_DAC_INT,	0x0022,	/* I2S, normal polarity, 24bit */1039		WM_ADC_INT,	0x0022,	/* I2S, normal polarity, 24bit */1040		WM_DAC_CTRL1,	0x0090,	/* DAC L/R */1041		WM_OUT_MUX,	0x0001,	/* OUT DAC */1042		WM_HP_ATTEN_L,	0x0179,	/* HP 0dB */1043		WM_HP_ATTEN_R,	0x0179,	/* HP 0dB */1044		WM_DAC_ATTEN_L,	0x0000,	/* DAC 0dB */1045		WM_DAC_ATTEN_L,	0x0100,	/* DAC 0dB */1046		WM_DAC_ATTEN_R,	0x0000,	/* DAC 0dB */1047		WM_DAC_ATTEN_R,	0x0100,	/* DAC 0dB */1048		WM_PHASE_SWAP,	0x0000,	/* phase normal */1049#if 01050		WM_DAC_MASTER,	0x0100,	/* DAC master muted */1051#endif1052		WM_DAC_CTRL2,	0x0000,	/* no deemphasis, no ZFLG */1053		WM_ADC_ATTEN_L,	0x0000,	/* ADC muted */1054		WM_ADC_ATTEN_R,	0x0000,	/* ADC muted */1055#if 11056		WM_ALC_CTRL1,	0x007b,	/* */1057		WM_ALC_CTRL2,	0x0000,	/* */1058		WM_ALC_CTRL3,	0x0000,	/* */1059		WM_NOISE_GATE,	0x0000,	/* */1060#endif1061		WM_DAC_MUTE,	0x0000,	/* DAC unmute */1062		WM_ADC_MUX,	0x0003,	/* ADC unmute, both CD/Line On */1063	};1064	struct prodigy_hifi_spec *spec;1065	unsigned int i;1066 1067	ice->vt1720 = 0;1068	ice->vt1724 = 1;1069 1070	ice->num_total_dacs = 8;1071	ice->num_total_adcs = 1;1072 1073	/* HACK - use this as the SPDIF source.1074	* don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten1075	*/1076	ice->gpio.saved[0] = 0;1077	/* to remember the register values */1078 1079	ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);1080	if (! ice->akm)1081		return -ENOMEM;1082	ice->akm_codecs = 1;1083 1084	spec = kzalloc(sizeof(*spec), GFP_KERNEL);1085	if (!spec)1086		return -ENOMEM;1087	ice->spec = spec;1088 1089	/* initialize WM8776 codec */1090	wm8776_init(ice);1091	schedule_timeout_uninterruptible(1);1092	for (i = 0; i < ARRAY_SIZE(wm8776_defaults); i += 2)1093		wm_put(ice, wm8776_defaults[i], wm8776_defaults[i + 1]);1094 1095	wm8766_init(ice);1096 1097#ifdef CONFIG_PM_SLEEP1098	ice->pm_resume = &prodigy_hifi_resume;1099	ice->pm_suspend_enabled = 1;1100#endif1101 1102	return 0;1103}1104 1105 1106/*1107 * initialize the chip1108 */1109static void ak4396_init(struct snd_ice1712 *ice)1110{1111	static const unsigned short ak4396_inits[] = {1112		AK4396_CTRL1,	   0x87,   /* I2S Normal Mode, 24 bit */1113		AK4396_CTRL2,	   0x02,1114		AK4396_CTRL3,	   0x00, 1115		AK4396_LCH_ATT,	 0x00,1116		AK4396_RCH_ATT,	 0x00,1117	};1118 1119	unsigned int i;1120 1121	/* initialize ak4396 codec */1122	/* reset codec */1123	ak4396_write(ice, AK4396_CTRL1, 0x86);1124	msleep(100);1125	ak4396_write(ice, AK4396_CTRL1, 0x87);1126 1127	for (i = 0; i < ARRAY_SIZE(ak4396_inits); i += 2)1128		ak4396_write(ice, ak4396_inits[i], ak4396_inits[i+1]);1129}1130 1131#ifdef CONFIG_PM_SLEEP1132static int prodigy_hd2_resume(struct snd_ice1712 *ice)1133{1134	/* initialize ak4396 codec and restore previous mixer volumes */1135	struct prodigy_hifi_spec *spec = ice->spec;1136	int i;1137	mutex_lock(&ice->gpio_mutex);1138	ak4396_init(ice);1139	for (i = 0; i < 2; i++)1140		ak4396_write(ice, AK4396_LCH_ATT + i, spec->vol[i] & 0xff);1141	mutex_unlock(&ice->gpio_mutex);1142	return 0;1143}1144#endif1145 1146static int prodigy_hd2_init(struct snd_ice1712 *ice)1147{1148	struct prodigy_hifi_spec *spec;1149 1150	ice->vt1720 = 0;1151	ice->vt1724 = 1;1152 1153	ice->num_total_dacs = 1;1154	ice->num_total_adcs = 1;1155 1156	/* HACK - use this as the SPDIF source.1157	* don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten1158	*/1159	ice->gpio.saved[0] = 0;1160	/* to remember the register values */1161 1162	ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);1163	if (! ice->akm)1164		return -ENOMEM;1165	ice->akm_codecs = 1;1166 1167	spec = kzalloc(sizeof(*spec), GFP_KERNEL);1168	if (!spec)1169		return -ENOMEM;1170	ice->spec = spec;1171 1172#ifdef CONFIG_PM_SLEEP1173	ice->pm_resume = &prodigy_hd2_resume;1174	ice->pm_suspend_enabled = 1;1175#endif1176 1177	ak4396_init(ice);1178 1179	return 0;1180}1181 1182 1183static const unsigned char prodigy71hifi_eeprom[] = {1184	0x4b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */1185	0x80,   /* ACLINK: I2S */1186	0xfc,   /* I2S: vol, 96k, 24bit, 192k */1187	0xc3,   /* SPDIF: out-en, out-int, spdif-in */1188	0xff,   /* GPIO_DIR */1189	0xff,   /* GPIO_DIR1 */1190	0x5f,   /* GPIO_DIR2 */1191	0x00,   /* GPIO_MASK */1192	0x00,   /* GPIO_MASK1 */1193	0x00,   /* GPIO_MASK2 */1194	0x00,   /* GPIO_STATE */1195	0x00,   /* GPIO_STATE1 */1196	0x00,   /* GPIO_STATE2 */1197};1198 1199static const unsigned char prodigyhd2_eeprom[] = {1200	0x4b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */1201	0x80,   /* ACLINK: I2S */1202	0xfc,   /* I2S: vol, 96k, 24bit, 192k */1203	0xc3,   /* SPDIF: out-en, out-int, spdif-in */1204	0xff,   /* GPIO_DIR */1205	0xff,   /* GPIO_DIR1 */1206	0x5f,   /* GPIO_DIR2 */1207	0x00,   /* GPIO_MASK */1208	0x00,   /* GPIO_MASK1 */1209	0x00,   /* GPIO_MASK2 */1210	0x00,   /* GPIO_STATE */1211	0x00,   /* GPIO_STATE1 */1212	0x00,   /* GPIO_STATE2 */1213};1214 1215static const unsigned char fortissimo4_eeprom[] = {1216	0x43,   /* SYSCONF: clock 512, ADC, 4DACs */	1217	0x80,   /* ACLINK: I2S */1218	0xfc,   /* I2S: vol, 96k, 24bit, 192k */1219	0xc1,   /* SPDIF: out-en, out-int */1220	0xff,   /* GPIO_DIR */1221	0xff,   /* GPIO_DIR1 */1222	0x5f,   /* GPIO_DIR2 */1223	0x00,   /* GPIO_MASK */1224	0x00,   /* GPIO_MASK1 */1225	0x00,   /* GPIO_MASK2 */1226	0x00,   /* GPIO_STATE */1227	0x00,   /* GPIO_STATE1 */1228	0x00,   /* GPIO_STATE2 */1229};1230 1231/* entry point */1232struct snd_ice1712_card_info snd_vt1724_prodigy_hifi_cards[] = {1233	{1234		.subvendor = VT1724_SUBDEVICE_PRODIGY_HIFI,1235		.name = "Audiotrak Prodigy 7.1 HiFi",1236		.model = "prodigy71hifi",1237		.chip_init = prodigy_hifi_init,1238		.build_controls = prodigy_hifi_add_controls,1239		.eeprom_size = sizeof(prodigy71hifi_eeprom),1240		.eeprom_data = prodigy71hifi_eeprom,1241		.driver = "Prodigy71HIFI",1242	},1243	{1244	.subvendor = VT1724_SUBDEVICE_PRODIGY_HD2,1245	.name = "Audiotrak Prodigy HD2",1246	.model = "prodigyhd2",1247	.chip_init = prodigy_hd2_init,1248	.build_controls = prodigy_hd2_add_controls,1249	.eeprom_size = sizeof(prodigyhd2_eeprom),1250	.eeprom_data = prodigyhd2_eeprom,1251	.driver = "Prodigy71HD2",1252	},1253	{1254		.subvendor = VT1724_SUBDEVICE_FORTISSIMO4,1255		.name = "Hercules Fortissimo IV",1256		.model = "fortissimo4",1257		.chip_init = prodigy_hifi_init,1258		.build_controls = prodigy_hifi_add_controls,1259		.eeprom_size = sizeof(fortissimo4_eeprom),1260		.eeprom_data = fortissimo4_eeprom,1261		.driver = "Fortissimo4",1262	},1263	{ } /* terminator */1264};1265 1266