brintos

brintos / linux-shallow public Read only

0
0
Text · 32.3 KiB · cb7a68c Raw
1179 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// IDT821034 ALSA SoC driver4//5// Copyright 2022 CS GROUP France6//7// Author: Herve Codina <herve.codina@bootlin.com>8 9#include <linux/bitrev.h>10#include <linux/gpio/driver.h>11#include <linux/module.h>12#include <linux/slab.h>13#include <linux/spi/spi.h>14#include <sound/pcm_params.h>15#include <sound/soc.h>16#include <sound/tlv.h>17 18#define IDT821034_NB_CHANNEL	419 20struct idt821034_amp {21	u16 gain;22	bool is_muted;23};24 25struct idt821034 {26	struct spi_device *spi;27	struct mutex mutex;28	u8 spi_tx_buf; /* Cannot use stack area for SPI (dma-safe memory) */29	u8 spi_rx_buf; /* Cannot use stack area for SPI (dma-safe memory) */30	struct {31		u8 codec_conf;32		struct {33			u8 power;34			u8 tx_slot;35			u8 rx_slot;36			u8 slic_conf;37			u8 slic_control;38		} ch[IDT821034_NB_CHANNEL];39	} cache;40	struct {41		struct {42			struct idt821034_amp amp_out;43			struct idt821034_amp amp_in;44		} ch[IDT821034_NB_CHANNEL];45	} amps;46	int max_ch_playback;47	int max_ch_capture;48	struct gpio_chip gpio_chip;49};50 51static int idt821034_8bit_write(struct idt821034 *idt821034, u8 val)52{53	struct spi_transfer xfer[] = {54		{55			.tx_buf = &idt821034->spi_tx_buf,56			.len = 1,57		}, {58			.cs_off = 1,59			.tx_buf = &idt821034->spi_tx_buf,60			.len = 1,61		}62	};63 64	idt821034->spi_tx_buf = val;65 66	dev_vdbg(&idt821034->spi->dev, "spi xfer wr 0x%x\n", val);67 68	return spi_sync_transfer(idt821034->spi, xfer, 2);69}70 71static int idt821034_2x8bit_write(struct idt821034 *idt821034, u8 val1, u8 val2)72{73	int ret;74 75	ret = idt821034_8bit_write(idt821034, val1);76	if (ret)77		return ret;78	return idt821034_8bit_write(idt821034, val2);79}80 81static int idt821034_8bit_read(struct idt821034 *idt821034, u8 valw, u8 *valr)82{83	struct spi_transfer xfer[] = {84		{85			.tx_buf = &idt821034->spi_tx_buf,86			.rx_buf = &idt821034->spi_rx_buf,87			.len = 1,88		}, {89			.cs_off = 1,90			.tx_buf = &idt821034->spi_tx_buf,91			.len = 1,92		}93	};94	int ret;95 96	idt821034->spi_tx_buf = valw;97 98	ret = spi_sync_transfer(idt821034->spi, xfer, 2);99	if (ret)100		return ret;101 102	*valr = idt821034->spi_rx_buf;103 104	dev_vdbg(&idt821034->spi->dev, "spi xfer wr 0x%x, rd 0x%x\n",105		 valw, *valr);106 107	return 0;108}109 110/* Available mode for the programming sequence */111#define IDT821034_MODE_CODEC(_ch) (0x80 | ((_ch) << 2))112#define IDT821034_MODE_SLIC(_ch)  (0xD0 | ((_ch) << 2))113#define IDT821034_MODE_GAIN(_ch)  (0xC0 | ((_ch) << 2))114 115/* Power values that can be used in 'power' (can be ORed) */116#define IDT821034_CONF_PWRUP_TX		BIT(1) /* from analog input to PCM */117#define IDT821034_CONF_PWRUP_RX		BIT(0) /* from PCM to analog output */118 119static int idt821034_set_channel_power(struct idt821034 *idt821034, u8 ch, u8 power)120{121	u8 conf;122	int ret;123 124	dev_dbg(&idt821034->spi->dev, "set_channel_power(%u, 0x%x)\n", ch, power);125 126	conf = IDT821034_MODE_CODEC(ch) | idt821034->cache.codec_conf;127 128	if (power & IDT821034_CONF_PWRUP_RX) {129		ret = idt821034_2x8bit_write(idt821034,130					     conf | IDT821034_CONF_PWRUP_RX,131					     idt821034->cache.ch[ch].rx_slot);132		if (ret)133			return ret;134	}135	if (power & IDT821034_CONF_PWRUP_TX) {136		ret = idt821034_2x8bit_write(idt821034,137					     conf | IDT821034_CONF_PWRUP_TX,138					     idt821034->cache.ch[ch].tx_slot);139		if (ret)140			return ret;141	}142	if (!(power & (IDT821034_CONF_PWRUP_TX | IDT821034_CONF_PWRUP_RX))) {143		ret = idt821034_2x8bit_write(idt821034, conf, 0);144		if (ret)145			return ret;146	}147 148	idt821034->cache.ch[ch].power = power;149 150	return 0;151}152 153static u8 idt821034_get_channel_power(struct idt821034 *idt821034, u8 ch)154{155	return idt821034->cache.ch[ch].power;156}157 158/* Codec configuration values that can be used in 'codec_conf' (can be ORed) */159#define IDT821034_CONF_ALAW_MODE	BIT(5)160#define IDT821034_CONF_DELAY_MODE	BIT(4)161 162static int idt821034_set_codec_conf(struct idt821034 *idt821034, u8 codec_conf)163{164	u8 conf;165	u8 ts;166	int ret;167 168	dev_dbg(&idt821034->spi->dev, "set_codec_conf(0x%x)\n", codec_conf);169 170	/* codec conf fields are common to all channel.171	 * Arbitrary use of channel 0 for this configuration.172	 */173 174	/* Set Configuration Register */175	conf = IDT821034_MODE_CODEC(0) | codec_conf;176 177	/* Update conf value and timeslot register value according178	 * to cache values179	 */180	if (idt821034->cache.ch[0].power & IDT821034_CONF_PWRUP_RX) {181		conf |= IDT821034_CONF_PWRUP_RX;182		ts = idt821034->cache.ch[0].rx_slot;183	} else if (idt821034->cache.ch[0].power & IDT821034_CONF_PWRUP_TX) {184		conf |= IDT821034_CONF_PWRUP_TX;185		ts = idt821034->cache.ch[0].tx_slot;186	} else {187		ts = 0x00;188	}189 190	/* Write configuration register and time-slot register */191	ret = idt821034_2x8bit_write(idt821034, conf, ts);192	if (ret)193		return ret;194 195	idt821034->cache.codec_conf = codec_conf;196	return 0;197}198 199static u8 idt821034_get_codec_conf(struct idt821034 *idt821034)200{201	return idt821034->cache.codec_conf;202}203 204/* Channel direction values that can be used in 'ch_dir' (can be ORed) */205#define IDT821034_CH_RX		BIT(0) /* from PCM to analog output */206#define IDT821034_CH_TX		BIT(1) /* from analog input to PCM */207 208static int idt821034_set_channel_ts(struct idt821034 *idt821034, u8 ch, u8 ch_dir, u8 ts_num)209{210	u8 conf;211	int ret;212 213	dev_dbg(&idt821034->spi->dev, "set_channel_ts(%u, 0x%x, %d)\n", ch, ch_dir, ts_num);214 215	conf = IDT821034_MODE_CODEC(ch) | idt821034->cache.codec_conf;216 217	if (ch_dir & IDT821034_CH_RX) {218		if (idt821034->cache.ch[ch].power & IDT821034_CONF_PWRUP_RX) {219			ret = idt821034_2x8bit_write(idt821034,220						     conf | IDT821034_CONF_PWRUP_RX,221						     ts_num);222			if (ret)223				return ret;224		}225		idt821034->cache.ch[ch].rx_slot = ts_num;226	}227	if (ch_dir & IDT821034_CH_TX) {228		if (idt821034->cache.ch[ch].power & IDT821034_CONF_PWRUP_TX) {229			ret = idt821034_2x8bit_write(idt821034,230						     conf | IDT821034_CONF_PWRUP_TX,231						     ts_num);232			if (ret)233				return ret;234		}235		idt821034->cache.ch[ch].tx_slot = ts_num;236	}237 238	return 0;239}240 241/* SLIC direction values that can be used in 'slic_dir' (can be ORed) */242#define IDT821034_SLIC_IO1_IN       BIT(1)243#define IDT821034_SLIC_IO0_IN       BIT(0)244 245static int idt821034_set_slic_conf(struct idt821034 *idt821034, u8 ch, u8 slic_dir)246{247	u8 conf;248	int ret;249 250	dev_dbg(&idt821034->spi->dev, "set_slic_conf(%u, 0x%x)\n", ch, slic_dir);251 252	conf = IDT821034_MODE_SLIC(ch) | slic_dir;253	ret = idt821034_2x8bit_write(idt821034, conf, idt821034->cache.ch[ch].slic_control);254	if (ret)255		return ret;256 257	idt821034->cache.ch[ch].slic_conf = slic_dir;258 259	return 0;260}261 262static u8 idt821034_get_slic_conf(struct idt821034 *idt821034, u8 ch)263{264	return idt821034->cache.ch[ch].slic_conf;265}266 267static int idt821034_write_slic_raw(struct idt821034 *idt821034, u8 ch, u8 slic_raw)268{269	u8 conf;270	int ret;271 272	dev_dbg(&idt821034->spi->dev, "write_slic_raw(%u, 0x%x)\n", ch, slic_raw);273 274	/*275	 * On write, slic_raw is mapped as follow :276	 *   b4: O_4277	 *   b3: O_3278	 *   b2: O_2279	 *   b1: I/O_1280	 *   b0: I/O_0281	 */282 283	conf = IDT821034_MODE_SLIC(ch) | idt821034->cache.ch[ch].slic_conf;284	ret = idt821034_2x8bit_write(idt821034, conf, slic_raw);285	if (ret)286		return ret;287 288	idt821034->cache.ch[ch].slic_control = slic_raw;289	return 0;290}291 292static u8 idt821034_get_written_slic_raw(struct idt821034 *idt821034, u8 ch)293{294	return idt821034->cache.ch[ch].slic_control;295}296 297static int idt821034_read_slic_raw(struct idt821034 *idt821034, u8 ch, u8 *slic_raw)298{299	u8 val;300	int ret;301 302	/*303	 * On read, slic_raw is mapped as follow :304	 *   b7: I/O_0305	 *   b6: I/O_1306	 *   b5: O_2307	 *   b4: O_3308	 *   b3: O_4309	 *   b2: I/O1_0, I/O_0 from channel 1 (no matter ch value)310	 *   b1: I/O2_0, I/O_0 from channel 2 (no matter ch value)311	 *   b2: I/O3_0, I/O_0 from channel 3 (no matter ch value)312	 */313 314	val = IDT821034_MODE_SLIC(ch) | idt821034->cache.ch[ch].slic_conf;315	ret = idt821034_8bit_write(idt821034, val);316	if (ret)317		return ret;318 319	ret = idt821034_8bit_read(idt821034, idt821034->cache.ch[ch].slic_control, slic_raw);320	if (ret)321		return ret;322 323	dev_dbg(&idt821034->spi->dev, "read_slic_raw(%i) 0x%x\n", ch, *slic_raw);324 325	return 0;326}327 328/* Gain type values that can be used in 'gain_type' (cannot be ORed) */329#define IDT821034_GAIN_RX		(0 << 1) /* from PCM to analog output */330#define IDT821034_GAIN_TX		(1 << 1) /* from analog input to PCM */331 332static int idt821034_set_gain_channel(struct idt821034 *idt821034, u8 ch,333				      u8 gain_type, u16 gain_val)334{335	u8 conf;336	int ret;337 338	dev_dbg(&idt821034->spi->dev, "set_gain_channel(%u, 0x%x, 0x%x-%d)\n",339		ch, gain_type, gain_val, gain_val);340 341	/*342	 * The gain programming coefficients should be calculated as:343	 *   Transmit : Coeff_X = round [ gain_X0dB × gain_X ]344	 *   Receive: Coeff_R = round [ gain_R0dB × gain_R ]345	 * where:346	 *   gain_X0dB = 1820;347	 *   gain_X is the target gain;348	 *   Coeff_X should be in the range of 0 to 8192.349	 *   gain_R0dB = 2506;350	 *   gain_R is the target gain;351	 *   Coeff_R should be in the range of 0 to 8192.352	 *353	 * A gain programming coefficient is 14-bit wide and in binary format.354	 * The 7 Most Significant Bits of the coefficient is called355	 * GA_MSB_Transmit for transmit path, or is called GA_MSB_Receive for356	 * receive path; The 7 Least Significant Bits of the coefficient is357	 * called GA_LSB_ Transmit for transmit path, or is called358	 * GA_LSB_Receive for receive path.359	 *360	 * An example is given below to clarify the calculation of the361	 * coefficient. To program a +3 dB gain in transmit path and a -3.5 dB362	 * gain in receive path:363	 *364	 * Linear Code of +3dB = 10^(3/20)= 1.412537545365	 * Coeff_X = round (1820 × 1.412537545) = 2571366	 *                                      = 0b001010_00001011367	 * GA_MSB_Transmit = 0b0010100368	 * GA_LSB_Transmit = 0b0001011369	 *370	 * Linear Code of -3.5dB = 10^(-3.5/20) = 0.668343917371	 * Coeff_R= round (2506 × 0.668343917) = 1675372	 *                                     = 0b0001101_0001011373	 * GA_MSB_Receive = 0b0001101374	 * GA_LSB_Receive = 0b0001011375	 */376 377	conf = IDT821034_MODE_GAIN(ch) | gain_type;378 379	ret = idt821034_2x8bit_write(idt821034, conf | 0x00, gain_val & 0x007F);380	if (ret)381		return ret;382 383	ret = idt821034_2x8bit_write(idt821034, conf | 0x01, (gain_val >> 7) & 0x7F);384	if (ret)385		return ret;386 387	return 0;388}389 390/* Id helpers used in controls and dapm */391#define IDT821034_DIR_OUT (1 << 3)392#define IDT821034_DIR_IN  (0 << 3)393#define IDT821034_ID(_ch, _dir) (((_ch) & 0x03) | (_dir))394#define IDT821034_ID_OUT(_ch) IDT821034_ID(_ch, IDT821034_DIR_OUT)395#define IDT821034_ID_IN(_ch)  IDT821034_ID(_ch, IDT821034_DIR_IN)396 397#define IDT821034_ID_GET_CHAN(_id) ((_id) & 0x03)398#define IDT821034_ID_GET_DIR(_id) ((_id) & (1 << 3))399#define IDT821034_ID_IS_OUT(_id) (IDT821034_ID_GET_DIR(_id) == IDT821034_DIR_OUT)400 401static int idt821034_kctrl_gain_get(struct snd_kcontrol *kcontrol,402				    struct snd_ctl_elem_value *ucontrol)403{404	struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;405	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);406	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(component);407	int min = mc->min;408	int max = mc->max;409	unsigned int mask = (1 << fls(max)) - 1;410	unsigned int invert = mc->invert;411	int val;412	u8 ch;413 414	ch = IDT821034_ID_GET_CHAN(mc->reg);415 416	mutex_lock(&idt821034->mutex);417	if (IDT821034_ID_IS_OUT(mc->reg))418		val = idt821034->amps.ch[ch].amp_out.gain;419	else420		val = idt821034->amps.ch[ch].amp_in.gain;421	mutex_unlock(&idt821034->mutex);422 423	ucontrol->value.integer.value[0] = val & mask;424	if (invert)425		ucontrol->value.integer.value[0] = max - ucontrol->value.integer.value[0];426	else427		ucontrol->value.integer.value[0] = ucontrol->value.integer.value[0] - min;428 429	return 0;430}431 432static int idt821034_kctrl_gain_put(struct snd_kcontrol *kcontrol,433				    struct snd_ctl_elem_value *ucontrol)434{435	struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;436	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);437	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(component);438	struct idt821034_amp *amp;439	int min = mc->min;440	int max = mc->max;441	unsigned int mask = (1 << fls(max)) - 1;442	unsigned int invert = mc->invert;443	unsigned int val;444	int ret;445	u8 gain_type;446	u8 ch;447 448	val = ucontrol->value.integer.value[0];449	if (val > max - min)450		return -EINVAL;451 452	if (invert)453		val = (max - val) & mask;454	else455		val = (val + min) & mask;456 457	ch = IDT821034_ID_GET_CHAN(mc->reg);458 459	mutex_lock(&idt821034->mutex);460 461	if (IDT821034_ID_IS_OUT(mc->reg)) {462		amp = &idt821034->amps.ch[ch].amp_out;463		gain_type = IDT821034_GAIN_RX;464	} else {465		amp = &idt821034->amps.ch[ch].amp_in;466		gain_type = IDT821034_GAIN_TX;467	}468 469	if (amp->gain == val) {470		ret = 0;471		goto end;472	}473 474	if (!amp->is_muted) {475		ret = idt821034_set_gain_channel(idt821034, ch, gain_type, val);476		if (ret)477			goto end;478	}479 480	amp->gain = val;481	ret = 1; /* The value changed */482end:483	mutex_unlock(&idt821034->mutex);484	return ret;485}486 487static int idt821034_kctrl_mute_get(struct snd_kcontrol *kcontrol,488				    struct snd_ctl_elem_value *ucontrol)489{490	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);491	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(component);492	int id = kcontrol->private_value;493	bool is_muted;494	u8 ch;495 496	ch = IDT821034_ID_GET_CHAN(id);497 498	mutex_lock(&idt821034->mutex);499	is_muted = IDT821034_ID_IS_OUT(id) ?500			idt821034->amps.ch[ch].amp_out.is_muted :501			idt821034->amps.ch[ch].amp_in.is_muted;502	mutex_unlock(&idt821034->mutex);503 504	ucontrol->value.integer.value[0] = !is_muted;505 506	return 0;507}508 509static int idt821034_kctrl_mute_put(struct snd_kcontrol *kcontrol,510				    struct snd_ctl_elem_value *ucontrol)511{512	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);513	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(component);514	int id = kcontrol->private_value;515	struct idt821034_amp *amp;516	bool is_mute;517	u8 gain_type;518	int ret;519	u8 ch;520 521	ch = IDT821034_ID_GET_CHAN(id);522	is_mute = !ucontrol->value.integer.value[0];523 524	mutex_lock(&idt821034->mutex);525 526	if (IDT821034_ID_IS_OUT(id)) {527		amp = &idt821034->amps.ch[ch].amp_out;528		gain_type = IDT821034_GAIN_RX;529	} else {530		amp = &idt821034->amps.ch[ch].amp_in;531		gain_type = IDT821034_GAIN_TX;532	}533 534	if (amp->is_muted == is_mute) {535		ret = 0;536		goto end;537	}538 539	ret = idt821034_set_gain_channel(idt821034, ch, gain_type,540					 is_mute ? 0 : amp->gain);541	if (ret)542		goto end;543 544	amp->is_muted = is_mute;545	ret = 1; /* The value changed */546end:547	mutex_unlock(&idt821034->mutex);548	return ret;549}550 551static const DECLARE_TLV_DB_LINEAR(idt821034_gain_in, -6520, 1306);552#define IDT821034_GAIN_IN_MIN_RAW	1 /* -65.20 dB -> 10^(-65.2/20.0) * 1820 = 1 */553#define IDT821034_GAIN_IN_MAX_RAW	8191 /* 13.06 dB -> 10^(13.06/20.0) * 1820 = 8191 */554#define IDT821034_GAIN_IN_INIT_RAW	1820 /* 0dB -> 10^(0/20) * 1820 = 1820 */555 556static const DECLARE_TLV_DB_LINEAR(idt821034_gain_out, -6798, 1029);557#define IDT821034_GAIN_OUT_MIN_RAW	1 /* -67.98 dB -> 10^(-67.98/20.0) * 2506 = 1*/558#define IDT821034_GAIN_OUT_MAX_RAW	8191 /* 10.29 dB -> 10^(10.29/20.0) * 2506 = 8191 */559#define IDT821034_GAIN_OUT_INIT_RAW	2506 /* 0dB -> 10^(0/20) * 2506 = 2506 */560 561static const struct snd_kcontrol_new idt821034_controls[] = {562	/* DAC volume control */563	SOC_SINGLE_RANGE_EXT_TLV("DAC0 Playback Volume", IDT821034_ID_OUT(0), 0,564				 IDT821034_GAIN_OUT_MIN_RAW, IDT821034_GAIN_OUT_MAX_RAW,565				 0, idt821034_kctrl_gain_get, idt821034_kctrl_gain_put,566				 idt821034_gain_out),567	SOC_SINGLE_RANGE_EXT_TLV("DAC1 Playback Volume", IDT821034_ID_OUT(1), 0,568				 IDT821034_GAIN_OUT_MIN_RAW, IDT821034_GAIN_OUT_MAX_RAW,569				 0, idt821034_kctrl_gain_get, idt821034_kctrl_gain_put,570				 idt821034_gain_out),571	SOC_SINGLE_RANGE_EXT_TLV("DAC2 Playback Volume", IDT821034_ID_OUT(2), 0,572				 IDT821034_GAIN_OUT_MIN_RAW, IDT821034_GAIN_OUT_MAX_RAW,573				 0, idt821034_kctrl_gain_get, idt821034_kctrl_gain_put,574				 idt821034_gain_out),575	SOC_SINGLE_RANGE_EXT_TLV("DAC3 Playback Volume", IDT821034_ID_OUT(3), 0,576				 IDT821034_GAIN_OUT_MIN_RAW, IDT821034_GAIN_OUT_MAX_RAW,577				 0, idt821034_kctrl_gain_get, idt821034_kctrl_gain_put,578				 idt821034_gain_out),579 580	/* DAC mute control */581	SOC_SINGLE_BOOL_EXT("DAC0 Playback Switch", IDT821034_ID_OUT(0),582			    idt821034_kctrl_mute_get, idt821034_kctrl_mute_put),583	SOC_SINGLE_BOOL_EXT("DAC1 Playback Switch", IDT821034_ID_OUT(1),584			    idt821034_kctrl_mute_get, idt821034_kctrl_mute_put),585	SOC_SINGLE_BOOL_EXT("DAC2 Playback Switch", IDT821034_ID_OUT(2),586			    idt821034_kctrl_mute_get, idt821034_kctrl_mute_put),587	SOC_SINGLE_BOOL_EXT("DAC3 Playback Switch", IDT821034_ID_OUT(3),588			    idt821034_kctrl_mute_get, idt821034_kctrl_mute_put),589 590	/* ADC volume control */591	SOC_SINGLE_RANGE_EXT_TLV("ADC0 Capture Volume", IDT821034_ID_IN(0), 0,592				 IDT821034_GAIN_IN_MIN_RAW, IDT821034_GAIN_IN_MAX_RAW,593				 0, idt821034_kctrl_gain_get, idt821034_kctrl_gain_put,594				 idt821034_gain_in),595	SOC_SINGLE_RANGE_EXT_TLV("ADC1 Capture Volume", IDT821034_ID_IN(1), 0,596				 IDT821034_GAIN_IN_MIN_RAW, IDT821034_GAIN_IN_MAX_RAW,597				 0, idt821034_kctrl_gain_get, idt821034_kctrl_gain_put,598				 idt821034_gain_in),599	SOC_SINGLE_RANGE_EXT_TLV("ADC2 Capture Volume", IDT821034_ID_IN(2), 0,600				 IDT821034_GAIN_IN_MIN_RAW, IDT821034_GAIN_IN_MAX_RAW,601				 0, idt821034_kctrl_gain_get, idt821034_kctrl_gain_put,602				 idt821034_gain_in),603	SOC_SINGLE_RANGE_EXT_TLV("ADC3 Capture Volume", IDT821034_ID_IN(3), 0,604				 IDT821034_GAIN_IN_MIN_RAW, IDT821034_GAIN_IN_MAX_RAW,605				 0, idt821034_kctrl_gain_get, idt821034_kctrl_gain_put,606				 idt821034_gain_in),607 608	/* ADC mute control */609	SOC_SINGLE_BOOL_EXT("ADC0 Capture Switch", IDT821034_ID_IN(0),610			    idt821034_kctrl_mute_get, idt821034_kctrl_mute_put),611	SOC_SINGLE_BOOL_EXT("ADC1 Capture Switch", IDT821034_ID_IN(1),612			    idt821034_kctrl_mute_get, idt821034_kctrl_mute_put),613	SOC_SINGLE_BOOL_EXT("ADC2 Capture Switch", IDT821034_ID_IN(2),614			    idt821034_kctrl_mute_get, idt821034_kctrl_mute_put),615	SOC_SINGLE_BOOL_EXT("ADC3 Capture Switch", IDT821034_ID_IN(3),616			    idt821034_kctrl_mute_get, idt821034_kctrl_mute_put),617};618 619static int idt821034_power_event(struct snd_soc_dapm_widget *w,620				 struct snd_kcontrol *kcontrol, int event)621{622	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);623	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(component);624	unsigned int id = w->shift;625	u8 power, mask;626	int ret;627	u8 ch;628 629	ch = IDT821034_ID_GET_CHAN(id);630	mask = IDT821034_ID_IS_OUT(id) ? IDT821034_CONF_PWRUP_RX : IDT821034_CONF_PWRUP_TX;631 632	mutex_lock(&idt821034->mutex);633 634	power = idt821034_get_channel_power(idt821034, ch);635	if (SND_SOC_DAPM_EVENT_ON(event))636		power |= mask;637	else638		power &= ~mask;639	ret = idt821034_set_channel_power(idt821034, ch, power);640 641	mutex_unlock(&idt821034->mutex);642 643	return ret;644}645 646static const struct snd_soc_dapm_widget idt821034_dapm_widgets[] = {647	SND_SOC_DAPM_DAC_E("DAC0", "Playback", SND_SOC_NOPM, IDT821034_ID_OUT(0), 0,648			   idt821034_power_event,649			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),650	SND_SOC_DAPM_DAC_E("DAC1", "Playback", SND_SOC_NOPM, IDT821034_ID_OUT(1), 0,651			   idt821034_power_event,652			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),653	SND_SOC_DAPM_DAC_E("DAC2", "Playback", SND_SOC_NOPM, IDT821034_ID_OUT(2), 0,654			   idt821034_power_event,655			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),656	SND_SOC_DAPM_DAC_E("DAC3", "Playback", SND_SOC_NOPM, IDT821034_ID_OUT(3), 0,657			   idt821034_power_event,658			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),659 660	SND_SOC_DAPM_OUTPUT("OUT0"),661	SND_SOC_DAPM_OUTPUT("OUT1"),662	SND_SOC_DAPM_OUTPUT("OUT2"),663	SND_SOC_DAPM_OUTPUT("OUT3"),664 665	SND_SOC_DAPM_DAC_E("ADC0", "Capture", SND_SOC_NOPM, IDT821034_ID_IN(0), 0,666			   idt821034_power_event,667			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),668	SND_SOC_DAPM_DAC_E("ADC1", "Capture", SND_SOC_NOPM, IDT821034_ID_IN(1), 0,669			   idt821034_power_event,670			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),671	SND_SOC_DAPM_DAC_E("ADC2", "Capture", SND_SOC_NOPM, IDT821034_ID_IN(2), 0,672			   idt821034_power_event,673			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),674	SND_SOC_DAPM_DAC_E("ADC3", "Capture", SND_SOC_NOPM, IDT821034_ID_IN(3), 0,675			   idt821034_power_event,676			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),677 678	SND_SOC_DAPM_INPUT("IN0"),679	SND_SOC_DAPM_INPUT("IN1"),680	SND_SOC_DAPM_INPUT("IN2"),681	SND_SOC_DAPM_INPUT("IN3"),682};683 684static const struct snd_soc_dapm_route idt821034_dapm_routes[] = {685	{ "OUT0", NULL, "DAC0" },686	{ "OUT1", NULL, "DAC1" },687	{ "OUT2", NULL, "DAC2" },688	{ "OUT3", NULL, "DAC3" },689 690	{ "ADC0", NULL, "IN0" },691	{ "ADC1", NULL, "IN1" },692	{ "ADC2", NULL, "IN2" },693	{ "ADC3", NULL, "IN3" },694};695 696static int idt821034_dai_set_tdm_slot(struct snd_soc_dai *dai,697				      unsigned int tx_mask, unsigned int rx_mask,698				      int slots, int width)699{700	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(dai->component);701	unsigned int mask;702	u8 slot;703	int ret;704	u8 ch;705 706	switch (width) {707	case 0: /* Not set -> default 8 */708	case 8:709		break;710	default:711		dev_err(dai->dev, "tdm slot width %d not supported\n", width);712		return -EINVAL;713	}714 715	mask = tx_mask;716	slot = 0;717	ch = 0;718	while (mask && ch < IDT821034_NB_CHANNEL) {719		if (mask & 0x1) {720			mutex_lock(&idt821034->mutex);721			ret = idt821034_set_channel_ts(idt821034, ch, IDT821034_CH_RX, slot);722			mutex_unlock(&idt821034->mutex);723			if (ret) {724				dev_err(dai->dev, "ch%u set tx tdm slot failed (%d)\n",725					ch, ret);726				return ret;727			}728			ch++;729		}730		mask >>= 1;731		slot++;732	}733	if (mask) {734		dev_err(dai->dev, "too much tx slots defined (mask = 0x%x) support max %d\n",735			tx_mask, IDT821034_NB_CHANNEL);736		return -EINVAL;737	}738	idt821034->max_ch_playback = ch;739 740	mask = rx_mask;741	slot = 0;742	ch = 0;743	while (mask && ch < IDT821034_NB_CHANNEL) {744		if (mask & 0x1) {745			mutex_lock(&idt821034->mutex);746			ret = idt821034_set_channel_ts(idt821034, ch, IDT821034_CH_TX, slot);747			mutex_unlock(&idt821034->mutex);748			if (ret) {749				dev_err(dai->dev, "ch%u set rx tdm slot failed (%d)\n",750					ch, ret);751				return ret;752			}753			ch++;754		}755		mask >>= 1;756		slot++;757	}758	if (mask) {759		dev_err(dai->dev, "too much rx slots defined (mask = 0x%x) support max %d\n",760			rx_mask, IDT821034_NB_CHANNEL);761		return -EINVAL;762	}763	idt821034->max_ch_capture = ch;764 765	return 0;766}767 768static int idt821034_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)769{770	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(dai->component);771	u8 conf;772	int ret;773 774	mutex_lock(&idt821034->mutex);775 776	conf = idt821034_get_codec_conf(idt821034);777 778	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {779	case SND_SOC_DAIFMT_DSP_A:780		conf |= IDT821034_CONF_DELAY_MODE;781		break;782	case SND_SOC_DAIFMT_DSP_B:783		conf &= ~IDT821034_CONF_DELAY_MODE;784		break;785	default:786		dev_err(dai->dev, "Unsupported DAI format 0x%x\n",787			fmt & SND_SOC_DAIFMT_FORMAT_MASK);788		ret = -EINVAL;789		goto end;790	}791	ret = idt821034_set_codec_conf(idt821034, conf);792end:793	mutex_unlock(&idt821034->mutex);794	return ret;795}796 797static int idt821034_dai_hw_params(struct snd_pcm_substream *substream,798				   struct snd_pcm_hw_params *params,799				   struct snd_soc_dai *dai)800{801	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(dai->component);802	u8 conf;803	int ret;804 805	mutex_lock(&idt821034->mutex);806 807	conf = idt821034_get_codec_conf(idt821034);808 809	switch (params_format(params)) {810	case SNDRV_PCM_FORMAT_A_LAW:811		conf |= IDT821034_CONF_ALAW_MODE;812		break;813	case SNDRV_PCM_FORMAT_MU_LAW:814		conf &= ~IDT821034_CONF_ALAW_MODE;815		break;816	default:817		dev_err(dai->dev, "Unsupported PCM format 0x%x\n",818			params_format(params));819		ret = -EINVAL;820		goto end;821	}822	ret = idt821034_set_codec_conf(idt821034, conf);823end:824	mutex_unlock(&idt821034->mutex);825	return ret;826}827 828static const unsigned int idt821034_sample_bits[] = {8};829 830static struct snd_pcm_hw_constraint_list idt821034_sample_bits_constr = {831	.list = idt821034_sample_bits,832	.count = ARRAY_SIZE(idt821034_sample_bits),833};834 835static int idt821034_dai_startup(struct snd_pcm_substream *substream,836				 struct snd_soc_dai *dai)837{838	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(dai->component);839	unsigned int max_ch = 0;840	int ret;841 842	max_ch = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?843		idt821034->max_ch_playback : idt821034->max_ch_capture;844 845	/*846	 * Disable stream support (min = 0, max = 0) if no timeslots were847	 * configured otherwise, limit the number of channels to those848	 * configured.849	 */850	ret = snd_pcm_hw_constraint_minmax(substream->runtime, SNDRV_PCM_HW_PARAM_CHANNELS,851					   max_ch ? 1 : 0, max_ch);852	if (ret < 0)853		return ret;854 855	ret = snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,856					 &idt821034_sample_bits_constr);857	if (ret)858		return ret;859 860	return 0;861}862 863static const u64 idt821034_dai_formats[] = {864	SND_SOC_POSSIBLE_DAIFMT_DSP_A	|865	SND_SOC_POSSIBLE_DAIFMT_DSP_B,866};867 868static const struct snd_soc_dai_ops idt821034_dai_ops = {869	.startup      = idt821034_dai_startup,870	.hw_params    = idt821034_dai_hw_params,871	.set_tdm_slot = idt821034_dai_set_tdm_slot,872	.set_fmt      = idt821034_dai_set_fmt,873	.auto_selectable_formats     = idt821034_dai_formats,874	.num_auto_selectable_formats = ARRAY_SIZE(idt821034_dai_formats),875};876 877static struct snd_soc_dai_driver idt821034_dai_driver = {878	.name = "idt821034",879	.playback = {880		.stream_name = "Playback",881		.channels_min = 1,882		.channels_max = IDT821034_NB_CHANNEL,883		.rates = SNDRV_PCM_RATE_8000,884		.formats = SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW,885	},886	.capture = {887		.stream_name = "Capture",888		.channels_min = 1,889		.channels_max = IDT821034_NB_CHANNEL,890		.rates = SNDRV_PCM_RATE_8000,891		.formats = SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW,892	},893	.ops = &idt821034_dai_ops,894};895 896static int idt821034_reset_audio(struct idt821034 *idt821034)897{898	int ret;899	u8 i;900 901	mutex_lock(&idt821034->mutex);902 903	ret = idt821034_set_codec_conf(idt821034, 0);904	if (ret)905		goto end;906 907	for (i = 0; i < IDT821034_NB_CHANNEL; i++) {908		idt821034->amps.ch[i].amp_out.gain = IDT821034_GAIN_OUT_INIT_RAW;909		idt821034->amps.ch[i].amp_out.is_muted = false;910		ret = idt821034_set_gain_channel(idt821034, i, IDT821034_GAIN_RX,911						 idt821034->amps.ch[i].amp_out.gain);912		if (ret)913			goto end;914 915		idt821034->amps.ch[i].amp_in.gain = IDT821034_GAIN_IN_INIT_RAW;916		idt821034->amps.ch[i].amp_in.is_muted = false;917		ret = idt821034_set_gain_channel(idt821034, i, IDT821034_GAIN_TX,918						 idt821034->amps.ch[i].amp_in.gain);919		if (ret)920			goto end;921 922		ret = idt821034_set_channel_power(idt821034, i, 0);923		if (ret)924			goto end;925	}926 927	ret = 0;928end:929	mutex_unlock(&idt821034->mutex);930	return ret;931}932 933static int idt821034_component_probe(struct snd_soc_component *component)934{935	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(component);936	int ret;937 938	/* reset idt821034 audio part*/939	ret = idt821034_reset_audio(idt821034);940	if (ret)941		return ret;942 943	return 0;944}945 946static const struct snd_soc_component_driver idt821034_component_driver = {947	.probe			= idt821034_component_probe,948	.controls		= idt821034_controls,949	.num_controls		= ARRAY_SIZE(idt821034_controls),950	.dapm_widgets		= idt821034_dapm_widgets,951	.num_dapm_widgets	= ARRAY_SIZE(idt821034_dapm_widgets),952	.dapm_routes		= idt821034_dapm_routes,953	.num_dapm_routes	= ARRAY_SIZE(idt821034_dapm_routes),954	.endianness		= 1,955};956 957#define IDT821034_GPIO_OFFSET_TO_SLIC_CHANNEL(_offset) (((_offset) / 5) % 4)958#define IDT821034_GPIO_OFFSET_TO_SLIC_MASK(_offset)    BIT((_offset) % 5)959 960static void idt821034_chip_gpio_set(struct gpio_chip *c, unsigned int offset, int val)961{962	u8 ch = IDT821034_GPIO_OFFSET_TO_SLIC_CHANNEL(offset);963	u8 mask = IDT821034_GPIO_OFFSET_TO_SLIC_MASK(offset);964	struct idt821034 *idt821034 = gpiochip_get_data(c);965	u8 slic_raw;966	int ret;967 968	mutex_lock(&idt821034->mutex);969 970	slic_raw = idt821034_get_written_slic_raw(idt821034, ch);971	if (val)972		slic_raw |= mask;973	else974		slic_raw &= ~mask;975	ret = idt821034_write_slic_raw(idt821034, ch, slic_raw);976	if (ret) {977		dev_err(&idt821034->spi->dev, "set gpio %d (%u, 0x%x) failed (%d)\n",978			offset, ch, mask, ret);979	}980 981	mutex_unlock(&idt821034->mutex);982}983 984static int idt821034_chip_gpio_get(struct gpio_chip *c, unsigned int offset)985{986	u8 ch = IDT821034_GPIO_OFFSET_TO_SLIC_CHANNEL(offset);987	u8 mask = IDT821034_GPIO_OFFSET_TO_SLIC_MASK(offset);988	struct idt821034 *idt821034 = gpiochip_get_data(c);989	u8 slic_raw;990	int ret;991 992	mutex_lock(&idt821034->mutex);993	ret = idt821034_read_slic_raw(idt821034, ch, &slic_raw);994	mutex_unlock(&idt821034->mutex);995	if (ret) {996		dev_err(&idt821034->spi->dev, "get gpio %d (%u, 0x%x) failed (%d)\n",997			offset, ch, mask, ret);998		return ret;999	}1000 1001	/*1002	 * SLIC IOs are read in reverse order compared to write.1003	 * Reverse the read value here in order to have IO0 at lsb (ie same1004	 * order as write)1005	 */1006	return !!(bitrev8(slic_raw) & mask);1007}1008 1009static int idt821034_chip_get_direction(struct gpio_chip *c, unsigned int offset)1010{1011	u8 ch = IDT821034_GPIO_OFFSET_TO_SLIC_CHANNEL(offset);1012	u8 mask = IDT821034_GPIO_OFFSET_TO_SLIC_MASK(offset);1013	struct idt821034 *idt821034 = gpiochip_get_data(c);1014	u8 slic_dir;1015 1016	mutex_lock(&idt821034->mutex);1017	slic_dir = idt821034_get_slic_conf(idt821034, ch);1018	mutex_unlock(&idt821034->mutex);1019 1020	return slic_dir & mask ? GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT;1021}1022 1023static int idt821034_chip_direction_input(struct gpio_chip *c, unsigned int offset)1024{1025	u8 ch = IDT821034_GPIO_OFFSET_TO_SLIC_CHANNEL(offset);1026	u8 mask = IDT821034_GPIO_OFFSET_TO_SLIC_MASK(offset);1027	struct idt821034 *idt821034 = gpiochip_get_data(c);1028	u8 slic_conf;1029	int ret;1030 1031	/* Only IO0 and IO1 can be set as input */1032	if (mask & ~(IDT821034_SLIC_IO1_IN | IDT821034_SLIC_IO0_IN))1033		return -EPERM;1034 1035	mutex_lock(&idt821034->mutex);1036 1037	slic_conf = idt821034_get_slic_conf(idt821034, ch) | mask;1038 1039	ret = idt821034_set_slic_conf(idt821034, ch, slic_conf);1040	if (ret) {1041		dev_err(&idt821034->spi->dev, "dir in gpio %d (%u, 0x%x) failed (%d)\n",1042			offset, ch, mask, ret);1043	}1044 1045	mutex_unlock(&idt821034->mutex);1046	return ret;1047}1048 1049static int idt821034_chip_direction_output(struct gpio_chip *c, unsigned int offset, int val)1050{1051	u8 ch = IDT821034_GPIO_OFFSET_TO_SLIC_CHANNEL(offset);1052	u8 mask = IDT821034_GPIO_OFFSET_TO_SLIC_MASK(offset);1053	struct idt821034 *idt821034 = gpiochip_get_data(c);1054	u8 slic_conf;1055	int ret;1056 1057	idt821034_chip_gpio_set(c, offset, val);1058 1059	mutex_lock(&idt821034->mutex);1060 1061	slic_conf = idt821034_get_slic_conf(idt821034, ch) & ~mask;1062 1063	ret = idt821034_set_slic_conf(idt821034, ch, slic_conf);1064	if (ret) {1065		dev_err(&idt821034->spi->dev, "dir in gpio %d (%u, 0x%x) failed (%d)\n",1066			offset, ch, mask, ret);1067	}1068 1069	mutex_unlock(&idt821034->mutex);1070	return ret;1071}1072 1073static int idt821034_reset_gpio(struct idt821034 *idt821034)1074{1075	int ret;1076	u8 i;1077 1078	mutex_lock(&idt821034->mutex);1079 1080	/* IO0 and IO1 as input for all channels and output IO set to 0 */1081	for (i = 0; i < IDT821034_NB_CHANNEL; i++) {1082		ret = idt821034_set_slic_conf(idt821034, i,1083					      IDT821034_SLIC_IO1_IN | IDT821034_SLIC_IO0_IN);1084		if (ret)1085			goto end;1086 1087		ret = idt821034_write_slic_raw(idt821034, i, 0);1088		if (ret)1089			goto end;1090 1091	}1092	ret = 0;1093end:1094	mutex_unlock(&idt821034->mutex);1095	return ret;1096}1097 1098static int idt821034_gpio_init(struct idt821034 *idt821034)1099{1100	int ret;1101 1102	ret = idt821034_reset_gpio(idt821034);1103	if (ret)1104		return ret;1105 1106	idt821034->gpio_chip.owner = THIS_MODULE;1107	idt821034->gpio_chip.label = dev_name(&idt821034->spi->dev);1108	idt821034->gpio_chip.parent = &idt821034->spi->dev;1109	idt821034->gpio_chip.base = -1;1110	idt821034->gpio_chip.ngpio = 5 * 4; /* 5 GPIOs on 4 channels */1111	idt821034->gpio_chip.get_direction = idt821034_chip_get_direction;1112	idt821034->gpio_chip.direction_input = idt821034_chip_direction_input;1113	idt821034->gpio_chip.direction_output = idt821034_chip_direction_output;1114	idt821034->gpio_chip.get = idt821034_chip_gpio_get;1115	idt821034->gpio_chip.set = idt821034_chip_gpio_set;1116	idt821034->gpio_chip.can_sleep = true;1117 1118	return devm_gpiochip_add_data(&idt821034->spi->dev, &idt821034->gpio_chip,1119				      idt821034);1120}1121 1122static int idt821034_spi_probe(struct spi_device *spi)1123{1124	struct idt821034 *idt821034;1125	int ret;1126 1127	spi->bits_per_word = 8;1128	ret = spi_setup(spi);1129	if (ret < 0)1130		return ret;1131 1132	idt821034 = devm_kzalloc(&spi->dev, sizeof(*idt821034), GFP_KERNEL);1133	if (!idt821034)1134		return -ENOMEM;1135 1136	idt821034->spi = spi;1137 1138	mutex_init(&idt821034->mutex);1139 1140	spi_set_drvdata(spi, idt821034);1141 1142	ret = devm_snd_soc_register_component(&spi->dev, &idt821034_component_driver,1143					      &idt821034_dai_driver, 1);1144	if (ret)1145		return ret;1146 1147	if (IS_ENABLED(CONFIG_GPIOLIB))1148		return idt821034_gpio_init(idt821034);1149 1150	return 0;1151}1152 1153static const struct of_device_id idt821034_of_match[] = {1154	{ .compatible = "renesas,idt821034", },1155	{ }1156};1157MODULE_DEVICE_TABLE(of, idt821034_of_match);1158 1159static const struct spi_device_id idt821034_id_table[] = {1160	{ "idt821034", 0 },1161	{ }1162};1163MODULE_DEVICE_TABLE(spi, idt821034_id_table);1164 1165static struct spi_driver idt821034_spi_driver = {1166	.driver  = {1167		.name   = "idt821034",1168		.of_match_table = idt821034_of_match,1169	},1170	.id_table = idt821034_id_table,1171	.probe  = idt821034_spi_probe,1172};1173 1174module_spi_driver(idt821034_spi_driver);1175 1176MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");1177MODULE_DESCRIPTION("IDT821034 ALSA SoC driver");1178MODULE_LICENSE("GPL");1179