brintos

brintos / linux-shallow public Read only

0
0
Text · 54.6 KiB · bb9ca63 Raw
2061 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// peb2466.c  --  Infineon PEB2466 ALSA SoC driver4//5// Copyright 2023 CS GROUP France6//7// Author: Herve Codina <herve.codina@bootlin.com>8 9#include <linux/unaligned.h>10#include <linux/clk.h>11#include <linux/firmware.h>12#include <linux/gpio/consumer.h>13#include <linux/gpio/driver.h>14#include <linux/module.h>15#include <linux/mutex.h>16#include <linux/slab.h>17#include <linux/spi/spi.h>18#include <sound/pcm_params.h>19#include <sound/soc.h>20#include <sound/tlv.h>21 22#define PEB2466_NB_CHANNEL	423 24struct peb2466_lookup {25	u8 (*table)[4];26	unsigned int count;27};28 29#define PEB2466_TLV_SIZE  (sizeof((unsigned int []){TLV_DB_SCALE_ITEM(0, 0, 0)}) / \30			   sizeof(unsigned int))31 32struct peb2466_lkup_ctrl {33	int reg;34	unsigned int index;35	const struct peb2466_lookup *lookup;36	unsigned int tlv_array[PEB2466_TLV_SIZE];37};38 39struct peb2466 {40	struct spi_device *spi;41	struct clk *mclk;42	struct gpio_desc *reset_gpio;43	u8 spi_tx_buf[2 + 8]; /* Cannot use stack area for SPI (dma-safe memory) */44	u8 spi_rx_buf[2 + 8]; /* Cannot use stack area for SPI (dma-safe memory) */45	struct regmap *regmap;46	struct {47		struct peb2466_lookup ax_lookup;48		struct peb2466_lookup ar_lookup;49		struct peb2466_lkup_ctrl ax_lkup_ctrl;50		struct peb2466_lkup_ctrl ar_lkup_ctrl;51		unsigned int tg1_freq_item;52		unsigned int tg2_freq_item;53	} ch[PEB2466_NB_CHANNEL];54	int max_chan_playback;55	int max_chan_capture;56	struct {57		struct gpio_chip gpio_chip;58		struct mutex lock;59		struct {60			unsigned int xr0;61			unsigned int xr1;62			unsigned int xr2;63			unsigned int xr3;64		} cache;65	} gpio;66};67 68#define PEB2466_CMD_R	(1 << 5)69#define PEB2466_CMD_W	(0 << 5)70 71#define PEB2466_CMD_MASK 0x1872#define PEB2466_CMD_XOP  0x18  /* XOP is 0bxxx11xxx */73#define PEB2466_CMD_SOP  0x10  /* SOP is 0bxxx10xxx */74#define PEB2466_CMD_COP  0x00  /* COP is 0bxxx0xxxx, handle 0bxxx00xxx */75#define PEB2466_CMD_COP1 0x08  /* COP is 0bxxx0xxxx, handle 0bxxx01xxx */76 77#define PEB2466_MAKE_XOP(_lsel)      (PEB2466_CMD_XOP | (_lsel))78#define PEB2466_MAKE_SOP(_ad, _lsel) (PEB2466_CMD_SOP | ((_ad) << 6) | (_lsel))79#define PEB2466_MAKE_COP(_ad, _code) (PEB2466_CMD_COP | ((_ad) << 6) | (_code))80 81#define PEB2466_CR0(_ch)	PEB2466_MAKE_SOP(_ch, 0x0)82#define   PEB2466_CR0_TH		(1 << 7)83#define   PEB2466_CR0_IMR1		(1 << 6)84#define   PEB2466_CR0_FRX		(1 << 5)85#define   PEB2466_CR0_FRR		(1 << 4)86#define   PEB2466_CR0_AX		(1 << 3)87#define   PEB2466_CR0_AR		(1 << 2)88#define   PEB2466_CR0_THSEL_MASK	(0x3 << 0)89#define   PEB2466_CR0_THSEL(_set)	((_set) << 0)90 91#define PEB2466_CR1(_ch)	PEB2466_MAKE_SOP(_ch, 0x1)92#define   PEB2466_CR1_ETG2		(1 << 7)93#define   PEB2466_CR1_ETG1		(1 << 6)94#define   PEB2466_CR1_PTG2		(1 << 5)95#define   PEB2466_CR1_PTG1		(1 << 4)96#define   PEB2466_CR1_LAW_MASK		(1 << 3)97#define   PEB2466_CR1_LAW_ALAW		(0 << 3)98#define   PEB2466_CR1_LAW_MULAW		(1 << 3)99#define   PEB2466_CR1_PU		(1 << 0)100 101#define PEB2466_CR2(_ch)	PEB2466_MAKE_SOP(_ch, 0x2)102#define PEB2466_CR3(_ch)	PEB2466_MAKE_SOP(_ch, 0x3)103#define PEB2466_CR4(_ch)	PEB2466_MAKE_SOP(_ch, 0x4)104#define PEB2466_CR5(_ch)	PEB2466_MAKE_SOP(_ch, 0x5)105 106#define PEB2466_XR0		PEB2466_MAKE_XOP(0x0)107#define PEB2466_XR1		PEB2466_MAKE_XOP(0x1)108#define PEB2466_XR2		PEB2466_MAKE_XOP(0x2)109#define PEB2466_XR3		PEB2466_MAKE_XOP(0x3)110#define PEB2466_XR4		PEB2466_MAKE_XOP(0x4)111#define PEB2466_XR5		PEB2466_MAKE_XOP(0x5)112#define   PEB2466_XR5_MCLK_1536		(0x0 << 6)113#define   PEB2466_XR5_MCLK_2048		(0x1 << 6)114#define   PEB2466_XR5_MCLK_4096		(0x2 << 6)115#define   PEB2466_XR5_MCLK_8192		(0x3 << 6)116 117#define PEB2466_XR6		PEB2466_MAKE_XOP(0x6)118#define   PEB2466_XR6_PCM_OFFSET(_off)	((_off) << 0)119 120#define PEB2466_XR7		PEB2466_MAKE_XOP(0x7)121 122#define PEB2466_TH_FILTER_P1(_ch)	PEB2466_MAKE_COP(_ch, 0x0)123#define PEB2466_TH_FILTER_P2(_ch)	PEB2466_MAKE_COP(_ch, 0x1)124#define PEB2466_TH_FILTER_P3(_ch)	PEB2466_MAKE_COP(_ch, 0x2)125#define PEB2466_IMR1_FILTER_P1(_ch)	PEB2466_MAKE_COP(_ch, 0x4)126#define PEB2466_IMR1_FILTER_P2(_ch)	PEB2466_MAKE_COP(_ch, 0x5)127#define PEB2466_FRX_FILTER(_ch)		PEB2466_MAKE_COP(_ch, 0x6)128#define PEB2466_FRR_FILTER(_ch)		PEB2466_MAKE_COP(_ch, 0x7)129#define PEB2466_AX_FILTER(_ch)		PEB2466_MAKE_COP(_ch, 0x8)130#define PEB2466_AR_FILTER(_ch)		PEB2466_MAKE_COP(_ch, 0x9)131#define PEB2466_TG1(_ch)		PEB2466_MAKE_COP(_ch, 0xc)132#define PEB2466_TG2(_ch)		PEB2466_MAKE_COP(_ch, 0xd)133 134static int peb2466_write_byte(struct peb2466 *peb2466, u8 cmd, u8 val)135{136	struct spi_transfer xfer = {137		.tx_buf = &peb2466->spi_tx_buf,138		.len = 2,139	};140 141	peb2466->spi_tx_buf[0] = cmd | PEB2466_CMD_W;142	peb2466->spi_tx_buf[1] = val;143 144	dev_dbg(&peb2466->spi->dev, "write byte (cmd %02x) %02x\n",145		peb2466->spi_tx_buf[0], peb2466->spi_tx_buf[1]);146 147	return spi_sync_transfer(peb2466->spi, &xfer, 1);148}149 150static int peb2466_read_byte(struct peb2466 *peb2466, u8 cmd, u8 *val)151{152	struct spi_transfer xfer = {153		.tx_buf = &peb2466->spi_tx_buf,154		.rx_buf = &peb2466->spi_rx_buf,155		.len = 3,156	};157	int ret;158 159	peb2466->spi_tx_buf[0] = cmd | PEB2466_CMD_R;160 161	ret = spi_sync_transfer(peb2466->spi, &xfer, 1);162	if (ret)163		return ret;164 165	if (peb2466->spi_rx_buf[1] != 0x81) {166		dev_err(&peb2466->spi->dev,167			"spi xfer rd (cmd %02x) invalid ident byte (0x%02x)\n",168			peb2466->spi_tx_buf[0], peb2466->spi_rx_buf[1]);169		return -EILSEQ;170	}171 172	*val = peb2466->spi_rx_buf[2];173 174	dev_dbg(&peb2466->spi->dev, "read byte (cmd %02x) %02x\n",175		peb2466->spi_tx_buf[0], *val);176 177	return 0;178}179 180static int peb2466_write_buf(struct peb2466 *peb2466, u8 cmd, const u8 *buf, unsigned int len)181{182	struct spi_transfer xfer = {183		.tx_buf = &peb2466->spi_tx_buf,184		.len = len + 1,185	};186 187	if (len > 8)188		return -EINVAL;189 190	peb2466->spi_tx_buf[0] = cmd | PEB2466_CMD_W;191	memcpy(&peb2466->spi_tx_buf[1], buf, len);192 193	dev_dbg(&peb2466->spi->dev, "write buf (cmd %02x, %u) %*ph\n",194		peb2466->spi_tx_buf[0], len, len, &peb2466->spi_tx_buf[1]);195 196	return spi_sync_transfer(peb2466->spi, &xfer, 1);197}198 199static int peb2466_reg_write(void *context, unsigned int reg, unsigned int val)200{201	struct peb2466 *peb2466 = context;202	int ret;203 204	/*205	 * Only XOP and SOP commands can be handled as registers.206	 * COP commands are handled using direct peb2466_write_buf() calls.207	 */208	switch (reg & PEB2466_CMD_MASK) {209	case PEB2466_CMD_XOP:210	case PEB2466_CMD_SOP:211		ret = peb2466_write_byte(peb2466, reg, val);212		break;213	default:214		dev_err(&peb2466->spi->dev, "Not a XOP or SOP command\n");215		ret = -EINVAL;216		break;217	}218	return ret;219}220 221static int peb2466_reg_read(void *context, unsigned int reg, unsigned int *val)222{223	struct peb2466 *peb2466 = context;224	int ret;225	u8 tmp;226 227	/* Only XOP and SOP commands can be handled as registers */228	switch (reg & PEB2466_CMD_MASK) {229	case PEB2466_CMD_XOP:230	case PEB2466_CMD_SOP:231		ret = peb2466_read_byte(peb2466, reg, &tmp);232		if (!ret)233			*val = tmp;234		break;235	default:236		dev_err(&peb2466->spi->dev, "Not a XOP or SOP command\n");237		ret = -EINVAL;238		break;239	}240	return ret;241}242 243static const struct regmap_config peb2466_regmap_config = {244	.reg_bits = 8,245	.val_bits = 8,246	.max_register = 0xFF,247	.reg_write = peb2466_reg_write,248	.reg_read = peb2466_reg_read,249	.cache_type = REGCACHE_NONE,250};251 252static int peb2466_lkup_ctrl_info(struct snd_kcontrol *kcontrol,253				  struct snd_ctl_elem_info *uinfo)254{255	struct peb2466_lkup_ctrl *lkup_ctrl =256		(struct peb2466_lkup_ctrl *)kcontrol->private_value;257 258	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;259	uinfo->count = 1;260	uinfo->value.integer.min = 0;261	uinfo->value.integer.max = lkup_ctrl->lookup->count - 1;262	return 0;263}264 265static int peb2466_lkup_ctrl_get(struct snd_kcontrol *kcontrol,266				 struct snd_ctl_elem_value *ucontrol)267{268	struct peb2466_lkup_ctrl *lkup_ctrl =269		(struct peb2466_lkup_ctrl *)kcontrol->private_value;270 271	ucontrol->value.integer.value[0] = lkup_ctrl->index;272	return 0;273}274 275static int peb2466_lkup_ctrl_put(struct snd_kcontrol *kcontrol,276				 struct snd_ctl_elem_value *ucontrol)277{278	struct peb2466_lkup_ctrl *lkup_ctrl =279		(struct peb2466_lkup_ctrl *)kcontrol->private_value;280	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);281	struct peb2466 *peb2466 = snd_soc_component_get_drvdata(component);282	unsigned int index;283	int ret;284 285	index = ucontrol->value.integer.value[0];286	if (index >= lkup_ctrl->lookup->count)287		return -EINVAL;288 289	if (index == lkup_ctrl->index)290		return 0;291 292	ret = peb2466_write_buf(peb2466, lkup_ctrl->reg,293				lkup_ctrl->lookup->table[index], 4);294	if (ret)295		return ret;296 297	lkup_ctrl->index = index;298	return 1; /* The value changed */299}300 301static int peb2466_add_lkup_ctrl(struct snd_soc_component *component,302				 struct peb2466_lkup_ctrl *lkup_ctrl,303				 const char *name, int min_val, int step)304{305	DECLARE_TLV_DB_SCALE(tlv_array, min_val, step, 0);306	struct snd_kcontrol_new control = {0};307 308	BUILD_BUG_ON(sizeof(lkup_ctrl->tlv_array) < sizeof(tlv_array));309	memcpy(lkup_ctrl->tlv_array, tlv_array, sizeof(tlv_array));310 311	control.iface = SNDRV_CTL_ELEM_IFACE_MIXER;312	control.name = name;313	control.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |314			 SNDRV_CTL_ELEM_ACCESS_READWRITE;315	control.tlv.p = lkup_ctrl->tlv_array;316	control.info = peb2466_lkup_ctrl_info;317	control.get = peb2466_lkup_ctrl_get;318	control.put = peb2466_lkup_ctrl_put;319	control.private_value = (unsigned long)lkup_ctrl;320 321	return snd_soc_add_component_controls(component, &control, 1);322}323 324enum peb2466_tone_freq {325	PEB2466_TONE_697HZ,326	PEB2466_TONE_800HZ,327	PEB2466_TONE_950HZ,328	PEB2466_TONE_1000HZ,329	PEB2466_TONE_1008HZ,330	PEB2466_TONE_2000HZ,331};332 333static const u8 peb2466_tone_lookup[][4] = {334	[PEB2466_TONE_697HZ] = {0x0a, 0x33, 0x5a, 0x2c},335	[PEB2466_TONE_800HZ] = {0x12, 0xD6, 0x5a, 0xc0},336	[PEB2466_TONE_950HZ] = {0x1c, 0xf0, 0x5c, 0xc0},337	[PEB2466_TONE_1000HZ] = {0}, /* lookup value not used for 1000Hz */338	[PEB2466_TONE_1008HZ] = {0x1a, 0xae, 0x57, 0x70},339	[PEB2466_TONE_2000HZ] = {0x00, 0x80, 0x50, 0x09},340};341 342static const char * const peb2466_tone_freq_txt[] = {343	[PEB2466_TONE_697HZ] = "697Hz",344	[PEB2466_TONE_800HZ] = "800Hz",345	[PEB2466_TONE_950HZ] = "950Hz",346	[PEB2466_TONE_1000HZ] = "1000Hz",347	[PEB2466_TONE_1008HZ] = "1008Hz",348	[PEB2466_TONE_2000HZ] = "2000Hz"349};350 351static const struct soc_enum peb2466_tg_freq[][2] = {352	[0] = {353		SOC_ENUM_SINGLE(PEB2466_TG1(0), 0, ARRAY_SIZE(peb2466_tone_freq_txt),354				peb2466_tone_freq_txt),355		SOC_ENUM_SINGLE(PEB2466_TG2(0), 0, ARRAY_SIZE(peb2466_tone_freq_txt),356				peb2466_tone_freq_txt)357	},358	[1] = {359		SOC_ENUM_SINGLE(PEB2466_TG1(1), 0, ARRAY_SIZE(peb2466_tone_freq_txt),360				peb2466_tone_freq_txt),361		SOC_ENUM_SINGLE(PEB2466_TG2(1), 0, ARRAY_SIZE(peb2466_tone_freq_txt),362				peb2466_tone_freq_txt)363	},364	[2] = {365		SOC_ENUM_SINGLE(PEB2466_TG1(2), 0, ARRAY_SIZE(peb2466_tone_freq_txt),366				peb2466_tone_freq_txt),367		SOC_ENUM_SINGLE(PEB2466_TG2(2), 0, ARRAY_SIZE(peb2466_tone_freq_txt),368				peb2466_tone_freq_txt)369	},370	[3] = {371		SOC_ENUM_SINGLE(PEB2466_TG1(3), 0, ARRAY_SIZE(peb2466_tone_freq_txt),372				peb2466_tone_freq_txt),373		SOC_ENUM_SINGLE(PEB2466_TG2(3), 0, ARRAY_SIZE(peb2466_tone_freq_txt),374				peb2466_tone_freq_txt)375	}376};377 378static int peb2466_tg_freq_get(struct snd_kcontrol *kcontrol,379			       struct snd_ctl_elem_value *ucontrol)380{381	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);382	struct peb2466 *peb2466 = snd_soc_component_get_drvdata(component);383	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;384 385	switch (e->reg) {386	case PEB2466_TG1(0):387		ucontrol->value.enumerated.item[0] = peb2466->ch[0].tg1_freq_item;388		break;389	case PEB2466_TG2(0):390		ucontrol->value.enumerated.item[0] = peb2466->ch[0].tg2_freq_item;391		break;392	case PEB2466_TG1(1):393		ucontrol->value.enumerated.item[0] = peb2466->ch[1].tg1_freq_item;394		break;395	case PEB2466_TG2(1):396		ucontrol->value.enumerated.item[0] = peb2466->ch[1].tg2_freq_item;397		break;398	case PEB2466_TG1(2):399		ucontrol->value.enumerated.item[0] = peb2466->ch[2].tg1_freq_item;400		break;401	case PEB2466_TG2(2):402		ucontrol->value.enumerated.item[0] = peb2466->ch[2].tg2_freq_item;403		break;404	case PEB2466_TG1(3):405		ucontrol->value.enumerated.item[0] = peb2466->ch[3].tg1_freq_item;406		break;407	case PEB2466_TG2(3):408		ucontrol->value.enumerated.item[0] = peb2466->ch[3].tg2_freq_item;409		break;410	default:411		return -EINVAL;412	}413	return 0;414}415 416static int peb2466_tg_freq_put(struct snd_kcontrol *kcontrol,417			       struct snd_ctl_elem_value *ucontrol)418{419	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);420	struct peb2466 *peb2466 = snd_soc_component_get_drvdata(component);421	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;422	unsigned int *tg_freq_item;423	u8 cr1_reg, cr1_mask;424	unsigned int index;425	int ret;426 427	index = ucontrol->value.enumerated.item[0];428 429	if (index >= ARRAY_SIZE(peb2466_tone_lookup))430		return -EINVAL;431 432	switch (e->reg) {433	case PEB2466_TG1(0):434		tg_freq_item = &peb2466->ch[0].tg1_freq_item;435		cr1_reg = PEB2466_CR1(0);436		cr1_mask = PEB2466_CR1_PTG1;437		break;438	case PEB2466_TG2(0):439		tg_freq_item = &peb2466->ch[0].tg2_freq_item;440		cr1_reg = PEB2466_CR1(0);441		cr1_mask = PEB2466_CR1_PTG2;442		break;443	case PEB2466_TG1(1):444		tg_freq_item = &peb2466->ch[1].tg1_freq_item;445		cr1_reg = PEB2466_CR1(1);446		cr1_mask = PEB2466_CR1_PTG1;447		break;448	case PEB2466_TG2(1):449		tg_freq_item = &peb2466->ch[1].tg2_freq_item;450		cr1_reg = PEB2466_CR1(1);451		cr1_mask = PEB2466_CR1_PTG2;452		break;453	case PEB2466_TG1(2):454		tg_freq_item = &peb2466->ch[2].tg1_freq_item;455		cr1_reg = PEB2466_CR1(2);456		cr1_mask = PEB2466_CR1_PTG1;457		break;458	case PEB2466_TG2(2):459		tg_freq_item = &peb2466->ch[2].tg2_freq_item;460		cr1_reg = PEB2466_CR1(2);461		cr1_mask = PEB2466_CR1_PTG2;462		break;463	case PEB2466_TG1(3):464		tg_freq_item = &peb2466->ch[3].tg1_freq_item;465		cr1_reg = PEB2466_CR1(3);466		cr1_mask = PEB2466_CR1_PTG1;467		break;468	case PEB2466_TG2(3):469		tg_freq_item = &peb2466->ch[3].tg2_freq_item;470		cr1_reg = PEB2466_CR1(3);471		cr1_mask = PEB2466_CR1_PTG2;472		break;473	default:474		return -EINVAL;475	}476 477	if (index == *tg_freq_item)478		return 0;479 480	if (index == PEB2466_TONE_1000HZ) {481		ret = regmap_update_bits(peb2466->regmap, cr1_reg, cr1_mask, 0);482		if (ret)483			return ret;484	} else {485		ret = peb2466_write_buf(peb2466, e->reg, peb2466_tone_lookup[index], 4);486		if (ret)487			return ret;488		ret = regmap_update_bits(peb2466->regmap, cr1_reg, cr1_mask, cr1_mask);489		if (ret)490			return ret;491	}492 493	*tg_freq_item = index;494	return 1; /* The value changed */495}496 497static const struct snd_kcontrol_new peb2466_ch0_out_mix_controls[] = {498	SOC_DAPM_SINGLE("TG1 Switch", PEB2466_CR1(0), 6, 1, 0),499	SOC_DAPM_SINGLE("TG2 Switch", PEB2466_CR1(0), 7, 1, 0),500	SOC_DAPM_SINGLE("Voice Switch", PEB2466_CR2(0), 0, 1, 0)501};502 503static const struct snd_kcontrol_new peb2466_ch1_out_mix_controls[] = {504	SOC_DAPM_SINGLE("TG1 Switch", PEB2466_CR1(1), 6, 1, 0),505	SOC_DAPM_SINGLE("TG2 Switch", PEB2466_CR1(1), 7, 1, 0),506	SOC_DAPM_SINGLE("Voice Switch", PEB2466_CR2(1), 0, 1, 0)507};508 509static const struct snd_kcontrol_new peb2466_ch2_out_mix_controls[] = {510	SOC_DAPM_SINGLE("TG1 Switch", PEB2466_CR1(2), 6, 1, 0),511	SOC_DAPM_SINGLE("TG2 Switch", PEB2466_CR1(2), 7, 1, 0),512	SOC_DAPM_SINGLE("Voice Switch", PEB2466_CR2(2), 0, 1, 0)513};514 515static const struct snd_kcontrol_new peb2466_ch3_out_mix_controls[] = {516	SOC_DAPM_SINGLE("TG1 Switch", PEB2466_CR1(3), 6, 1, 0),517	SOC_DAPM_SINGLE("TG2 Switch", PEB2466_CR1(3), 7, 1, 0),518	SOC_DAPM_SINGLE("Voice Switch", PEB2466_CR2(3), 0, 1, 0)519};520 521static const struct snd_kcontrol_new peb2466_controls[] = {522	/* Attenuators */523	SOC_SINGLE("DAC0 -6dB Playback Switch", PEB2466_CR3(0), 2, 1, 0),524	SOC_SINGLE("DAC1 -6dB Playback Switch", PEB2466_CR3(1), 2, 1, 0),525	SOC_SINGLE("DAC2 -6dB Playback Switch", PEB2466_CR3(2), 2, 1, 0),526	SOC_SINGLE("DAC3 -6dB Playback Switch", PEB2466_CR3(3), 2, 1, 0),527 528	/* Amplifiers */529	SOC_SINGLE("ADC0 +6dB Capture Switch", PEB2466_CR3(0), 3, 1, 0),530	SOC_SINGLE("ADC1 +6dB Capture Switch", PEB2466_CR3(1), 3, 1, 0),531	SOC_SINGLE("ADC2 +6dB Capture Switch", PEB2466_CR3(2), 3, 1, 0),532	SOC_SINGLE("ADC3 +6dB Capture Switch", PEB2466_CR3(3), 3, 1, 0),533 534	/* Tone generators */535	SOC_ENUM_EXT("DAC0 TG1 Freq", peb2466_tg_freq[0][0],536		     peb2466_tg_freq_get, peb2466_tg_freq_put),537	SOC_ENUM_EXT("DAC1 TG1 Freq", peb2466_tg_freq[1][0],538		     peb2466_tg_freq_get, peb2466_tg_freq_put),539	SOC_ENUM_EXT("DAC2 TG1 Freq", peb2466_tg_freq[2][0],540		     peb2466_tg_freq_get, peb2466_tg_freq_put),541	SOC_ENUM_EXT("DAC3 TG1 Freq", peb2466_tg_freq[3][0],542		     peb2466_tg_freq_get, peb2466_tg_freq_put),543 544	SOC_ENUM_EXT("DAC0 TG2 Freq", peb2466_tg_freq[0][1],545		     peb2466_tg_freq_get, peb2466_tg_freq_put),546	SOC_ENUM_EXT("DAC1 TG2 Freq", peb2466_tg_freq[1][1],547		     peb2466_tg_freq_get, peb2466_tg_freq_put),548	SOC_ENUM_EXT("DAC2 TG2 Freq", peb2466_tg_freq[2][1],549		     peb2466_tg_freq_get, peb2466_tg_freq_put),550	SOC_ENUM_EXT("DAC3 TG2 Freq", peb2466_tg_freq[3][1],551		     peb2466_tg_freq_get, peb2466_tg_freq_put),552};553 554static const struct snd_soc_dapm_widget peb2466_dapm_widgets[] = {555	SND_SOC_DAPM_SUPPLY("CH0 PWR", PEB2466_CR1(0), 0, 0, NULL, 0),556	SND_SOC_DAPM_SUPPLY("CH1 PWR", PEB2466_CR1(1), 0, 0, NULL, 0),557	SND_SOC_DAPM_SUPPLY("CH2 PWR", PEB2466_CR1(2), 0, 0, NULL, 0),558	SND_SOC_DAPM_SUPPLY("CH3 PWR", PEB2466_CR1(3), 0, 0, NULL, 0),559 560	SND_SOC_DAPM_DAC("CH0 DIN", "Playback", SND_SOC_NOPM, 0, 0),561	SND_SOC_DAPM_DAC("CH1 DIN", "Playback", SND_SOC_NOPM, 0, 0),562	SND_SOC_DAPM_DAC("CH2 DIN", "Playback", SND_SOC_NOPM, 0, 0),563	SND_SOC_DAPM_DAC("CH3 DIN", "Playback", SND_SOC_NOPM, 0, 0),564 565	SND_SOC_DAPM_SIGGEN("CH0 TG1"),566	SND_SOC_DAPM_SIGGEN("CH1 TG1"),567	SND_SOC_DAPM_SIGGEN("CH2 TG1"),568	SND_SOC_DAPM_SIGGEN("CH3 TG1"),569 570	SND_SOC_DAPM_SIGGEN("CH0 TG2"),571	SND_SOC_DAPM_SIGGEN("CH1 TG2"),572	SND_SOC_DAPM_SIGGEN("CH2 TG2"),573	SND_SOC_DAPM_SIGGEN("CH3 TG2"),574 575	SND_SOC_DAPM_MIXER("DAC0 Mixer", SND_SOC_NOPM, 0, 0,576			   peb2466_ch0_out_mix_controls,577			   ARRAY_SIZE(peb2466_ch0_out_mix_controls)),578	SND_SOC_DAPM_MIXER("DAC1 Mixer", SND_SOC_NOPM, 0, 0,579			   peb2466_ch1_out_mix_controls,580			   ARRAY_SIZE(peb2466_ch1_out_mix_controls)),581	SND_SOC_DAPM_MIXER("DAC2 Mixer", SND_SOC_NOPM, 0, 0,582			   peb2466_ch2_out_mix_controls,583			   ARRAY_SIZE(peb2466_ch2_out_mix_controls)),584	SND_SOC_DAPM_MIXER("DAC3 Mixer", SND_SOC_NOPM, 0, 0,585			   peb2466_ch3_out_mix_controls,586			   ARRAY_SIZE(peb2466_ch3_out_mix_controls)),587 588	SND_SOC_DAPM_PGA("DAC0 PGA", SND_SOC_NOPM, 0, 0, NULL, 0),589	SND_SOC_DAPM_PGA("DAC1 PGA", SND_SOC_NOPM, 0, 0, NULL, 0),590	SND_SOC_DAPM_PGA("DAC2 PGA", SND_SOC_NOPM, 0, 0, NULL, 0),591	SND_SOC_DAPM_PGA("DAC3 PGA", SND_SOC_NOPM, 0, 0, NULL, 0),592 593	SND_SOC_DAPM_OUTPUT("OUT0"),594	SND_SOC_DAPM_OUTPUT("OUT1"),595	SND_SOC_DAPM_OUTPUT("OUT2"),596	SND_SOC_DAPM_OUTPUT("OUT3"),597 598	SND_SOC_DAPM_INPUT("IN0"),599	SND_SOC_DAPM_INPUT("IN1"),600	SND_SOC_DAPM_INPUT("IN2"),601	SND_SOC_DAPM_INPUT("IN3"),602 603	SND_SOC_DAPM_DAC("ADC0", "Capture", SND_SOC_NOPM, 0, 0),604	SND_SOC_DAPM_DAC("ADC1", "Capture", SND_SOC_NOPM, 0, 0),605	SND_SOC_DAPM_DAC("ADC2", "Capture", SND_SOC_NOPM, 0, 0),606	SND_SOC_DAPM_DAC("ADC3", "Capture", SND_SOC_NOPM, 0, 0),607};608 609static const struct snd_soc_dapm_route peb2466_dapm_routes[] = {610	{ "CH0 DIN", NULL, "CH0 PWR" },611	{ "CH1 DIN", NULL, "CH1 PWR" },612	{ "CH2 DIN", NULL, "CH2 PWR" },613	{ "CH3 DIN", NULL, "CH3 PWR" },614 615	{ "CH0 TG1", NULL, "CH0 PWR" },616	{ "CH1 TG1", NULL, "CH1 PWR" },617	{ "CH2 TG1", NULL, "CH2 PWR" },618	{ "CH3 TG1", NULL, "CH3 PWR" },619 620	{ "CH0 TG2", NULL, "CH0 PWR" },621	{ "CH1 TG2", NULL, "CH1 PWR" },622	{ "CH2 TG2", NULL, "CH2 PWR" },623	{ "CH3 TG2", NULL, "CH3 PWR" },624 625	{ "DAC0 Mixer", "TG1 Switch", "CH0 TG1" },626	{ "DAC0 Mixer", "TG2 Switch", "CH0 TG2" },627	{ "DAC0 Mixer", "Voice Switch", "CH0 DIN" },628	{ "DAC0 Mixer", NULL, "CH0 DIN" },629 630	{ "DAC1 Mixer", "TG1 Switch", "CH1 TG1" },631	{ "DAC1 Mixer", "TG2 Switch", "CH1 TG2" },632	{ "DAC1 Mixer", "Voice Switch", "CH1 DIN" },633	{ "DAC1 Mixer", NULL, "CH1 DIN" },634 635	{ "DAC2 Mixer", "TG1 Switch", "CH2 TG1" },636	{ "DAC2 Mixer", "TG2 Switch", "CH2 TG2" },637	{ "DAC2 Mixer", "Voice Switch", "CH2 DIN" },638	{ "DAC2 Mixer", NULL, "CH2 DIN" },639 640	{ "DAC3 Mixer", "TG1 Switch", "CH3 TG1" },641	{ "DAC3 Mixer", "TG2 Switch", "CH3 TG2" },642	{ "DAC3 Mixer", "Voice Switch", "CH3 DIN" },643	{ "DAC3 Mixer", NULL, "CH3 DIN" },644 645	{ "DAC0 PGA", NULL, "DAC0 Mixer" },646	{ "DAC1 PGA", NULL, "DAC1 Mixer" },647	{ "DAC2 PGA", NULL, "DAC2 Mixer" },648	{ "DAC3 PGA", NULL, "DAC3 Mixer" },649 650	{ "OUT0", NULL, "DAC0 PGA" },651	{ "OUT1", NULL, "DAC1 PGA" },652	{ "OUT2", NULL, "DAC2 PGA" },653	{ "OUT3", NULL, "DAC3 PGA" },654 655	{ "ADC0", NULL, "IN0" },656	{ "ADC1", NULL, "IN1" },657	{ "ADC2", NULL, "IN2" },658	{ "ADC3", NULL, "IN3" },659 660	{ "ADC0", NULL, "CH0 PWR" },661	{ "ADC1", NULL, "CH1 PWR" },662	{ "ADC2", NULL, "CH2 PWR" },663	{ "ADC3", NULL, "CH3 PWR" },664};665 666static int peb2466_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,667				    unsigned int rx_mask, int slots, int width)668{669	struct peb2466 *peb2466 = snd_soc_component_get_drvdata(dai->component);670	unsigned int chan;671	unsigned int mask;672	u8 slot;673	int ret;674 675	switch (width) {676	case 0:677		/* Not set -> default 8 */678	case 8:679		break;680	default:681		dev_err(dai->dev, "tdm slot width %d not supported\n", width);682		return -EINVAL;683	}684 685	mask = tx_mask;686	slot = 0;687	chan = 0;688	while (mask && chan < PEB2466_NB_CHANNEL) {689		if (mask & 0x1) {690			ret = regmap_write(peb2466->regmap, PEB2466_CR5(chan), slot);691			if (ret) {692				dev_err(dai->dev, "chan %d set tx tdm slot failed (%d)\n",693					chan, ret);694				return ret;695			}696			chan++;697		}698		mask >>= 1;699		slot++;700	}701	if (mask) {702		dev_err(dai->dev, "too much tx slots defined (mask = 0x%x) support max %d\n",703			tx_mask, PEB2466_NB_CHANNEL);704		return -EINVAL;705	}706	peb2466->max_chan_playback = chan;707 708	mask = rx_mask;709	slot = 0;710	chan = 0;711	while (mask && chan < PEB2466_NB_CHANNEL) {712		if (mask & 0x1) {713			ret = regmap_write(peb2466->regmap, PEB2466_CR4(chan), slot);714			if (ret) {715				dev_err(dai->dev, "chan %d set rx tdm slot failed (%d)\n",716					chan, ret);717				return ret;718			}719			chan++;720		}721		mask >>= 1;722		slot++;723	}724	if (mask) {725		dev_err(dai->dev, "too much rx slots defined (mask = 0x%x) support max %d\n",726			rx_mask, PEB2466_NB_CHANNEL);727		return -EINVAL;728	}729	peb2466->max_chan_capture = chan;730 731	return 0;732}733 734static int peb2466_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)735{736	struct peb2466 *peb2466 = snd_soc_component_get_drvdata(dai->component);737	u8 xr6;738 739	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {740	case SND_SOC_DAIFMT_DSP_A:741		xr6 = PEB2466_XR6_PCM_OFFSET(1);742		break;743	case SND_SOC_DAIFMT_DSP_B:744		xr6 = PEB2466_XR6_PCM_OFFSET(0);745		break;746	default:747		dev_err(dai->dev, "Unsupported format 0x%x\n",748			fmt & SND_SOC_DAIFMT_FORMAT_MASK);749		return -EINVAL;750	}751	return regmap_write(peb2466->regmap, PEB2466_XR6, xr6);752}753 754static int peb2466_dai_hw_params(struct snd_pcm_substream *substream,755				 struct snd_pcm_hw_params *params,756				 struct snd_soc_dai *dai)757{758	struct peb2466 *peb2466 = snd_soc_component_get_drvdata(dai->component);759	unsigned int ch;760	int ret;761	u8 cr1;762 763	switch (params_format(params)) {764	case SNDRV_PCM_FORMAT_MU_LAW:765		cr1 = PEB2466_CR1_LAW_MULAW;766		break;767	case SNDRV_PCM_FORMAT_A_LAW:768		cr1 = PEB2466_CR1_LAW_ALAW;769		break;770	default:771		dev_err(&peb2466->spi->dev, "Unsupported format 0x%x\n",772			params_format(params));773		return -EINVAL;774	}775 776	for (ch = 0; ch < PEB2466_NB_CHANNEL; ch++) {777		ret = regmap_update_bits(peb2466->regmap, PEB2466_CR1(ch),778					 PEB2466_CR1_LAW_MASK, cr1);779		if (ret)780			return ret;781	}782 783	return 0;784}785 786static const unsigned int peb2466_sample_bits[] = {8};787 788static struct snd_pcm_hw_constraint_list peb2466_sample_bits_constr = {789	.list = peb2466_sample_bits,790	.count = ARRAY_SIZE(peb2466_sample_bits),791};792 793static int peb2466_dai_startup(struct snd_pcm_substream *substream,794			       struct snd_soc_dai *dai)795{796	struct peb2466 *peb2466 = snd_soc_component_get_drvdata(dai->component);797	unsigned int max_ch;798	int ret;799 800	max_ch = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?801		peb2466->max_chan_playback : peb2466->max_chan_capture;802 803	/*804	 * Disable stream support (min = 0, max = 0) if no timeslots were805	 * configured.806	 */807	ret = snd_pcm_hw_constraint_minmax(substream->runtime,808					   SNDRV_PCM_HW_PARAM_CHANNELS,809					   max_ch ? 1 : 0, max_ch);810	if (ret < 0)811		return ret;812 813	return snd_pcm_hw_constraint_list(substream->runtime, 0,814					  SNDRV_PCM_HW_PARAM_SAMPLE_BITS,815					  &peb2466_sample_bits_constr);816}817 818static const u64 peb2466_dai_formats[] = {819	SND_SOC_POSSIBLE_DAIFMT_DSP_A	|820	SND_SOC_POSSIBLE_DAIFMT_DSP_B,821};822 823static const struct snd_soc_dai_ops peb2466_dai_ops = {824	.startup = peb2466_dai_startup,825	.hw_params = peb2466_dai_hw_params,826	.set_tdm_slot = peb2466_dai_set_tdm_slot,827	.set_fmt = peb2466_dai_set_fmt,828	.auto_selectable_formats     = peb2466_dai_formats,829	.num_auto_selectable_formats = ARRAY_SIZE(peb2466_dai_formats),830};831 832static struct snd_soc_dai_driver peb2466_dai_driver = {833	.name = "peb2466",834	.playback = {835		.stream_name = "Playback",836		.channels_min = 1,837		.channels_max = PEB2466_NB_CHANNEL,838		.rates = SNDRV_PCM_RATE_8000,839		.formats = SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW,840	},841	.capture = {842		.stream_name = "Capture",843		.channels_min = 1,844		.channels_max = PEB2466_NB_CHANNEL,845		.rates = SNDRV_PCM_RATE_8000,846		.formats = SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW,847	},848	.ops = &peb2466_dai_ops,849};850 851static int peb2466_reset_audio(struct peb2466 *peb2466)852{853	static const struct reg_sequence reg_reset[] = {854		{  .reg = PEB2466_XR6,    .def = 0x00 },855 856		{  .reg = PEB2466_CR5(0), .def = 0x00 },857		{  .reg = PEB2466_CR4(0), .def = 0x00 },858		{  .reg = PEB2466_CR3(0), .def = 0x00 },859		{  .reg = PEB2466_CR2(0), .def = 0x00 },860		{  .reg = PEB2466_CR1(0), .def = 0x00 },861		{  .reg = PEB2466_CR0(0), .def = PEB2466_CR0_IMR1 },862 863		{  .reg = PEB2466_CR5(1), .def = 0x00 },864		{  .reg = PEB2466_CR4(1), .def = 0x00 },865		{  .reg = PEB2466_CR3(1), .def = 0x00 },866		{  .reg = PEB2466_CR2(1), .def = 0x00 },867		{  .reg = PEB2466_CR1(1), .def = 0x00 },868		{  .reg = PEB2466_CR0(1), .def = PEB2466_CR0_IMR1 },869 870		{  .reg = PEB2466_CR5(2), .def = 0x00 },871		{  .reg = PEB2466_CR4(2), .def = 0x00 },872		{  .reg = PEB2466_CR3(2), .def = 0x00 },873		{  .reg = PEB2466_CR2(2), .def = 0x00 },874		{  .reg = PEB2466_CR1(2), .def = 0x00 },875		{  .reg = PEB2466_CR0(2), .def = PEB2466_CR0_IMR1 },876 877		{  .reg = PEB2466_CR5(3), .def = 0x00 },878		{  .reg = PEB2466_CR4(3), .def = 0x00 },879		{  .reg = PEB2466_CR3(3), .def = 0x00 },880		{  .reg = PEB2466_CR2(3), .def = 0x00 },881		{  .reg = PEB2466_CR1(3), .def = 0x00 },882		{  .reg = PEB2466_CR0(3), .def = PEB2466_CR0_IMR1 },883	};884	static const u8 imr1_p1[8] = {0x00, 0x90, 0x09, 0x00, 0x90, 0x09, 0x00, 0x00};885	static const u8 imr1_p2[8] = {0x7F, 0xFF, 0x00, 0x00, 0x90, 0x14, 0x40, 0x08};886	static const u8 zero[8] = {0};887	int ret;888	int i;889 890	for (i = 0; i < ARRAY_SIZE(peb2466->ch); i++) {891		peb2466->ch[i].tg1_freq_item = PEB2466_TONE_1000HZ;892		peb2466->ch[i].tg2_freq_item = PEB2466_TONE_1000HZ;893 894		/*895		 * Even if not used, disabling IM/R1 filter is not recommended.896		 * Instead, we must configure it with default coefficients and897		 * enable it.898		 * The filter will be enabled right after (in the following899		 * regmap_multi_reg_write() call).900		 */901		ret = peb2466_write_buf(peb2466, PEB2466_IMR1_FILTER_P1(i), imr1_p1, 8);902		if (ret)903			return ret;904		ret = peb2466_write_buf(peb2466, PEB2466_IMR1_FILTER_P2(i), imr1_p2, 8);905		if (ret)906			return ret;907 908		/* Set all other filters coefficients to zero */909		ret = peb2466_write_buf(peb2466, PEB2466_TH_FILTER_P1(i), zero, 8);910		if (ret)911			return ret;912		ret = peb2466_write_buf(peb2466, PEB2466_TH_FILTER_P2(i), zero, 8);913		if (ret)914			return ret;915		ret = peb2466_write_buf(peb2466, PEB2466_TH_FILTER_P3(i), zero, 8);916		if (ret)917			return ret;918		ret = peb2466_write_buf(peb2466, PEB2466_FRX_FILTER(i), zero, 8);919		if (ret)920			return ret;921		ret = peb2466_write_buf(peb2466, PEB2466_FRR_FILTER(i), zero, 8);922		if (ret)923			return ret;924		ret = peb2466_write_buf(peb2466, PEB2466_AX_FILTER(i), zero, 4);925		if (ret)926			return ret;927		ret = peb2466_write_buf(peb2466, PEB2466_AR_FILTER(i), zero, 4);928		if (ret)929			return ret;930	}931 932	return regmap_multi_reg_write(peb2466->regmap, reg_reset, ARRAY_SIZE(reg_reset));933}934 935static int peb2466_fw_parse_thfilter(struct snd_soc_component *component,936				     u16 tag, u32 lng, const u8 *data)937{938	struct peb2466 *peb2466 = snd_soc_component_get_drvdata(component);939	u8 mask;940	int ret;941	int i;942 943	dev_info(component->dev, "fw TH filter: mask %x, %*phN\n", *data,944		 lng - 1, data + 1);945 946	/*947	 * TH_FILTER TLV data:948	 *   - @0  1 byte:  Chan mask (bit set means related channel is concerned)949	 *   - @1  8 bytes: TH-Filter coefficients part1950	 *   - @9  8 bytes: TH-Filter coefficients part2951	 *   - @17 8 bytes: TH-Filter coefficients part3952	 */953	mask = *data;954	for (i = 0; i < ARRAY_SIZE(peb2466->ch); i++) {955		if (!(mask & (1 << i)))956			continue;957 958		ret = regmap_update_bits(peb2466->regmap, PEB2466_CR0(i),959					 PEB2466_CR0_TH, 0);960		if (ret)961			return ret;962 963		ret = peb2466_write_buf(peb2466, PEB2466_TH_FILTER_P1(i), data + 1, 8);964		if (ret)965			return ret;966 967		ret = peb2466_write_buf(peb2466, PEB2466_TH_FILTER_P2(i), data + 9, 8);968		if (ret)969			return ret;970 971		ret = peb2466_write_buf(peb2466, PEB2466_TH_FILTER_P3(i), data + 17, 8);972		if (ret)973			return ret;974 975		ret = regmap_update_bits(peb2466->regmap, PEB2466_CR0(i),976					 PEB2466_CR0_TH | PEB2466_CR0_THSEL_MASK,977					 PEB2466_CR0_TH | PEB2466_CR0_THSEL(i));978		if (ret)979			return ret;980	}981	return 0;982}983 984static int peb2466_fw_parse_imr1filter(struct snd_soc_component *component,985				       u16 tag, u32 lng, const u8 *data)986{987	struct peb2466 *peb2466 = snd_soc_component_get_drvdata(component);988	u8 mask;989	int ret;990	int i;991 992	dev_info(component->dev, "fw IM/R1 filter: mask %x, %*phN\n", *data,993		 lng - 1, data + 1);994 995	/*996	 * IMR1_FILTER TLV data:997	 *   - @0 1 byte:  Chan mask (bit set means related channel is concerned)998	 *   - @1 8 bytes: IM/R1-Filter coefficients part1999	 *   - @9 8 bytes: IM/R1-Filter coefficients part21000	 */1001	mask = *data;1002	for (i = 0; i < ARRAY_SIZE(peb2466->ch); i++) {1003		if (!(mask & (1 << i)))1004			continue;1005 1006		ret = regmap_update_bits(peb2466->regmap, PEB2466_CR0(i),1007					 PEB2466_CR0_IMR1, 0);1008		if (ret)1009			return ret;1010 1011		ret = peb2466_write_buf(peb2466, PEB2466_IMR1_FILTER_P1(i), data + 1, 8);1012		if (ret)1013			return ret;1014 1015		ret = peb2466_write_buf(peb2466, PEB2466_IMR1_FILTER_P2(i), data + 9, 8);1016		if (ret)1017			return ret;1018 1019		ret = regmap_update_bits(peb2466->regmap, PEB2466_CR0(i),1020					 PEB2466_CR0_IMR1, PEB2466_CR0_IMR1);1021		if (ret)1022			return ret;1023	}1024	return 0;1025}1026 1027static int peb2466_fw_parse_frxfilter(struct snd_soc_component *component,1028				      u16 tag, u32 lng, const u8 *data)1029{1030	struct peb2466 *peb2466 = snd_soc_component_get_drvdata(component);1031	u8 mask;1032	int ret;1033	int i;1034 1035	dev_info(component->dev, "fw FRX filter: mask %x, %*phN\n", *data,1036		 lng - 1, data + 1);1037 1038	/*1039	 * FRX_FILTER TLV data:1040	 *   - @0 1 byte:  Chan mask (bit set means related channel is concerned)1041	 *   - @1 8 bytes: FRX-Filter coefficients1042	 */1043	mask = *data;1044	for (i = 0; i < ARRAY_SIZE(peb2466->ch); i++) {1045		if (!(mask & (1 << i)))1046			continue;1047 1048		ret = regmap_update_bits(peb2466->regmap, PEB2466_CR0(i),1049					 PEB2466_CR0_FRX, 0);1050		if (ret)1051			return ret;1052 1053		ret = peb2466_write_buf(peb2466, PEB2466_FRX_FILTER(i), data + 1, 8);1054		if (ret)1055			return ret;1056 1057		ret = regmap_update_bits(peb2466->regmap, PEB2466_CR0(i),1058					 PEB2466_CR0_FRX, PEB2466_CR0_FRX);1059		if (ret)1060			return ret;1061	}1062	return 0;1063}1064 1065static int peb2466_fw_parse_frrfilter(struct snd_soc_component *component,1066				      u16 tag, u32 lng, const u8 *data)1067{1068	struct peb2466 *peb2466 = snd_soc_component_get_drvdata(component);1069	u8 mask;1070	int ret;1071	int i;1072 1073	dev_info(component->dev, "fw FRR filter: mask %x, %*phN\n", *data,1074		 lng - 1, data + 1);1075 1076	/*1077	 * FRR_FILTER TLV data:1078	 *   - @0 1 byte:  Chan mask (bit set means related channel is concerned)1079	 *   - @1 8 bytes: FRR-Filter coefficients1080	 */1081	mask = *data;1082	for (i = 0; i < ARRAY_SIZE(peb2466->ch); i++) {1083		if (!(mask & (1 << i)))1084			continue;1085 1086		ret = regmap_update_bits(peb2466->regmap, PEB2466_CR0(i),1087					 PEB2466_CR0_FRR, 0);1088		if (ret)1089			return ret;1090 1091		ret = peb2466_write_buf(peb2466, PEB2466_FRR_FILTER(i), data + 1, 8);1092		if (ret)1093			return ret;1094 1095		ret = regmap_update_bits(peb2466->regmap, PEB2466_CR0(i),1096					 PEB2466_CR0_FRR, PEB2466_CR0_FRR);1097		if (ret)1098			return ret;1099	}1100	return 0;1101}1102 1103static int peb2466_fw_parse_axfilter(struct snd_soc_component *component,1104				     u16 tag, u32 lng, const u8 *data)1105{1106	struct peb2466 *peb2466 = snd_soc_component_get_drvdata(component);1107	u8 mask;1108	int ret;1109	int i;1110 1111	dev_info(component->dev, "fw AX filter: mask %x, %*phN\n", *data,1112		 lng - 1, data + 1);1113 1114	/*1115	 * AX_FILTER TLV data:1116	 *   - @0 1 byte:  Chan mask (bit set means related channel is concerned)1117	 *   - @1 4 bytes: AX-Filter coefficients1118	 */1119	mask = *data;1120	for (i = 0; i < ARRAY_SIZE(peb2466->ch); i++) {1121		if (!(mask & (1 << i)))1122			continue;1123 1124		ret = regmap_update_bits(peb2466->regmap, PEB2466_CR0(i),1125					 PEB2466_CR0_AX, 0);1126		if (ret)1127			return ret;1128 1129		ret = peb2466_write_buf(peb2466, PEB2466_AX_FILTER(i), data + 1, 4);1130		if (ret)1131			return ret;1132 1133		ret = regmap_update_bits(peb2466->regmap, PEB2466_CR0(i),1134					 PEB2466_CR0_AX, PEB2466_CR0_AX);1135		if (ret)1136			return ret;1137	}1138	return 0;1139}1140 1141static int peb2466_fw_parse_arfilter(struct snd_soc_component *component,1142				     u16 tag, u32 lng, const u8 *data)1143{1144	struct peb2466 *peb2466 = snd_soc_component_get_drvdata(component);1145	u8 mask;1146	int ret;1147	int i;1148 1149	dev_info(component->dev, "fw AR filter: mask %x, %*phN\n", *data,1150		 lng - 1, data + 1);1151 1152	/*1153	 * AR_FILTER TLV data:1154	 *   - @0 1 byte:  Chan mask (bit set means related channel is concerned)1155	 *   - @1 4 bytes: AR-Filter coefficients1156	 */1157	mask = *data;1158	for (i = 0; i < ARRAY_SIZE(peb2466->ch); i++) {1159		if (!(mask & (1 << i)))1160			continue;1161 1162		ret = regmap_update_bits(peb2466->regmap, PEB2466_CR0(i),1163					 PEB2466_CR0_AR, 0);1164		if (ret)1165			return ret;1166 1167		ret = peb2466_write_buf(peb2466, PEB2466_AR_FILTER(i), data + 1, 4);1168		if (ret)1169			return ret;1170 1171		ret = regmap_update_bits(peb2466->regmap, PEB2466_CR0(i),1172					 PEB2466_CR0_AR, PEB2466_CR0_AR);1173		if (ret)1174			return ret;1175	}1176	return 0;1177}1178 1179static const char * const peb2466_ax_ctrl_names[] = {1180	"ADC0 Capture Volume",1181	"ADC1 Capture Volume",1182	"ADC2 Capture Volume",1183	"ADC3 Capture Volume",1184};1185 1186static int peb2466_fw_parse_axtable(struct snd_soc_component *component,1187				    u16 tag, u32 lng, const u8 *data)1188{1189	struct peb2466 *peb2466 = snd_soc_component_get_drvdata(component);1190	struct peb2466_lkup_ctrl *lkup_ctrl;1191	struct peb2466_lookup *lookup;1192	u8 (*table)[4];1193	u32 table_size;1194	u32 init_index;1195	s32 min_val;1196	s32 step;1197	u8 mask;1198	int ret;1199	int i;1200 1201	/*1202	 * AX_TABLE TLV data:1203	 *   - @0 1 byte:  Chan mask (bit set means related channel is concerned)1204	 *   - @1 32bits signed: Min table value in centi dB (MinVal)1205	 *                       ie -300 means -3.0 dB1206	 *   - @5 32bits signed: Step from on item to other item in centi dB (Step)1207	 *                       ie 25 means 0.25 dB)1208	 *   - @9 32bits unsigned: Item index in the table to use for the initial1209	 *                         value1210	 *   - @13 N*4 bytes: Table composed of 4 bytes items.1211	 *                    Each item correspond to an AX filter value.1212	 *1213	 * The conversion from raw value item in the table to/from the value in1214	 * dB is: Raw value at index i <-> (MinVal + i * Step) in centi dB.1215	 */1216 1217	/* Check Lng and extract the table size. */1218	if (lng < 13 || ((lng - 13) % 4)) {1219		dev_err(component->dev, "fw AX table lng %u invalid\n", lng);1220		return -EINVAL;1221	}1222	table_size = lng - 13;1223 1224	min_val = get_unaligned_be32(data + 1);1225	step = get_unaligned_be32(data + 5);1226	init_index = get_unaligned_be32(data + 9);1227	if (init_index >= (table_size / 4)) {1228		dev_err(component->dev, "fw AX table index %u out of table[%u]\n",1229			init_index, table_size / 4);1230		return -EINVAL;1231	}1232 1233	dev_info(component->dev,1234		 "fw AX table: mask %x, min %d, step %d, %u items, tbl[%u] %*phN\n",1235		 *data, min_val, step, table_size / 4, init_index,1236		 4, data + 13 + (init_index * 4));1237 1238	BUILD_BUG_ON(sizeof(*table) != 4);1239	table = devm_kzalloc(&peb2466->spi->dev, table_size, GFP_KERNEL);1240	if (!table)1241		return -ENOMEM;1242	memcpy(table, data + 13, table_size);1243 1244	mask = *data;1245	BUILD_BUG_ON(ARRAY_SIZE(peb2466_ax_ctrl_names) != ARRAY_SIZE(peb2466->ch));1246	for (i = 0; i < ARRAY_SIZE(peb2466->ch); i++) {1247		if (!(mask & (1 << i)))1248			continue;1249 1250		lookup = &peb2466->ch[i].ax_lookup;1251		lookup->table = table;1252		lookup->count = table_size / 4;1253 1254		ret = regmap_update_bits(peb2466->regmap, PEB2466_CR0(i),1255					 PEB2466_CR0_AX, 0);1256		if (ret)1257			return ret;1258 1259		ret = peb2466_write_buf(peb2466, PEB2466_AX_FILTER(i),1260					lookup->table[init_index], 4);1261		if (ret)1262			return ret;1263 1264		ret = regmap_update_bits(peb2466->regmap, PEB2466_CR0(i),1265					 PEB2466_CR0_AX, PEB2466_CR0_AX);1266		if (ret)1267			return ret;1268 1269		lkup_ctrl = &peb2466->ch[i].ax_lkup_ctrl;1270		lkup_ctrl->lookup = lookup;1271		lkup_ctrl->reg = PEB2466_AX_FILTER(i);1272		lkup_ctrl->index = init_index;1273 1274		ret = peb2466_add_lkup_ctrl(component, lkup_ctrl,1275					    peb2466_ax_ctrl_names[i],1276					    min_val, step);1277		if (ret)1278			return ret;1279	}1280	return 0;1281}1282 1283static const char * const peb2466_ar_ctrl_names[] = {1284	"DAC0 Playback Volume",1285	"DAC1 Playback Volume",1286	"DAC2 Playback Volume",1287	"DAC3 Playback Volume",1288};1289 1290static int peb2466_fw_parse_artable(struct snd_soc_component *component,1291				    u16 tag, u32 lng, const u8 *data)1292{1293	struct peb2466 *peb2466 = snd_soc_component_get_drvdata(component);1294	struct peb2466_lkup_ctrl *lkup_ctrl;1295	struct peb2466_lookup *lookup;1296	u8 (*table)[4];1297	u32 table_size;1298	u32 init_index;1299	s32 min_val;1300	s32 step;1301	u8 mask;1302	int ret;1303	int i;1304 1305	/*1306	 * AR_TABLE TLV data:1307	 *   - @0 1 byte:  Chan mask (bit set means related channel is concerned)1308	 *   - @1 32bits signed: Min table value in centi dB (MinVal)1309	 *                       ie -300 means -3.0 dB1310	 *   - @5 32bits signed: Step from on item to other item in centi dB (Step)1311	 *                       ie 25 means 0.25 dB)1312	 *   - @9 32bits unsigned: Item index in the table to use for the initial1313	 *                         value1314	 *   - @13 N*4 bytes: Table composed of 4 bytes items.1315	 *                    Each item correspond to an AR filter value.1316	 *1317	 * The conversion from raw value item in the table to/from the value in1318	 * dB is: Raw value at index i <-> (MinVal + i * Step) in centi dB.1319	 */1320 1321	/* Check Lng and extract the table size. */1322	if (lng < 13 || ((lng - 13) % 4)) {1323		dev_err(component->dev, "fw AR table lng %u invalid\n", lng);1324		return -EINVAL;1325	}1326	table_size = lng - 13;1327 1328	min_val = get_unaligned_be32(data + 1);1329	step = get_unaligned_be32(data + 5);1330	init_index = get_unaligned_be32(data + 9);1331	if (init_index >= (table_size / 4)) {1332		dev_err(component->dev, "fw AR table index %u out of table[%u]\n",1333			init_index, table_size / 4);1334		return -EINVAL;1335	}1336 1337	dev_info(component->dev,1338		 "fw AR table: mask %x, min %d, step %d, %u items, tbl[%u] %*phN\n",1339		 *data, min_val, step, table_size / 4, init_index,1340		 4, data + 13 + (init_index * 4));1341 1342	BUILD_BUG_ON(sizeof(*table) != 4);1343	table = devm_kzalloc(&peb2466->spi->dev, table_size, GFP_KERNEL);1344	if (!table)1345		return -ENOMEM;1346	memcpy(table, data + 13, table_size);1347 1348	mask = *data;1349	BUILD_BUG_ON(ARRAY_SIZE(peb2466_ar_ctrl_names) != ARRAY_SIZE(peb2466->ch));1350	for (i = 0; i < ARRAY_SIZE(peb2466->ch); i++) {1351		if (!(mask & (1 << i)))1352			continue;1353 1354		lookup = &peb2466->ch[i].ar_lookup;1355		lookup->table = table;1356		lookup->count = table_size / 4;1357 1358		ret = regmap_update_bits(peb2466->regmap, PEB2466_CR0(i),1359					 PEB2466_CR0_AR, 0);1360		if (ret)1361			return ret;1362 1363		ret = peb2466_write_buf(peb2466, PEB2466_AR_FILTER(i),1364					lookup->table[init_index], 4);1365		if (ret)1366			return ret;1367 1368		ret = regmap_update_bits(peb2466->regmap, PEB2466_CR0(i),1369					 PEB2466_CR0_AR, PEB2466_CR0_AR);1370		if (ret)1371			return ret;1372 1373		lkup_ctrl = &peb2466->ch[i].ar_lkup_ctrl;1374		lkup_ctrl->lookup = lookup;1375		lkup_ctrl->reg = PEB2466_AR_FILTER(i);1376		lkup_ctrl->index = init_index;1377 1378		ret = peb2466_add_lkup_ctrl(component, lkup_ctrl,1379					    peb2466_ar_ctrl_names[i],1380					    min_val, step);1381		if (ret)1382			return ret;1383	}1384	return 0;1385}1386 1387struct peb2466_fw_tag_def {1388	u16 tag;1389	u32 lng_min;1390	u32 lng_max;1391	int (*parse)(struct snd_soc_component *component,1392		     u16 tag, u32 lng, const u8 *data);1393};1394 1395#define PEB2466_TAG_DEF_LNG_EQ(__tag, __lng, __parse) { \1396	.tag = __tag,		\1397	.lng_min = __lng,	\1398	.lng_max = __lng,	\1399	.parse = __parse,	\1400}1401 1402#define PEB2466_TAG_DEF_LNG_MIN(__tag, __lng_min, __parse) { \1403	.tag = __tag,		\1404	.lng_min = __lng_min,	\1405	.lng_max = U32_MAX,	\1406	.parse = __parse,	\1407}1408 1409static const struct peb2466_fw_tag_def peb2466_fw_tag_defs[] = {1410	/* TH FILTER */1411	PEB2466_TAG_DEF_LNG_EQ(0x0001, 1 + 3 * 8, peb2466_fw_parse_thfilter),1412	/* IMR1 FILTER */1413	PEB2466_TAG_DEF_LNG_EQ(0x0002, 1 + 2 * 8, peb2466_fw_parse_imr1filter),1414	/* FRX FILTER */1415	PEB2466_TAG_DEF_LNG_EQ(0x0003, 1 + 8, peb2466_fw_parse_frxfilter),1416	/* FRR FILTER */1417	PEB2466_TAG_DEF_LNG_EQ(0x0004, 1 + 8, peb2466_fw_parse_frrfilter),1418	/* AX FILTER */1419	PEB2466_TAG_DEF_LNG_EQ(0x0005, 1 + 4, peb2466_fw_parse_axfilter),1420	/* AR FILTER */1421	PEB2466_TAG_DEF_LNG_EQ(0x0006, 1 + 4, peb2466_fw_parse_arfilter),1422	/* AX TABLE */1423	PEB2466_TAG_DEF_LNG_MIN(0x0105, 1 + 3 * 4, peb2466_fw_parse_axtable),1424	/* AR TABLE */1425	PEB2466_TAG_DEF_LNG_MIN(0x0106, 1 + 3 * 4, peb2466_fw_parse_artable),1426};1427 1428static const struct peb2466_fw_tag_def *peb2466_fw_get_tag_def(u16 tag)1429{1430	int i;1431 1432	for (i = 0; i < ARRAY_SIZE(peb2466_fw_tag_defs); i++) {1433		if (peb2466_fw_tag_defs[i].tag == tag)1434			return &peb2466_fw_tag_defs[i];1435	}1436	return NULL;1437}1438 1439static int peb2466_fw_parse(struct snd_soc_component *component,1440			    const u8 *data, size_t size)1441{1442	const struct peb2466_fw_tag_def *tag_def;1443	size_t left;1444	const u8 *buf;1445	u16 val16;1446	u16 tag;1447	u32 lng;1448	int ret;1449 1450	/*1451	 * Coefficients firmware binary structure (16bits and 32bits are1452	 * big-endian values).1453	 *1454	 * @0, 16bits: Magic (0x2466)1455	 * @2, 16bits: Version (0x0100 for version 1.0)1456	 * @4, 2+4+N bytes: TLV block1457	 * @4+(2+4+N) bytes: Next TLV block1458	 * ...1459	 *1460	 * Detail of a TLV block:1461	 *   @0, 16bits: Tag1462	 *   @2, 32bits: Lng1463	 *   @6, lng bytes: Data1464	 *1465	 * The detail the Data for a given TLV Tag is provided in the related1466	 * parser.1467	 */1468 1469	left = size;1470	buf = data;1471 1472	if (left < 4) {1473		dev_err(component->dev, "fw size %zu, exp at least 4\n", left);1474		return -EINVAL;1475	}1476 1477	/* Check magic */1478	val16 = get_unaligned_be16(buf);1479	if (val16 != 0x2466) {1480		dev_err(component->dev, "fw magic 0x%04x exp 0x2466\n", val16);1481		return -EINVAL;1482	}1483	buf += 2;1484	left -= 2;1485 1486	/* Check version */1487	val16 = get_unaligned_be16(buf);1488	if (val16 != 0x0100) {1489		dev_err(component->dev, "fw magic 0x%04x exp 0x0100\n", val16);1490		return -EINVAL;1491	}1492	buf += 2;1493	left -= 2;1494 1495	while (left) {1496		if (left < 6) {1497			dev_err(component->dev, "fw %td/%zu left %zu, exp at least 6\n",1498				buf - data, size, left);1499			return -EINVAL;1500		}1501		/* Check tag and lng */1502		tag = get_unaligned_be16(buf);1503		lng = get_unaligned_be32(buf + 2);1504		tag_def = peb2466_fw_get_tag_def(tag);1505		if (!tag_def) {1506			dev_err(component->dev, "fw %td/%zu tag 0x%04x unknown\n",1507				buf - data, size, tag);1508			return -EINVAL;1509		}1510		if (lng < tag_def->lng_min || lng > tag_def->lng_max) {1511			dev_err(component->dev, "fw %td/%zu tag 0x%04x lng %u, exp [%u;%u]\n",1512				buf - data, size, tag, lng, tag_def->lng_min, tag_def->lng_max);1513			return -EINVAL;1514		}1515		buf += 6;1516		left -= 6;1517		if (left < lng) {1518			dev_err(component->dev, "fw %td/%zu tag 0x%04x lng %u, left %zu\n",1519				buf - data, size, tag, lng, left);1520			return -EINVAL;1521		}1522 1523		/* TLV block is valid -> parse the data part */1524		ret = tag_def->parse(component, tag, lng, buf);1525		if (ret) {1526			dev_err(component->dev, "fw %td/%zu tag 0x%04x lng %u parse failed\n",1527				buf - data, size, tag, lng);1528			return ret;1529		}1530 1531		buf += lng;1532		left -= lng;1533	}1534	return 0;1535}1536 1537static int peb2466_load_coeffs(struct snd_soc_component *component, const char *fw_name)1538{1539	const struct firmware *fw;1540	int ret;1541 1542	ret = request_firmware(&fw, fw_name, component->dev);1543	if (ret)1544		return ret;1545 1546	ret = peb2466_fw_parse(component, fw->data, fw->size);1547	release_firmware(fw);1548 1549	return ret;1550}1551 1552static int peb2466_component_probe(struct snd_soc_component *component)1553{1554	struct peb2466 *peb2466 = snd_soc_component_get_drvdata(component);1555	const char *firmware_name;1556	int ret;1557 1558	/* reset peb2466 audio part */1559	ret = peb2466_reset_audio(peb2466);1560	if (ret)1561		return ret;1562 1563	ret = of_property_read_string(peb2466->spi->dev.of_node,1564				      "firmware-name", &firmware_name);1565	if (ret)1566		return (ret == -EINVAL) ? 0 : ret;1567 1568	return peb2466_load_coeffs(component, firmware_name);1569}1570 1571static const struct snd_soc_component_driver peb2466_component_driver = {1572	.probe			= peb2466_component_probe,1573	.controls		= peb2466_controls,1574	.num_controls		= ARRAY_SIZE(peb2466_controls),1575	.dapm_widgets		= peb2466_dapm_widgets,1576	.num_dapm_widgets	= ARRAY_SIZE(peb2466_dapm_widgets),1577	.dapm_routes		= peb2466_dapm_routes,1578	.num_dapm_routes	= ARRAY_SIZE(peb2466_dapm_routes),1579	.endianness		= 1,1580};1581 1582/*1583 * The mapping used for the relationship between the gpio offset and the1584 * physical pin is the following:1585 *1586 * offset     pin1587 *      0     SI1_01588 *      1     SI1_11589 *      2     SI2_01590 *      3     SI2_11591 *      4     SI3_01592 *      5     SI3_11593 *      6     SI4_01594 *      7     SI4_11595 *      8     SO1_01596 *      9     SO1_11597 *     10     SO2_01598 *     11     SO2_11599 *     12     SO3_01600 *     13     SO3_11601 *     14     SO4_01602 *     15     SO4_11603 *     16     SB1_01604 *     17     SB1_11605 *     18     SB2_01606 *     19     SB2_11607 *     20     SB3_01608 *     21     SB3_11609 *     22     SB4_01610 *     23     SB4_11611 *     24     SB1_21612 *     25     SB2_21613 *     26     SB3_21614 *     27     SB4_21615 */1616 1617static int peb2466_chip_gpio_offset_to_data_regmask(unsigned int offset,1618						    unsigned int *xr_reg,1619						    unsigned int *mask)1620{1621	if (offset < 16) {1622		/*1623		 * SIx_{0,1} and SOx_{0,1}1624		 *   Read accesses read SIx_{0,1} values1625		 *   Write accesses write SOx_{0,1} values1626		 */1627		*xr_reg = PEB2466_XR0;1628		*mask = (1 << (offset % 8));1629		return 0;1630	}1631	if (offset < 24) {1632		/* SBx_{0,1} */1633		*xr_reg = PEB2466_XR1;1634		*mask = (1 << (offset - 16));1635		return 0;1636	}1637	if (offset < 28) {1638		/* SBx_2 */1639		*xr_reg = PEB2466_XR3;1640		*mask = (1 << (offset - 24 + 4));1641		return 0;1642	}1643	return -EINVAL;1644}1645 1646static int peb2466_chip_gpio_offset_to_dir_regmask(unsigned int offset,1647						   unsigned int *xr_reg,1648						   unsigned int *mask)1649{1650	if (offset < 16) {1651		/* Direction cannot be changed for these GPIOs */1652		return -EINVAL;1653	}1654	if (offset < 24) {1655		*xr_reg = PEB2466_XR2;1656		*mask = (1 << (offset - 16));1657		return 0;1658	}1659	if (offset < 28) {1660		*xr_reg = PEB2466_XR3;1661		*mask = (1 << (offset - 24));1662		return 0;1663	}1664	return -EINVAL;1665}1666 1667static unsigned int *peb2466_chip_gpio_get_cache(struct peb2466 *peb2466,1668						 unsigned int xr_reg)1669{1670	unsigned int *cache;1671 1672	switch (xr_reg) {1673	case PEB2466_XR0:1674		cache = &peb2466->gpio.cache.xr0;1675		break;1676	case PEB2466_XR1:1677		cache = &peb2466->gpio.cache.xr1;1678		break;1679	case PEB2466_XR2:1680		cache = &peb2466->gpio.cache.xr2;1681		break;1682	case PEB2466_XR3:1683		cache = &peb2466->gpio.cache.xr3;1684		break;1685	default:1686		cache = NULL;1687		break;1688	}1689	return cache;1690}1691 1692static int peb2466_chip_gpio_update_bits(struct peb2466 *peb2466, unsigned int xr_reg,1693					 unsigned int mask, unsigned int val)1694{1695	unsigned int tmp;1696	unsigned int *cache;1697	int ret;1698 1699	/*1700	 * Read and write accesses use different peb2466 internal signals (input1701	 * signals on reads and output signals on writes). regmap_update_bits1702	 * cannot be used to read/modify/write the value.1703	 * So, a specific cache value is used.1704	 */1705 1706	mutex_lock(&peb2466->gpio.lock);1707 1708	cache = peb2466_chip_gpio_get_cache(peb2466, xr_reg);1709	if (!cache) {1710		ret = -EINVAL;1711		goto end;1712	}1713 1714	tmp = *cache;1715	tmp &= ~mask;1716	tmp |= val;1717 1718	ret = regmap_write(peb2466->regmap, xr_reg, tmp);1719	if (ret)1720		goto end;1721 1722	*cache = tmp;1723	ret = 0;1724 1725end:1726	mutex_unlock(&peb2466->gpio.lock);1727	return ret;1728}1729 1730static void peb2466_chip_gpio_set(struct gpio_chip *c, unsigned int offset, int val)1731{1732	struct peb2466 *peb2466 = gpiochip_get_data(c);1733	unsigned int xr_reg;1734	unsigned int mask;1735	int ret;1736 1737	if (offset < 8) {1738		/*1739		 * SIx_{0,1} signals cannot be set and writing the related1740		 * register will change the SOx_{0,1} signals1741		 */1742		dev_warn(&peb2466->spi->dev, "cannot set gpio %d (read-only)\n",1743			 offset);1744		return;1745	}1746 1747	ret = peb2466_chip_gpio_offset_to_data_regmask(offset, &xr_reg, &mask);1748	if (ret) {1749		dev_err(&peb2466->spi->dev, "cannot set gpio %d (%d)\n",1750			offset, ret);1751		return;1752	}1753 1754	ret = peb2466_chip_gpio_update_bits(peb2466, xr_reg, mask, val ? mask : 0);1755	if (ret) {1756		dev_err(&peb2466->spi->dev, "set gpio %d (0x%x, 0x%x) failed (%d)\n",1757			offset, xr_reg, mask, ret);1758	}1759}1760 1761static int peb2466_chip_gpio_get(struct gpio_chip *c, unsigned int offset)1762{1763	struct peb2466 *peb2466 = gpiochip_get_data(c);1764	bool use_cache = false;1765	unsigned int *cache;1766	unsigned int xr_reg;1767	unsigned int mask;1768	unsigned int val;1769	int ret;1770 1771	if (offset >= 8 && offset < 16) {1772		/*1773		 * SOx_{0,1} signals cannot be read. Reading the related1774		 * register will read the SIx_{0,1} signals.1775		 * Use the cache to get value;1776		 */1777		use_cache = true;1778	}1779 1780	ret = peb2466_chip_gpio_offset_to_data_regmask(offset, &xr_reg, &mask);1781	if (ret) {1782		dev_err(&peb2466->spi->dev, "cannot get gpio %d (%d)\n",1783			offset, ret);1784		return -EINVAL;1785	}1786 1787	if (use_cache) {1788		cache = peb2466_chip_gpio_get_cache(peb2466, xr_reg);1789		if (!cache)1790			return -EINVAL;1791		val = *cache;1792	} else {1793		ret = regmap_read(peb2466->regmap, xr_reg, &val);1794		if (ret) {1795			dev_err(&peb2466->spi->dev, "get gpio %d (0x%x, 0x%x) failed (%d)\n",1796				offset, xr_reg, mask, ret);1797			return ret;1798		}1799	}1800 1801	return !!(val & mask);1802}1803 1804static int peb2466_chip_get_direction(struct gpio_chip *c, unsigned int offset)1805{1806	struct peb2466 *peb2466 = gpiochip_get_data(c);1807	unsigned int xr_reg;1808	unsigned int mask;1809	unsigned int val;1810	int ret;1811 1812	if (offset < 8) {1813		/* SIx_{0,1} */1814		return GPIO_LINE_DIRECTION_IN;1815	}1816	if (offset < 16) {1817		/* SOx_{0,1} */1818		return GPIO_LINE_DIRECTION_OUT;1819	}1820 1821	ret = peb2466_chip_gpio_offset_to_dir_regmask(offset, &xr_reg, &mask);1822	if (ret) {1823		dev_err(&peb2466->spi->dev, "cannot get gpio %d direction (%d)\n",1824			offset, ret);1825		return ret;1826	}1827 1828	ret = regmap_read(peb2466->regmap, xr_reg, &val);1829	if (ret) {1830		dev_err(&peb2466->spi->dev, "get dir gpio %d (0x%x, 0x%x) failed (%d)\n",1831			offset, xr_reg, mask, ret);1832		return ret;1833	}1834 1835	return val & mask ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;1836}1837 1838static int peb2466_chip_direction_input(struct gpio_chip *c, unsigned int offset)1839{1840	struct peb2466 *peb2466 = gpiochip_get_data(c);1841	unsigned int xr_reg;1842	unsigned int mask;1843	int ret;1844 1845	if (offset < 8) {1846		/* SIx_{0,1} */1847		return 0;1848	}1849	if (offset < 16) {1850		/* SOx_{0,1} */1851		return -EINVAL;1852	}1853 1854	ret = peb2466_chip_gpio_offset_to_dir_regmask(offset, &xr_reg, &mask);1855	if (ret) {1856		dev_err(&peb2466->spi->dev, "cannot set gpio %d direction (%d)\n",1857			offset, ret);1858		return ret;1859	}1860 1861	ret = peb2466_chip_gpio_update_bits(peb2466, xr_reg, mask, 0);1862	if (ret) {1863		dev_err(&peb2466->spi->dev, "Set dir in gpio %d (0x%x, 0x%x) failed (%d)\n",1864			offset, xr_reg, mask, ret);1865		return ret;1866	}1867 1868	return 0;1869}1870 1871static int peb2466_chip_direction_output(struct gpio_chip *c, unsigned int offset, int val)1872{1873	struct peb2466 *peb2466 = gpiochip_get_data(c);1874	unsigned int xr_reg;1875	unsigned int mask;1876	int ret;1877 1878	if (offset < 8) {1879		/* SIx_{0,1} */1880		return -EINVAL;1881	}1882 1883	peb2466_chip_gpio_set(c, offset, val);1884 1885	if (offset < 16) {1886		/* SOx_{0,1} */1887		return 0;1888	}1889 1890	ret = peb2466_chip_gpio_offset_to_dir_regmask(offset, &xr_reg, &mask);1891	if (ret) {1892		dev_err(&peb2466->spi->dev, "cannot set gpio %d direction (%d)\n",1893			offset, ret);1894		return ret;1895	}1896 1897	ret = peb2466_chip_gpio_update_bits(peb2466, xr_reg, mask, mask);1898	if (ret) {1899		dev_err(&peb2466->spi->dev, "Set dir in gpio %d (0x%x, 0x%x) failed (%d)\n",1900			offset, xr_reg, mask, ret);1901		return ret;1902	}1903 1904	return 0;1905}1906 1907static int peb2466_reset_gpio(struct peb2466 *peb2466)1908{1909	static const struct reg_sequence reg_reset[] = {1910		/* Output pins at 0, input/output pins as input */1911		{  .reg = PEB2466_XR0, .def = 0 },1912		{  .reg = PEB2466_XR1, .def = 0 },1913		{  .reg = PEB2466_XR2, .def = 0 },1914		{  .reg = PEB2466_XR3, .def = 0 },1915	};1916 1917	peb2466->gpio.cache.xr0 = 0;1918	peb2466->gpio.cache.xr1 = 0;1919	peb2466->gpio.cache.xr2 = 0;1920	peb2466->gpio.cache.xr3 = 0;1921 1922	return regmap_multi_reg_write(peb2466->regmap, reg_reset, ARRAY_SIZE(reg_reset));1923}1924 1925static int peb2466_gpio_init(struct peb2466 *peb2466)1926{1927	int ret;1928 1929	mutex_init(&peb2466->gpio.lock);1930 1931	ret = peb2466_reset_gpio(peb2466);1932	if (ret)1933		return ret;1934 1935	peb2466->gpio.gpio_chip.owner = THIS_MODULE;1936	peb2466->gpio.gpio_chip.label = dev_name(&peb2466->spi->dev);1937	peb2466->gpio.gpio_chip.parent = &peb2466->spi->dev;1938	peb2466->gpio.gpio_chip.base = -1;1939	peb2466->gpio.gpio_chip.ngpio = 28;1940	peb2466->gpio.gpio_chip.get_direction = peb2466_chip_get_direction;1941	peb2466->gpio.gpio_chip.direction_input = peb2466_chip_direction_input;1942	peb2466->gpio.gpio_chip.direction_output = peb2466_chip_direction_output;1943	peb2466->gpio.gpio_chip.get = peb2466_chip_gpio_get;1944	peb2466->gpio.gpio_chip.set = peb2466_chip_gpio_set;1945	peb2466->gpio.gpio_chip.can_sleep = true;1946 1947	return devm_gpiochip_add_data(&peb2466->spi->dev, &peb2466->gpio.gpio_chip,1948				      peb2466);1949}1950 1951static int peb2466_spi_probe(struct spi_device *spi)1952{1953	struct peb2466 *peb2466;1954	unsigned long mclk_rate;1955	int ret;1956	u8 xr5;1957 1958	spi->bits_per_word = 8;1959	ret = spi_setup(spi);1960	if (ret < 0)1961		return ret;1962 1963	peb2466 = devm_kzalloc(&spi->dev, sizeof(*peb2466), GFP_KERNEL);1964	if (!peb2466)1965		return -ENOMEM;1966 1967	peb2466->spi = spi;1968 1969	peb2466->regmap = devm_regmap_init(&peb2466->spi->dev, NULL, peb2466,1970					   &peb2466_regmap_config);1971	if (IS_ERR(peb2466->regmap))1972		return PTR_ERR(peb2466->regmap);1973 1974	peb2466->reset_gpio = devm_gpiod_get_optional(&peb2466->spi->dev,1975						      "reset", GPIOD_OUT_LOW);1976	if (IS_ERR(peb2466->reset_gpio))1977		return PTR_ERR(peb2466->reset_gpio);1978 1979	peb2466->mclk = devm_clk_get_enabled(&peb2466->spi->dev, "mclk");1980	if (IS_ERR(peb2466->mclk))1981		return PTR_ERR(peb2466->mclk);1982 1983	if (peb2466->reset_gpio) {1984		gpiod_set_value_cansleep(peb2466->reset_gpio, 1);1985		udelay(4);1986		gpiod_set_value_cansleep(peb2466->reset_gpio, 0);1987		udelay(4);1988	}1989 1990	spi_set_drvdata(spi, peb2466);1991 1992	mclk_rate = clk_get_rate(peb2466->mclk);1993	switch (mclk_rate) {1994	case 1536000:1995		xr5 = PEB2466_XR5_MCLK_1536;1996		break;1997	case 2048000:1998		xr5 = PEB2466_XR5_MCLK_2048;1999		break;2000	case 4096000:2001		xr5 = PEB2466_XR5_MCLK_4096;2002		break;2003	case 8192000:2004		xr5 = PEB2466_XR5_MCLK_8192;2005		break;2006	default:2007		dev_err(&peb2466->spi->dev, "Unsupported clock rate %lu\n",2008			mclk_rate);2009		ret = -EINVAL;2010		goto failed;2011	}2012	ret = regmap_write(peb2466->regmap, PEB2466_XR5, xr5);2013	if (ret) {2014		dev_err(&peb2466->spi->dev, "Setting MCLK failed (%d)\n", ret);2015		goto failed;2016	}2017 2018	ret = devm_snd_soc_register_component(&spi->dev, &peb2466_component_driver,2019					      &peb2466_dai_driver, 1);2020	if (ret)2021		goto failed;2022 2023	if (IS_ENABLED(CONFIG_GPIOLIB)) {2024		ret = peb2466_gpio_init(peb2466);2025		if (ret)2026			goto failed;2027	}2028 2029	return 0;2030 2031failed:2032	return ret;2033}2034 2035static const struct of_device_id peb2466_of_match[] = {2036	{ .compatible = "infineon,peb2466", },2037	{ }2038};2039MODULE_DEVICE_TABLE(of, peb2466_of_match);2040 2041static const struct spi_device_id peb2466_id_table[] = {2042	{ "peb2466", 0 },2043	{ }2044};2045MODULE_DEVICE_TABLE(spi, peb2466_id_table);2046 2047static struct spi_driver peb2466_spi_driver = {2048	.driver  = {2049		.name   = "peb2466",2050		.of_match_table = peb2466_of_match,2051	},2052	.id_table = peb2466_id_table,2053	.probe  = peb2466_spi_probe,2054};2055 2056module_spi_driver(peb2466_spi_driver);2057 2058MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");2059MODULE_DESCRIPTION("PEB2466 ALSA SoC driver");2060MODULE_LICENSE("GPL");2061