brintos

brintos / linux-shallow public Read only

0
0
Text · 15.3 KiB · f613f00 Raw
633 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *	ALSA driver for ICEnsemble VT1724 (Envy24HT)4 *5 *	Lowlevel functions for Ego Sys Waveterminal 192M6 *7 *		Copyright (c) 2006 Guedez Clement <klem.dev@gmail.com>8 *		Some functions are taken from the Prodigy192 driver9 *		source10 */11 12 13 14#include <linux/delay.h>15#include <linux/interrupt.h>16#include <linux/init.h>17#include <sound/core.h>18#include <sound/tlv.h>19#include <linux/slab.h>20 21#include "ice1712.h"22#include "envy24ht.h"23#include "wtm.h"24#include "stac946x.h"25 26struct wtm_spec {27	/* rate change needs atomic mute/unmute of all dacs*/28	struct mutex mute_mutex;29};30 31 32/*33 *	2*ADC 6*DAC no1 ringbuffer r/w on i2c bus34 */35static inline void stac9460_put(struct snd_ice1712 *ice, int reg,36						unsigned char val)37{38	snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val);39}40 41static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)42{43	return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg);44}45 46/*47 *	2*ADC 2*DAC no2 ringbuffer r/w on i2c bus48 */49static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg,50						unsigned char val)51{52	snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val);53}54 55static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg)56{57	return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg);58}59 60 61/*62 *	DAC mute control63 */64static void stac9460_dac_mute_all(struct snd_ice1712 *ice, unsigned char mute,65				unsigned short int *change_mask)66{67	unsigned char new, old;68	int id, idx, change;69 70	/*stac9460 1*/71	for (id = 0; id < 7; id++) {72		if (*change_mask & (0x01 << id)) {73			if (id == 0)74				idx = STAC946X_MASTER_VOLUME;75			else76				idx = STAC946X_LF_VOLUME - 1 + id;77			old = stac9460_get(ice, idx);78			new = (~mute << 7 & 0x80) | (old & ~0x80);79			change = (new != old);80			if (change) {81				stac9460_put(ice, idx, new);82				*change_mask = *change_mask | (0x01 << id);83			} else {84				*change_mask = *change_mask & ~(0x01 << id);85			}86		}87	}88 89	/*stac9460 2*/90	for (id = 0; id < 3; id++) {91		if (*change_mask & (0x01 << (id + 7))) {92			if (id == 0)93				idx = STAC946X_MASTER_VOLUME;94			else95				idx = STAC946X_LF_VOLUME - 1 + id;96			old = stac9460_2_get(ice, idx);97			new = (~mute << 7 & 0x80) | (old & ~0x80);98			change = (new != old);99			if (change) {100				stac9460_2_put(ice, idx, new);101				*change_mask = *change_mask | (0x01 << id);102			} else {103				*change_mask = *change_mask & ~(0x01 << id);104			}105		}106	}107}108 109 110 111#define stac9460_dac_mute_info		snd_ctl_boolean_mono_info112 113static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol,114				struct snd_ctl_elem_value *ucontrol)115{116	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);117	struct wtm_spec *spec = ice->spec;118	unsigned char val;119	int idx, id;120 121	mutex_lock(&spec->mute_mutex);122 123	if (kcontrol->private_value) {124		idx = STAC946X_MASTER_VOLUME;125		id = 0;126	} else {127		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);128		idx = id + STAC946X_LF_VOLUME;129	}130	if (id < 6)131		val = stac9460_get(ice, idx);132	else133		val = stac9460_2_get(ice, idx - 6);134	ucontrol->value.integer.value[0] = (~val >> 7) & 0x1;135 136	mutex_unlock(&spec->mute_mutex);137	return 0;138}139 140static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol,141				struct snd_ctl_elem_value *ucontrol)142{143	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);144	unsigned char new, old;145	int id, idx;146	int change;147 148	if (kcontrol->private_value) {149		idx = STAC946X_MASTER_VOLUME;150		old = stac9460_get(ice, idx);151		new = (~ucontrol->value.integer.value[0] << 7 & 0x80) |152							(old & ~0x80);153		change = (new != old);154		if (change) {155			stac9460_put(ice, idx, new);156			stac9460_2_put(ice, idx, new);157		}158	} else {159		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);160		idx = id + STAC946X_LF_VOLUME;161		if (id < 6)162			old = stac9460_get(ice, idx);163		else164			old = stac9460_2_get(ice, idx - 6);165		new = (~ucontrol->value.integer.value[0] << 7 & 0x80) |166							(old & ~0x80);167		change = (new != old);168		if (change) {169			if (id < 6)170				stac9460_put(ice, idx, new);171			else172				stac9460_2_put(ice, idx - 6, new);173		}174	}175	return change;176}177 178/*179 * 	DAC volume attenuation mixer control180 */181static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol,182				struct snd_ctl_elem_info *uinfo)183{184	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;185	uinfo->count = 1;186	uinfo->value.integer.min = 0;			/* mute */187	uinfo->value.integer.max = 0x7f;		/* 0dB */188	return 0;189}190 191static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol,192				struct snd_ctl_elem_value *ucontrol)193{194	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);195	int idx, id;196	unsigned char vol;197 198	if (kcontrol->private_value) {199		idx = STAC946X_MASTER_VOLUME;200		id = 0;201	} else {202		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);203		idx = id + STAC946X_LF_VOLUME;204	}205	if (id < 6)206		vol = stac9460_get(ice, idx) & 0x7f;207	else208		vol = stac9460_2_get(ice, idx - 6) & 0x7f;209	ucontrol->value.integer.value[0] = 0x7f - vol;210	return 0;211}212 213static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol,214				struct snd_ctl_elem_value *ucontrol)215{216	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);217	int idx, id;218	unsigned char tmp, ovol, nvol;219	int change;220 221	if (kcontrol->private_value) {222		idx = STAC946X_MASTER_VOLUME;223		nvol = ucontrol->value.integer.value[0] & 0x7f;224		tmp = stac9460_get(ice, idx);225		ovol = 0x7f - (tmp & 0x7f);226		change = (ovol != nvol);227		if (change) {228			stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));229			stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));230		}231	} else {232		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);233		idx = id + STAC946X_LF_VOLUME;234		nvol = ucontrol->value.integer.value[0] & 0x7f;235		if (id < 6)236			tmp = stac9460_get(ice, idx);237		else238			tmp = stac9460_2_get(ice, idx - 6);239		ovol = 0x7f - (tmp & 0x7f);240		change = (ovol != nvol);241		if (change) {242			if (id < 6)243				stac9460_put(ice, idx, (0x7f - nvol) |244							(tmp & 0x80));245			else246				stac9460_2_put(ice, idx-6, (0x7f - nvol) |247							(tmp & 0x80));248		}249	}250	return change;251}252 253/*254 * ADC mute control255 */256#define stac9460_adc_mute_info		snd_ctl_boolean_stereo_info257 258static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol,259				struct snd_ctl_elem_value *ucontrol)260{261	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);262	unsigned char val;263	int i, id;264 265	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);266	if (id == 0) {267		for (i = 0; i < 2; ++i) {268			val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i);269			ucontrol->value.integer.value[i] = ~val>>7 & 0x1;270		}271	} else {272		for (i = 0; i < 2; ++i) {273			val = stac9460_2_get(ice, STAC946X_MIC_L_VOLUME + i);274			ucontrol->value.integer.value[i] = ~val>>7 & 0x1;275		}276	}277	return 0;278}279 280static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol,281				struct snd_ctl_elem_value *ucontrol)282{283	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);284	unsigned char new, old;285	int i, reg, id;286	int change;287 288	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);289	if (id == 0) {290		for (i = 0; i < 2; ++i) {291			reg = STAC946X_MIC_L_VOLUME + i;292			old = stac9460_get(ice, reg);293			new = (~ucontrol->value.integer.value[i]<<7&0x80) |294								(old&~0x80);295			change = (new != old);296			if (change)297				stac9460_put(ice, reg, new);298		}299	} else {300		for (i = 0; i < 2; ++i) {301			reg = STAC946X_MIC_L_VOLUME + i;302			old = stac9460_2_get(ice, reg);303			new = (~ucontrol->value.integer.value[i]<<7&0x80) |304								(old&~0x80);305			change = (new != old);306			if (change)307				stac9460_2_put(ice, reg, new);308		}309	}310	return change;311}312 313/*314 *ADC gain mixer control315 */316static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol,317				struct snd_ctl_elem_info *uinfo)318{319	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;320	uinfo->count = 2;321	uinfo->value.integer.min = 0;		/* 0dB */322	uinfo->value.integer.max = 0x0f;	/* 22.5dB */323	return 0;324}325 326static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol,327				struct snd_ctl_elem_value *ucontrol)328{329	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);330	int i, reg, id;331	unsigned char vol;332 333	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);334	if (id == 0) {335		for (i = 0; i < 2; ++i) {336			reg = STAC946X_MIC_L_VOLUME + i;337			vol = stac9460_get(ice, reg) & 0x0f;338			ucontrol->value.integer.value[i] = 0x0f - vol;339		}340	} else {341		for (i = 0; i < 2; ++i) {342			reg = STAC946X_MIC_L_VOLUME + i;343			vol = stac9460_2_get(ice, reg) & 0x0f;344			ucontrol->value.integer.value[i] = 0x0f - vol;345		}346	}347	return 0;348}349 350static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol,351				struct snd_ctl_elem_value *ucontrol)352{353	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);354	int i, reg, id;355	unsigned char ovol, nvol;356	int change;357 358	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);359	if (id == 0) {360		for (i = 0; i < 2; ++i) {361			reg = STAC946X_MIC_L_VOLUME + i;362			nvol = ucontrol->value.integer.value[i] & 0x0f;363			ovol = 0x0f - stac9460_get(ice, reg);364			change = ((ovol & 0x0f) != nvol);365			if (change)366				stac9460_put(ice, reg, (0x0f - nvol) |367							(ovol & ~0x0f));368		}369	} else {370		for (i = 0; i < 2; ++i) {371			reg = STAC946X_MIC_L_VOLUME + i;372			nvol = ucontrol->value.integer.value[i] & 0x0f;373			ovol = 0x0f - stac9460_2_get(ice, reg);374			change = ((ovol & 0x0f) != nvol);375			if (change)376				stac9460_2_put(ice, reg, (0x0f - nvol) |377							(ovol & ~0x0f));378		}379	}380	return change;381}382 383/*384 * MIC / LINE switch fonction385 */386static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol,387				struct snd_ctl_elem_info *uinfo)388{389	static const char * const texts[2] = { "Line In", "Mic" };390 391	return snd_ctl_enum_info(uinfo, 1, 2, texts);392}393 394 395static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol,396				struct snd_ctl_elem_value *ucontrol)397{398	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);399	unsigned char val;400	int id;401 402	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);403	if (id == 0)404		val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);405	else406		val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);407	ucontrol->value.enumerated.item[0] = (val >> 7) & 0x1;408	return 0;409}410 411static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,412				struct snd_ctl_elem_value *ucontrol)413{414	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);415	unsigned char new, old;416	int change, id;417 418	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);419	if (id == 0)420		old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);421	else422		old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);423	new = (ucontrol->value.enumerated.item[0] << 7 & 0x80) | (old & ~0x80);424	change = (new != old);425	if (change) {426		if (id == 0)427			stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new);428		else429			stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new);430	}431	return change;432}433 434 435/*436 * Handler for setting correct codec rate - called when rate change is detected437 */438static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate)439{440	unsigned char old, new;441	unsigned short int changed;442	struct wtm_spec *spec = ice->spec;443 444	if (rate == 0)  /* no hint - S/PDIF input is master, simply return */445		return;446	else if (rate <= 48000)447		new = 0x08;     /* 256x, base rate mode */448	else if (rate <= 96000)449		new = 0x11;     /* 256x, mid rate mode */450	else451		new = 0x12;     /* 128x, high rate mode */452 453	old = stac9460_get(ice, STAC946X_MASTER_CLOCKING);454	if (old == new)455		return;456	/* change detected, setting master clock, muting first */457	/* due to possible conflicts with mute controls - mutexing */458	mutex_lock(&spec->mute_mutex);459	/* we have to remember current mute status for each DAC */460	changed = 0xFFFF;461	stac9460_dac_mute_all(ice, 0, &changed);462	/*printk(KERN_DEBUG "Rate change: %d, new MC: 0x%02x\n", rate, new);*/463	stac9460_put(ice, STAC946X_MASTER_CLOCKING, new);464	stac9460_2_put(ice, STAC946X_MASTER_CLOCKING, new);465	udelay(10);466	/* unmuting - only originally unmuted dacs -467	* i.e. those changed when muting */468	stac9460_dac_mute_all(ice, 1, &changed);469	mutex_unlock(&spec->mute_mutex);470}471 472 473/*Limits value in dB for fader*/474static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0);475static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);476 477/*478 * Control tabs479 */480static const struct snd_kcontrol_new stac9640_controls[] = {481	{482		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,483		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |484			    SNDRV_CTL_ELEM_ACCESS_TLV_READ),485		.name = "Master Playback Switch",486		.info = stac9460_dac_mute_info,487		.get = stac9460_dac_mute_get,488		.put = stac9460_dac_mute_put,489		.private_value = 1,490		.tlv = { .p = db_scale_dac }491	},492	{493		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,494		.name = "Master Playback Volume",495		.info = stac9460_dac_vol_info,496		.get = stac9460_dac_vol_get,497		.put = stac9460_dac_vol_put,498		.private_value = 1,499	},500	{501		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,502		.name = "MIC/Line Input Enum",503		.count = 2,504		.info = stac9460_mic_sw_info,505		.get = stac9460_mic_sw_get,506		.put = stac9460_mic_sw_put,507 508	},509	{510		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,511		.name = "DAC Switch",512		.count = 8,513		.info = stac9460_dac_mute_info,514		.get = stac9460_dac_mute_get,515		.put = stac9460_dac_mute_put,516	},517	{518		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,519		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |520			    SNDRV_CTL_ELEM_ACCESS_TLV_READ),521 522		.name = "DAC Volume",523		.count = 8,524		.info = stac9460_dac_vol_info,525		.get = stac9460_dac_vol_get,526		.put = stac9460_dac_vol_put,527		.tlv = { .p = db_scale_dac }528	},529	{530		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,531		.name = "ADC Switch",532		.count = 2,533		.info = stac9460_adc_mute_info,534		.get = stac9460_adc_mute_get,535		.put = stac9460_adc_mute_put,536	},537	{538		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,539		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |540			    SNDRV_CTL_ELEM_ACCESS_TLV_READ),541 542		.name = "ADC Volume",543		.count = 2,544		.info = stac9460_adc_vol_info,545		.get = stac9460_adc_vol_get,546		.put = stac9460_adc_vol_put,547		.tlv = { .p = db_scale_adc }548	}549};550 551 552 553/*INIT*/554static int wtm_add_controls(struct snd_ice1712 *ice)555{556	unsigned int i;557	int err;558 559	for (i = 0; i < ARRAY_SIZE(stac9640_controls); i++) {560		err = snd_ctl_add(ice->card,561				snd_ctl_new1(&stac9640_controls[i], ice));562		if (err < 0)563			return err;564	}565	return 0;566}567 568static int wtm_init(struct snd_ice1712 *ice)569{570	static const unsigned short stac_inits_wtm[] = {571		STAC946X_RESET, 0,572		STAC946X_MASTER_CLOCKING, 0x11,573		(unsigned short)-1574	};575	const unsigned short *p;576	struct wtm_spec *spec;577 578	/*WTM 192M*/579	ice->num_total_dacs = 8;580	ice->num_total_adcs = 4;581	ice->force_rdma1 = 1;582 583	/*init mutex for dac mute conflict*/584	spec = kzalloc(sizeof(*spec), GFP_KERNEL);585	if (!spec)586		return -ENOMEM;587	ice->spec = spec;588	mutex_init(&spec->mute_mutex);589 590 591	/*initialize codec*/592	p = stac_inits_wtm;593	for (; *p != (unsigned short)-1; p += 2) {594		stac9460_put(ice, p[0], p[1]);595		stac9460_2_put(ice, p[0], p[1]);596	}597	ice->gpio.set_pro_rate = stac9460_set_rate_val;598	return 0;599}600 601 602static const unsigned char wtm_eeprom[] = {603	[ICE_EEP2_SYSCONF]      = 0x67, /*SYSCONF: clock 192KHz, mpu401,604							4ADC, 8DAC */605	[ICE_EEP2_ACLINK]       = 0x80, /* ACLINK : I2S */606	[ICE_EEP2_I2S]          = 0xf8, /* I2S: vol; 96k, 24bit, 192k */607	[ICE_EEP2_SPDIF]        = 0xc1, /*SPDIF: out-en, spidf ext out*/608	[ICE_EEP2_GPIO_DIR]     = 0x9f,609	[ICE_EEP2_GPIO_DIR1]    = 0xff,610	[ICE_EEP2_GPIO_DIR2]    = 0x7f,611	[ICE_EEP2_GPIO_MASK]    = 0x9f,612	[ICE_EEP2_GPIO_MASK1]   = 0xff,613	[ICE_EEP2_GPIO_MASK2]   = 0x7f,614	[ICE_EEP2_GPIO_STATE]   = 0x16,615	[ICE_EEP2_GPIO_STATE1]  = 0x80,616	[ICE_EEP2_GPIO_STATE2]  = 0x00,617};618 619 620/*entry point*/621struct snd_ice1712_card_info snd_vt1724_wtm_cards[] = {622	{623		.subvendor = VT1724_SUBDEVICE_WTM,624		.name = "ESI Waveterminal 192M",625		.model = "WT192M",626		.chip_init = wtm_init,627		.build_controls = wtm_add_controls,628		.eeprom_size = sizeof(wtm_eeprom),629		.eeprom_data = wtm_eeprom,630	},631	{} /*terminator*/632};633