brintos

brintos / linux-shallow public Read only

0
0
Text · 50.8 KiB · 5d99877 Raw
2187 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// ALSA SoC Texas Instruments PCM6240 Family Audio ADC/DAC Device4//5// Copyright (C) 2022 - 2024 Texas Instruments Incorporated6// https://www.ti.com7//8// The PCM6240 driver implements a flexible and configurable9// algo coefficient setting for one, two, or even multiple10// PCM6240 Family chips.11//12// Author: Shenghao Ding <shenghao-ding@ti.com>13//14 15#include <linux/unaligned.h>16#include <linux/firmware.h>17#include <linux/gpio.h>18#include <linux/i2c.h>19#include <linux/module.h>20#include <linux/of_irq.h>21#include <linux/of_address.h>22#include <linux/regmap.h>23#include <sound/pcm_params.h>24#include <sound/soc.h>25#include <sound/tlv.h>26 27#include "pcm6240.h"28 29static const struct i2c_device_id pcmdevice_i2c_id[] = {30	{ "adc3120",  ADC3120  },31	{ "adc5120",  ADC5120  },32	{ "adc6120",  ADC6120  },33	{ "dix4192",  DIX4192  },34	{ "pcm1690",  PCM1690  },35	{ "pcm3120",  PCM3120  },36	{ "pcm3140",  PCM3140  },37	{ "pcm5120",  PCM5120  },38	{ "pcm5140",  PCM5140  },39	{ "pcm6120",  PCM6120  },40	{ "pcm6140",  PCM6140  },41	{ "pcm6240",  PCM6240  },42	{ "pcm6260",  PCM6260  },43	{ "pcm9211",  PCM9211  },44	{ "pcmd3140", PCMD3140 },45	{ "pcmd3180", PCMD3180 },46	{ "pcmd512x", PCMD512X },47	{ "taa5212",  TAA5212  },48	{ "taa5412",  TAA5412  },49	{ "tad5212",  TAD5212  },50	{ "tad5412",  TAD5412  },51	{}52};53MODULE_DEVICE_TABLE(i2c, pcmdevice_i2c_id);54 55static const char *const pcmdev_ctrl_name[] = {56	"%s i2c%d Dev%d Ch%d Ana Volume",57	"%s i2c%d Dev%d Ch%d Digi Volume",58	"%s i2c%d Dev%d Ch%d Fine Volume",59};60 61static const struct pcmdevice_mixer_control adc5120_analog_gain_ctl[] = {62	{63		.shift = 1,64		.reg = ADC5120_REG_CH1_ANALOG_GAIN,65		.max = 0x54,66		.invert = 0,67	},68	{69		.shift = 1,70		.reg = ADC5120_REG_CH2_ANALOG_GAIN,71		.max = 0x54,72		.invert = 0,73	}74};75 76static const struct pcmdevice_mixer_control adc5120_digi_gain_ctl[] = {77	{78		.shift = 0,79		.reg = ADC5120_REG_CH1_DIGITAL_GAIN,80		.max = 0xff,81		.invert = 0,82	},83	{84		.shift = 0,85		.reg = ADC5120_REG_CH2_DIGITAL_GAIN,86		.max = 0xff,87		.invert = 0,88	}89};90 91static const struct pcmdevice_mixer_control pcm1690_digi_gain_ctl[] = {92	{93		.shift = 0,94		.reg = PCM1690_REG_CH1_DIGITAL_GAIN,95		.max = 0xff,96		.invert = 0,97	},98	{99		.shift = 0,100		.reg = PCM1690_REG_CH2_DIGITAL_GAIN,101		.max = 0xff,102		.invert = 0,103	},104	{105		.shift = 0,106		.reg = PCM1690_REG_CH3_DIGITAL_GAIN,107		.max = 0xff,108		.invert = 0,109	},110	{111		.shift = 0,112		.reg = PCM1690_REG_CH4_DIGITAL_GAIN,113		.max = 0xff,114		.invert = 0,115	},116	{117		.shift = 0,118		.reg = PCM1690_REG_CH5_DIGITAL_GAIN,119		.max = 0xff,120		.invert = 0,121	},122	{123		.shift = 0,124		.reg = PCM1690_REG_CH6_DIGITAL_GAIN,125		.max = 0xff,126		.invert = 0,127	},128	{129		.shift = 0,130		.reg = PCM1690_REG_CH7_DIGITAL_GAIN,131		.max = 0xff,132		.invert = 0,133	},134	{135		.shift = 0,136		.reg = PCM1690_REG_CH8_DIGITAL_GAIN,137		.max = 0xff,138		.invert = 0,139	}140};141 142static const struct pcmdevice_mixer_control pcm6240_analog_gain_ctl[] = {143	{144		.shift = 2,145		.reg = PCM6240_REG_CH1_ANALOG_GAIN,146		.max = 0x42,147		.invert = 0,148	},149	{150		.shift = 2,151		.reg = PCM6240_REG_CH2_ANALOG_GAIN,152		.max = 0x42,153		.invert = 0,154	},155	{156		.shift = 2,157		.reg = PCM6240_REG_CH3_ANALOG_GAIN,158		.max = 0x42,159		.invert = 0,160	},161	{162		.shift = 2,163		.reg = PCM6240_REG_CH4_ANALOG_GAIN,164		.max = 0x42,165		.invert = 0,166	}167};168 169static const struct pcmdevice_mixer_control pcm6240_digi_gain_ctl[] = {170	{171		.shift = 0,172		.reg = PCM6240_REG_CH1_DIGITAL_GAIN,173		.max = 0xff,174		.invert = 0,175	},176	{177		.shift = 0,178		.reg = PCM6240_REG_CH2_DIGITAL_GAIN,179		.max = 0xff,180		.invert = 0,181	},182	{183		.shift = 0,184		.reg = PCM6240_REG_CH3_DIGITAL_GAIN,185		.max = 0xff,186		.invert = 0,187	},188	{189		.shift = 0,190		.reg = PCM6240_REG_CH4_DIGITAL_GAIN,191		.max = 0xff,192		.invert = 0,193	}194};195 196static const struct pcmdevice_mixer_control pcm6260_analog_gain_ctl[] = {197	{198		.shift = 2,199		.reg = PCM6260_REG_CH1_ANALOG_GAIN,200		.max = 0x42,201		.invert = 0,202	},203	{204		.shift = 2,205		.reg = PCM6260_REG_CH2_ANALOG_GAIN,206		.max = 0x42,207		.invert = 0,208	},209	{210		.shift = 2,211		.reg = PCM6260_REG_CH3_ANALOG_GAIN,212		.max = 0x42,213		.invert = 0,214	},215	{216		.shift = 2,217		.reg = PCM6260_REG_CH4_ANALOG_GAIN,218		.max = 0x42,219		.invert = 0,220	},221	{222		.shift = 2,223		.reg = PCM6260_REG_CH5_ANALOG_GAIN,224		.max = 0x42,225		.invert = 0,226	},227	{228		.shift = 2,229		.reg = PCM6260_REG_CH6_ANALOG_GAIN,230		.max = 0x42,231		.invert = 0,232	}233};234 235static const struct pcmdevice_mixer_control pcm6260_digi_gain_ctl[] = {236	{237		.shift = 0,238		.reg = PCM6260_REG_CH1_DIGITAL_GAIN,239		.max = 0xff,240		.invert = 0,241	},242	{243		.shift = 0,244		.reg = PCM6260_REG_CH2_DIGITAL_GAIN,245		.max = 0xff,246		.invert = 0,247	},248	{249		.shift = 0,250		.reg = PCM6260_REG_CH3_DIGITAL_GAIN,251		.max = 0xff,252		.invert = 0,253	},254	{255		.shift = 0,256		.reg = PCM6260_REG_CH4_DIGITAL_GAIN,257		.max = 0xff,258		.invert = 0,259	},260	{261		.shift = 0,262		.reg = PCM6260_REG_CH5_DIGITAL_GAIN,263		.max = 0xff,264		.invert = 0,265	},266	{267		.shift = 0,268		.reg = PCM6260_REG_CH6_DIGITAL_GAIN,269		.max = 0xff,270		.invert = 0,271	}272};273 274static const struct pcmdevice_mixer_control pcm9211_digi_gain_ctl[] = {275	{276		.shift = 0,277		.reg = PCM9211_REG_CH1_DIGITAL_GAIN,278		.max = 0xff,279		.invert = 0,280	},281	{282		.shift = 0,283		.reg = PCM9211_REG_CH2_DIGITAL_GAIN,284		.max = 0xff,285		.invert = 0,286	}287};288 289static const struct pcmdevice_mixer_control pcmd3140_digi_gain_ctl[] = {290	{291		.shift = 0,292		.reg = PCMD3140_REG_CH1_DIGITAL_GAIN,293		.max = 0xff,294		.invert = 0,295	},296	{297		.shift = 0,298		.reg = PCMD3140_REG_CH2_DIGITAL_GAIN,299		.max = 0xff,300		.invert = 0,301	},302	{303		.shift = 0,304		.reg = PCMD3140_REG_CH3_DIGITAL_GAIN,305		.max = 0xff,306		.invert = 0,307	},308	{309		.shift = 0,310		.reg = PCMD3140_REG_CH4_DIGITAL_GAIN,311		.max = 0xff,312		.invert = 0,313	}314};315 316static const struct pcmdevice_mixer_control pcmd3140_fine_gain_ctl[] = {317	{318		.shift = 4,319		.reg = PCMD3140_REG_CH1_FINE_GAIN,320		.max = 0xf,321		.invert = 0,322	},323	{324		.shift = 4,325		.reg = PCMD3140_REG_CH2_FINE_GAIN,326		.max = 0xf,327		.invert = 0,328	},329	{330		.shift = 4,331		.reg = PCMD3140_REG_CH3_FINE_GAIN,332		.max = 0xf,333		.invert = 0,334	},335	{336		.shift = 4,337		.reg = PCMD3140_REG_CH4_FINE_GAIN,338		.max = 0xf,339		.invert = 0,340	}341};342 343static const struct pcmdevice_mixer_control pcmd3180_digi_gain_ctl[] = {344	{345		.shift = 0,346		.reg = PCMD3180_REG_CH1_DIGITAL_GAIN,347		.max = 0xff,348		.invert = 0,349	},350	{351		.shift = 0,352		.reg = PCMD3180_REG_CH2_DIGITAL_GAIN,353		.max = 0xff,354		.invert = 0,355	},356	{357		.shift = 0,358		.reg = PCMD3180_REG_CH3_DIGITAL_GAIN,359		.max = 0xff,360		.invert = 0,361	},362	{363		.shift = 0,364		.reg = PCMD3180_REG_CH4_DIGITAL_GAIN,365		.max = 0xff,366		.invert = 0,367	},368	{369		.shift = 0,370		.reg = PCMD3180_REG_CH5_DIGITAL_GAIN,371		.max = 0xff,372		.invert = 0,373	},374	{375		.shift = 0,376		.reg = PCMD3180_REG_CH6_DIGITAL_GAIN,377		.max = 0xff,378		.invert = 0,379	},380	{381		.shift = 0,382		.reg = PCMD3180_REG_CH7_DIGITAL_GAIN,383		.max = 0xff,384		.invert = 0,385	},386	{387		.shift = 0,388		.reg = PCMD3180_REG_CH8_DIGITAL_GAIN,389		.max = 0xff,390		.invert = 0,391	}392};393 394static const struct pcmdevice_mixer_control pcmd3180_fine_gain_ctl[] = {395	{396		.shift = 4,397		.reg = PCMD3180_REG_CH1_FINE_GAIN,398		.max = 0xf,399		.invert = 0,400	},401	{402		.shift = 4,403		.reg = PCMD3180_REG_CH2_FINE_GAIN,404		.max = 0xf,405		.invert = 0,406	},407	{408		.shift = 4,409		.reg = PCMD3180_REG_CH3_FINE_GAIN,410		.max = 0xf,411		.invert = 0,412	},413	{414		.shift = 4,415		.reg = PCMD3180_REG_CH4_FINE_GAIN,416		.max = 0xf,417		.invert = 0,418	},419	{420		.shift = 4,421		.reg = PCMD3180_REG_CH5_FINE_GAIN,422		.max = 0xf,423		.invert = 0,424	},425	{426		.shift = 4,427		.reg = PCMD3180_REG_CH6_FINE_GAIN,428		.max = 0xf,429		.invert = 0,430	},431	{432		.shift = 4,433		.reg = PCMD3180_REG_CH7_FINE_GAIN,434		.max = 0xf,435		.invert = 0,436	},437	{438		.shift = 4,439		.reg = PCMD3180_REG_CH8_FINE_GAIN,440		.max = 0xf,441		.invert = 0,442	}443};444 445static const struct pcmdevice_mixer_control taa5412_digi_vol_ctl[] = {446	{447		.shift = 0,448		.reg = TAA5412_REG_CH1_DIGITAL_VOLUME,449		.max = 0xff,450		.invert = 0,451	},452	{453		.shift = 0,454		.reg = TAA5412_REG_CH2_DIGITAL_VOLUME,455		.max = 0xff,456		.invert = 0,457	},458	{459		.shift = 0,460		.reg = TAA5412_REG_CH3_DIGITAL_VOLUME,461		.max = 0xff,462		.invert = 0,463	},464	{465		.shift = 0,466		.reg = TAA5412_REG_CH4_DIGITAL_VOLUME,467		.max = 0xff,468		.invert = 0,469	}470};471 472static const struct pcmdevice_mixer_control taa5412_fine_gain_ctl[] = {473	{474		.shift = 4,475		.reg = TAA5412_REG_CH1_FINE_GAIN,476		.max = 0xf,477		.invert = 0,478	},479	{480		.shift = 4,481		.reg = TAA5412_REG_CH2_FINE_GAIN,482		.max = 0xf,483		.invert = 0,484	},485	{486		.shift = 4,487		.reg = TAA5412_REG_CH3_FINE_GAIN,488		.max = 0xf,489		.invert = 4,490	},491	{492		.shift = 0,493		.reg = TAA5412_REG_CH4_FINE_GAIN,494		.max = 0xf,495		.invert = 4,496	}497};498 499static const DECLARE_TLV_DB_MINMAX_MUTE(pcmd3140_dig_gain_tlv,500	-10000, 2700);501static const DECLARE_TLV_DB_MINMAX_MUTE(pcm1690_fine_dig_gain_tlv,502	-12750, 0);503static const DECLARE_TLV_DB_MINMAX_MUTE(pcm1690_dig_gain_tlv,504	-25500, 0);505static const DECLARE_TLV_DB_MINMAX_MUTE(pcm9211_dig_gain_tlv,506	-11450, 2000);507static const DECLARE_TLV_DB_MINMAX_MUTE(adc5120_fgain_tlv,508	-10050, 2700);509static const DECLARE_TLV_DB_LINEAR(adc5120_chgain_tlv, 0, 4200);510static const DECLARE_TLV_DB_MINMAX_MUTE(pcm6260_fgain_tlv,511	-10000, 2700);512static const DECLARE_TLV_DB_LINEAR(pcm6260_chgain_tlv, 0, 4200);513static const DECLARE_TLV_DB_MINMAX_MUTE(taa5412_dig_vol_tlv,514	-8050, 4700);515static const DECLARE_TLV_DB_LINEAR(taa5412_fine_gain_tlv,516	-80, 70);517 518static int pcmdev_change_dev(struct pcmdevice_priv *pcm_priv,519	unsigned short dev_no)520{521	struct i2c_client *client = (struct i2c_client *)pcm_priv->client;522	struct regmap *map = pcm_priv->regmap;523	int ret;524 525	if (client->addr == pcm_priv->addr[dev_no])526		return 0;527 528	client->addr = pcm_priv->addr[dev_no];529	/* All pcmdevices share the same regmap, clear the page530	 * inside regmap once switching to another pcmdevice.531	 * Register 0 at any pages inside pcmdevice is the same532	 * one for page-switching.533	 */534	ret = regmap_write(map, PCMDEVICE_PAGE_SELECT, 0);535	if (ret < 0)536		dev_err(pcm_priv->dev, "%s: err = %d\n", __func__, ret);537 538	return ret;539}540 541static int pcmdev_dev_read(struct pcmdevice_priv *pcm_dev,542	unsigned int dev_no, unsigned int reg, unsigned int *val)543{544	struct regmap *map = pcm_dev->regmap;545	int ret;546 547	if (dev_no >= pcm_dev->ndev) {548		dev_err(pcm_dev->dev, "%s: no such channel(%d)\n", __func__,549			dev_no);550		return -EINVAL;551	}552 553	ret = pcmdev_change_dev(pcm_dev, dev_no);554	if (ret < 0) {555		dev_err(pcm_dev->dev, "%s: chg dev err = %d\n", __func__, ret);556		return ret;557	}558 559	ret = regmap_read(map, reg, val);560	if (ret < 0)561		dev_err(pcm_dev->dev, "%s: err = %d\n", __func__, ret);562 563	return ret;564}565 566static int pcmdev_dev_update_bits(struct pcmdevice_priv *pcm_dev,567	unsigned int dev_no, unsigned int reg, unsigned int mask,568	unsigned int value)569{570	struct regmap *map = pcm_dev->regmap;571	int ret;572 573	if (dev_no >= pcm_dev->ndev) {574		dev_err(pcm_dev->dev, "%s: no such channel(%d)\n", __func__,575			dev_no);576		return -EINVAL;577	}578 579	ret = pcmdev_change_dev(pcm_dev, dev_no);580	if (ret < 0) {581		dev_err(pcm_dev->dev, "%s: chg dev err = %d\n", __func__, ret);582		return ret;583	}584 585	ret = regmap_update_bits(map, reg, mask, value);586	if (ret < 0)587		dev_err(pcm_dev->dev, "%s: update_bits err=%d\n",588			__func__, ret);589 590	return ret;591}592 593static int pcmdev_get_volsw(struct snd_kcontrol *kcontrol,594	struct snd_ctl_elem_value *ucontrol, int vol_ctrl_type)595{596	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);597	struct pcmdevice_priv *pcm_dev =598		snd_soc_component_get_drvdata(component);599	struct pcmdevice_mixer_control *mc =600		(struct pcmdevice_mixer_control *)kcontrol->private_value;601	int max = mc->max, ret;602	unsigned int mask = BIT(fls(max)) - 1;603	unsigned int dev_no = mc->dev_no;604	unsigned int shift = mc->shift;605	unsigned int reg = mc->reg;606	unsigned int val;607 608	mutex_lock(&pcm_dev->codec_lock);609 610	if (pcm_dev->chip_id == PCM1690) {611		ret = pcmdev_dev_read(pcm_dev, dev_no, PCM1690_REG_MODE_CTRL,612			&val);613		if (ret) {614			dev_err(pcm_dev->dev, "%s: read mode err=%d\n",615				__func__, ret);616			goto out;617		}618		val &= PCM1690_REG_MODE_CTRL_DAMS_MSK;619		/* Set to wide-range mode, before using vol ctrl. */620		if (!val && vol_ctrl_type == PCMDEV_PCM1690_VOL_CTRL) {621			ucontrol->value.integer.value[0] = -25500;622			goto out;623		}624		/* Set to fine mode, before using fine vol ctrl. */625		if (val && vol_ctrl_type == PCMDEV_PCM1690_FINE_VOL_CTRL) {626			ucontrol->value.integer.value[0] = -12750;627			goto out;628		}629	}630 631	ret = pcmdev_dev_read(pcm_dev, dev_no, reg, &val);632	if (ret) {633		dev_err(pcm_dev->dev, "%s: read err=%d\n",634			__func__, ret);635		goto out;636	}637 638	val = (val >> shift) & mask;639	val = (val > max) ? max : val;640	val = mc->invert ? max - val : val;641	ucontrol->value.integer.value[0] = val;642out:643	mutex_unlock(&pcm_dev->codec_lock);644	return ret;645}646 647static int pcmdevice_get_volsw(struct snd_kcontrol *kcontrol,648	struct snd_ctl_elem_value *ucontrol)649{650	return pcmdev_get_volsw(kcontrol, ucontrol, PCMDEV_GENERIC_VOL_CTRL);651}652 653static int pcm1690_get_volsw(struct snd_kcontrol *kcontrol,654	struct snd_ctl_elem_value *ucontrol)655{656	return pcmdev_get_volsw(kcontrol, ucontrol, PCMDEV_PCM1690_VOL_CTRL);657}658 659static int pcm1690_get_finevolsw(struct snd_kcontrol *kcontrol,660		struct snd_ctl_elem_value *ucontrol)661{662	return pcmdev_get_volsw(kcontrol, ucontrol,663		PCMDEV_PCM1690_FINE_VOL_CTRL);664}665 666static int pcmdev_put_volsw(struct snd_kcontrol *kcontrol,667	struct snd_ctl_elem_value *ucontrol, int vol_ctrl_type)668{669	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);670	struct pcmdevice_priv *pcm_dev =671		snd_soc_component_get_drvdata(component);672	struct pcmdevice_mixer_control *mc =673		(struct pcmdevice_mixer_control *)kcontrol->private_value;674	int max = mc->max, rc;675	unsigned int mask = BIT(fls(max)) - 1;676	unsigned int dev_no = mc->dev_no;677	unsigned int shift = mc->shift;678	unsigned int val, val_mask;679	unsigned int reg = mc->reg;680 681	mutex_lock(&pcm_dev->codec_lock);682	val = ucontrol->value.integer.value[0] & mask;683	val = (val > max) ? max : val;684	val = mc->invert ? max - val : val;685	val_mask = mask << shift;686	val = val << shift;687 688	switch (vol_ctrl_type) {689	case PCMDEV_PCM1690_VOL_CTRL:690		val_mask |= PCM1690_REG_MODE_CTRL_DAMS_MSK;691		val |= PCM1690_REG_MODE_CTRL_DAMS_WIDE_RANGE;692		break;693	case PCMDEV_PCM1690_FINE_VOL_CTRL:694		val_mask |= PCM1690_REG_MODE_CTRL_DAMS_MSK;695		val |= PCM1690_REG_MODE_CTRL_DAMS_FINE_STEP;696		break;697	}698 699	rc = pcmdev_dev_update_bits(pcm_dev, dev_no, reg, val_mask, val);700	if (rc < 0)701		dev_err(pcm_dev->dev, "%s: update_bits err = %d\n",702			__func__, rc);703	else704		rc = 1;705	mutex_unlock(&pcm_dev->codec_lock);706	return rc;707}708 709static int pcmdevice_put_volsw(struct snd_kcontrol *kcontrol,710	struct snd_ctl_elem_value *ucontrol)711{712	return pcmdev_put_volsw(kcontrol, ucontrol, PCMDEV_GENERIC_VOL_CTRL);713}714 715static int pcm1690_put_volsw(struct snd_kcontrol *kcontrol,716	struct snd_ctl_elem_value *ucontrol)717{718	return pcmdev_put_volsw(kcontrol, ucontrol, PCMDEV_PCM1690_VOL_CTRL);719}720 721static int pcm1690_put_finevolsw(struct snd_kcontrol *kcontrol,722	struct snd_ctl_elem_value *ucontrol)723{724	return pcmdev_put_volsw(kcontrol, ucontrol,725		PCMDEV_PCM1690_FINE_VOL_CTRL);726}727 728static const struct pcmdev_ctrl_info pcmdev_gain_ctl_info[][2] = {729	// ADC3120730	{731		{732			.gain = adc5120_chgain_tlv,733			.pcmdev_ctrl = adc5120_analog_gain_ctl,734			.ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl),735			.get = pcmdevice_get_volsw,736			.put = pcmdevice_put_volsw,737			.pcmdev_ctrl_name_id = 0,738		},739		{740			.gain = adc5120_fgain_tlv,741			.pcmdev_ctrl = adc5120_digi_gain_ctl,742			.ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl),743			.get = pcmdevice_get_volsw,744			.put = pcmdevice_put_volsw,745			.pcmdev_ctrl_name_id = 1,746		},747	},748	// ADC5120749	{750		{751			.gain = adc5120_chgain_tlv,752			.pcmdev_ctrl = adc5120_analog_gain_ctl,753			.ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl),754			.get = pcmdevice_get_volsw,755			.put = pcmdevice_put_volsw,756			.pcmdev_ctrl_name_id = 0,757		},758		{759			.gain = adc5120_fgain_tlv,760			.pcmdev_ctrl = adc5120_digi_gain_ctl,761			.ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl),762			.get = pcmdevice_get_volsw,763			.put = pcmdevice_put_volsw,764			.pcmdev_ctrl_name_id = 1,765		},766	},767	// ADC6120768	{769		{770			.gain = adc5120_chgain_tlv,771			.pcmdev_ctrl = adc5120_analog_gain_ctl,772			.ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl),773			.get = pcmdevice_get_volsw,774			.put = pcmdevice_put_volsw,775			.pcmdev_ctrl_name_id = 0,776		},777		{778			.gain = adc5120_fgain_tlv,779			.pcmdev_ctrl = adc5120_digi_gain_ctl,780			.ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl),781			.get = pcmdevice_get_volsw,782			.put = pcmdevice_put_volsw,783			.pcmdev_ctrl_name_id = 1,784		},785	},786	// DIX4192787	{788		{789			.ctrl_array_size = 0,790		},791		{792			.ctrl_array_size = 0,793		},794	},795	// PCM1690796	{797		{798			.gain = pcm1690_fine_dig_gain_tlv,799			.pcmdev_ctrl = pcm1690_digi_gain_ctl,800			.ctrl_array_size = ARRAY_SIZE(pcm1690_digi_gain_ctl),801			.get = pcm1690_get_volsw,802			.put = pcm1690_put_volsw,803			.pcmdev_ctrl_name_id = 1,804		},805		{806			.gain = pcm1690_dig_gain_tlv,807			.pcmdev_ctrl = pcm1690_digi_gain_ctl,808			.ctrl_array_size = ARRAY_SIZE(pcm1690_digi_gain_ctl),809			.get = pcm1690_get_finevolsw,810			.put = pcm1690_put_finevolsw,811			.pcmdev_ctrl_name_id = 2,812		},813	},814	// PCM3120815	{816		{817			.gain = adc5120_chgain_tlv,818			.pcmdev_ctrl = adc5120_analog_gain_ctl,819			.ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl),820			.get = pcmdevice_get_volsw,821			.put = pcmdevice_put_volsw,822			.pcmdev_ctrl_name_id = 0,823		},824		{825			.gain = adc5120_fgain_tlv,826			.pcmdev_ctrl = adc5120_digi_gain_ctl,827			.ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl),828			.get = pcmdevice_get_volsw,829			.put = pcmdevice_put_volsw,830			.pcmdev_ctrl_name_id = 1,831		},832	},833	// PCM3140834	{835		{836			.gain = pcm6260_chgain_tlv,837			.pcmdev_ctrl = pcm6240_analog_gain_ctl,838			.ctrl_array_size = ARRAY_SIZE(pcm6240_analog_gain_ctl),839			.get = pcmdevice_get_volsw,840			.put = pcmdevice_put_volsw,841			.pcmdev_ctrl_name_id = 0,842		},843		{844			.gain = pcm6260_fgain_tlv,845			.pcmdev_ctrl = pcm6240_digi_gain_ctl,846			.ctrl_array_size = ARRAY_SIZE(pcm6240_digi_gain_ctl),847			.get = pcmdevice_get_volsw,848			.put = pcmdevice_put_volsw,849			.pcmdev_ctrl_name_id = 1,850		},851	},852	// PCM5120853	{854		{855			.gain = adc5120_chgain_tlv,856			.pcmdev_ctrl = adc5120_analog_gain_ctl,857			.ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl),858			.get = pcmdevice_get_volsw,859			.put = pcmdevice_put_volsw,860			.pcmdev_ctrl_name_id = 0,861		},862		{863			.gain = adc5120_fgain_tlv,864			.pcmdev_ctrl = adc5120_digi_gain_ctl,865			.ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl),866			.get = pcmdevice_get_volsw,867			.put = pcmdevice_put_volsw,868			.pcmdev_ctrl_name_id = 1,869		},870	},871	// PCM5140872	{873		{874			.gain = pcm6260_chgain_tlv,875			.pcmdev_ctrl = pcm6240_analog_gain_ctl,876			.ctrl_array_size = ARRAY_SIZE(pcm6240_analog_gain_ctl),877			.get = pcmdevice_get_volsw,878			.put = pcmdevice_put_volsw,879			.pcmdev_ctrl_name_id = 0,880		},881		{882			.gain = pcm6260_fgain_tlv,883			.pcmdev_ctrl = pcm6240_digi_gain_ctl,884			.ctrl_array_size = ARRAY_SIZE(pcm6240_digi_gain_ctl),885			.get = pcmdevice_get_volsw,886			.put = pcmdevice_put_volsw,887			.pcmdev_ctrl_name_id = 1,888		},889	},890	// PCM6120891	{892		{893			.gain = adc5120_chgain_tlv,894			.pcmdev_ctrl = adc5120_analog_gain_ctl,895			.ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl),896			.get = pcmdevice_get_volsw,897			.put = pcmdevice_put_volsw,898			.pcmdev_ctrl_name_id = 0,899		},900		{901			.gain = adc5120_fgain_tlv,902			.pcmdev_ctrl = adc5120_digi_gain_ctl,903			.ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl),904			.get = pcmdevice_get_volsw,905			.put = pcmdevice_put_volsw,906			.pcmdev_ctrl_name_id = 1,907		},908	},909	// PCM6140910	{911		{912			.gain = pcm6260_chgain_tlv,913			.pcmdev_ctrl = pcm6240_analog_gain_ctl,914			.ctrl_array_size = ARRAY_SIZE(pcm6240_analog_gain_ctl),915			.get = pcmdevice_get_volsw,916			.put = pcmdevice_put_volsw,917			.pcmdev_ctrl_name_id = 0,918		},919		{920			.gain = pcm6260_fgain_tlv,921			.pcmdev_ctrl = pcm6240_digi_gain_ctl,922			.ctrl_array_size = ARRAY_SIZE(pcm6240_digi_gain_ctl),923			.get = pcmdevice_get_volsw,924			.put = pcmdevice_put_volsw,925			.pcmdev_ctrl_name_id = 1,926		},927	},928	// PCM6240929	{930		{931			.gain = pcm6260_chgain_tlv,932			.pcmdev_ctrl = pcm6240_analog_gain_ctl,933			.ctrl_array_size = ARRAY_SIZE(pcm6240_analog_gain_ctl),934			.get = pcmdevice_get_volsw,935			.put = pcmdevice_put_volsw,936			.pcmdev_ctrl_name_id = 0,937		},938		{939			.gain = pcm6260_fgain_tlv,940			.pcmdev_ctrl = pcm6240_digi_gain_ctl,941			.ctrl_array_size = ARRAY_SIZE(pcm6240_digi_gain_ctl),942			.get = pcmdevice_get_volsw,943			.put = pcmdevice_put_volsw,944			.pcmdev_ctrl_name_id = 1,945		},946	},947	// PCM6260948	{949		{950			.gain = pcm6260_chgain_tlv,951			.pcmdev_ctrl = pcm6260_analog_gain_ctl,952			.ctrl_array_size = ARRAY_SIZE(pcm6260_analog_gain_ctl),953			.get = pcmdevice_get_volsw,954			.put = pcmdevice_put_volsw,955			.pcmdev_ctrl_name_id = 0,956		},957		{958			.gain = pcm6260_fgain_tlv,959			.pcmdev_ctrl = pcm6260_digi_gain_ctl,960			.ctrl_array_size = ARRAY_SIZE(pcm6260_digi_gain_ctl),961			.get = pcmdevice_get_volsw,962			.put = pcmdevice_put_volsw,963			.pcmdev_ctrl_name_id = 1,964		},965	},966	// PCM9211967	{968		{969			.ctrl_array_size = 0,970		},971		{972			.gain = pcm9211_dig_gain_tlv,973			.pcmdev_ctrl = pcm9211_digi_gain_ctl,974			.ctrl_array_size = ARRAY_SIZE(pcm9211_digi_gain_ctl),975			.get = pcmdevice_get_volsw,976			.put = pcmdevice_put_volsw,977			.pcmdev_ctrl_name_id = 1,978		},979 980	},981	// PCMD3140982	{983		{984			.gain = taa5412_fine_gain_tlv,985			.pcmdev_ctrl = pcmd3140_fine_gain_ctl,986			.ctrl_array_size = ARRAY_SIZE(pcmd3140_fine_gain_ctl),987			.get = pcmdevice_get_volsw,988			.put = pcmdevice_put_volsw,989			.pcmdev_ctrl_name_id = 2,990		},991		{992			.gain = pcmd3140_dig_gain_tlv,993			.pcmdev_ctrl = pcmd3140_digi_gain_ctl,994			.ctrl_array_size = ARRAY_SIZE(pcmd3140_digi_gain_ctl),995			.get = pcmdevice_get_volsw,996			.put = pcmdevice_put_volsw,997			.pcmdev_ctrl_name_id = 1,998		},999	},1000	// PCMD31801001	{1002		{1003			.gain = taa5412_fine_gain_tlv,1004			.pcmdev_ctrl = pcmd3180_fine_gain_ctl,1005			.ctrl_array_size = ARRAY_SIZE(pcmd3180_fine_gain_ctl),1006			.get = pcmdevice_get_volsw,1007			.put = pcmdevice_put_volsw,1008			.pcmdev_ctrl_name_id = 2,1009		},1010		{1011			.gain = pcmd3140_dig_gain_tlv,1012			.pcmdev_ctrl = pcmd3180_digi_gain_ctl,1013			.ctrl_array_size = ARRAY_SIZE(pcmd3180_digi_gain_ctl),1014			.get = pcmdevice_get_volsw,1015			.put = pcmdevice_put_volsw,1016			.pcmdev_ctrl_name_id = 1,1017		},1018	},1019	// PCMD512X1020	{1021		{1022			.ctrl_array_size = 0,1023		},1024		{1025			.ctrl_array_size = 0,1026		},1027	},1028	// TAA52121029	{1030		{1031			.gain = taa5412_fine_gain_tlv,1032			.pcmdev_ctrl = taa5412_fine_gain_ctl,1033			.ctrl_array_size = ARRAY_SIZE(taa5412_fine_gain_ctl),1034			.get = pcmdevice_get_volsw,1035			.put = pcmdevice_put_volsw,1036			.pcmdev_ctrl_name_id = 2,1037		},1038		{1039			.gain = taa5412_dig_vol_tlv,1040			.pcmdev_ctrl = taa5412_digi_vol_ctl,1041			.ctrl_array_size = ARRAY_SIZE(taa5412_digi_vol_ctl),1042			.get = pcmdevice_get_volsw,1043			.put = pcmdevice_put_volsw,1044			.pcmdev_ctrl_name_id = 1,1045		},1046	},1047	// TAA54121048	{1049		{1050			.gain = taa5412_fine_gain_tlv,1051			.pcmdev_ctrl = taa5412_fine_gain_ctl,1052			.ctrl_array_size = ARRAY_SIZE(taa5412_fine_gain_ctl),1053			.get = pcmdevice_get_volsw,1054			.put = pcmdevice_put_volsw,1055			.pcmdev_ctrl_name_id = 2,1056		},1057		{1058			.gain = taa5412_dig_vol_tlv,1059			.pcmdev_ctrl = taa5412_digi_vol_ctl,1060			.ctrl_array_size = ARRAY_SIZE(taa5412_digi_vol_ctl),1061			.get = pcmdevice_get_volsw,1062			.put = pcmdevice_put_volsw,1063			.pcmdev_ctrl_name_id = 1,1064		},1065	},1066	// TAD52121067	{1068		{1069			.ctrl_array_size = 0,1070		},1071		{1072			.ctrl_array_size = 0,1073		},1074	},1075	// TAD54121076	{1077		{1078			.ctrl_array_size = 0,1079		},1080		{1081			.ctrl_array_size = 0,1082		},1083	},1084};1085 1086static int pcmdev_dev_bulk_write(struct pcmdevice_priv *pcm_dev,1087	unsigned int dev_no, unsigned int reg, unsigned char *data,1088	unsigned int len)1089{1090	struct regmap *map = pcm_dev->regmap;1091	int ret;1092 1093	if (dev_no >= pcm_dev->ndev) {1094		dev_err(pcm_dev->dev, "%s: no such channel(%d)\n", __func__,1095			dev_no);1096		return -EINVAL;1097	}1098 1099	ret = pcmdev_change_dev(pcm_dev, dev_no);1100	if (ret < 0) {1101		dev_err(pcm_dev->dev, "%s: chg dev err = %d\n", __func__, ret);1102		return ret;1103	}1104 1105	ret = regmap_bulk_write(map, reg, data, len);1106	if (ret < 0)1107		dev_err(pcm_dev->dev, "%s: bulk_write err = %d\n", __func__,1108			ret);1109 1110	return ret;1111}1112 1113static int pcmdev_dev_write(struct pcmdevice_priv *pcm_dev,1114	unsigned int dev_no, unsigned int reg, unsigned int value)1115{1116	struct regmap *map = pcm_dev->regmap;1117	int ret;1118 1119	if (dev_no >= pcm_dev->ndev) {1120		dev_err(pcm_dev->dev, "%s: no such channel(%d)\n", __func__,1121			dev_no);1122		return -EINVAL;1123	}1124 1125	ret = pcmdev_change_dev(pcm_dev, dev_no);1126	if (ret < 0) {1127		dev_err(pcm_dev->dev, "%s: chg dev err = %d\n", __func__, ret);1128		return ret;1129	}1130 1131	ret = regmap_write(map, reg, value);1132	if (ret < 0)1133		dev_err(pcm_dev->dev, "%s: err = %d\n", __func__, ret);1134 1135	return ret;1136}1137 1138static int pcmdevice_info_profile(1139	struct snd_kcontrol *kcontrol,1140	struct snd_ctl_elem_info *uinfo)1141{1142	struct snd_soc_component *codec1143		= snd_soc_kcontrol_component(kcontrol);1144	struct pcmdevice_priv *pcm_dev =1145		snd_soc_component_get_drvdata(codec);1146 1147	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;1148	uinfo->count = 1;1149	uinfo->value.integer.min = 0;1150	uinfo->value.integer.max = max(0, pcm_dev->regbin.ncfgs - 1);1151 1152	return 0;1153}1154 1155static int pcmdevice_get_profile_id(1156	struct snd_kcontrol *kcontrol,1157	struct snd_ctl_elem_value *ucontrol)1158{1159	struct snd_soc_component *codec1160		= snd_soc_kcontrol_component(kcontrol);1161	struct pcmdevice_priv *pcm_dev =1162		snd_soc_component_get_drvdata(codec);1163 1164	ucontrol->value.integer.value[0] = pcm_dev->cur_conf;1165 1166	return 0;1167}1168 1169static int pcmdevice_set_profile_id(1170	struct snd_kcontrol *kcontrol,1171	struct snd_ctl_elem_value *ucontrol)1172{1173	struct snd_soc_component *codec1174		= snd_soc_kcontrol_component(kcontrol);1175	struct pcmdevice_priv *pcm_dev =1176		snd_soc_component_get_drvdata(codec);1177	int nr_profile = ucontrol->value.integer.value[0];1178	int max = pcm_dev->regbin.ncfgs - 1;1179	int ret = 0;1180 1181	nr_profile = clamp(nr_profile, 0, max);1182 1183	if (pcm_dev->cur_conf != nr_profile) {1184		pcm_dev->cur_conf = nr_profile;1185		ret = 1;1186	}1187 1188	return ret;1189}1190 1191static int pcmdevice_info_volsw(struct snd_kcontrol *kcontrol,1192	struct snd_ctl_elem_info *uinfo)1193{1194	struct pcmdevice_mixer_control *mc =1195		(struct pcmdevice_mixer_control *)kcontrol->private_value;1196 1197	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;1198	uinfo->count = 1;1199	uinfo->value.integer.min = 0;1200	uinfo->value.integer.max = mc->max;1201	return 0;1202}1203 1204static void pcm9211_sw_rst(struct pcmdevice_priv *pcm_dev)1205{1206	int ret, i;1207 1208	for (i = 0; i < pcm_dev->ndev; i++) {1209		ret = pcmdev_dev_update_bits(pcm_dev, i,1210			PCM9211_REG_SW_CTRL, PCM9211_REG_SW_CTRL_MRST_MSK,1211			PCM9211_REG_SW_CTRL_MRST);1212		if (ret < 0)1213			dev_err(pcm_dev->dev, "%s: dev %d swreset fail %d\n",1214				__func__, i, ret);1215	}1216}1217 1218static void pcmdevice_sw_rst(struct pcmdevice_priv *pcm_dev)1219{1220	int ret, i;1221 1222	for (i = 0; i < pcm_dev->ndev; i++) {1223		ret = pcmdev_dev_write(pcm_dev, i, PCMDEVICE_REG_SWRESET,1224			PCMDEVICE_REG_SWRESET_RESET);1225		if (ret < 0)1226			dev_err(pcm_dev->dev, "%s: dev %d swreset fail %d\n",1227				__func__, i, ret);1228	}1229}1230 1231static struct pcmdevice_config_info *pcmdevice_add_config(void *ctxt,1232	const unsigned char *config_data, unsigned int config_size,1233	int *status)1234{1235	struct pcmdevice_priv *pcm_dev = (struct pcmdevice_priv *)ctxt;1236	struct pcmdevice_config_info *cfg_info;1237	struct pcmdevice_block_data **bk_da;1238	unsigned int config_offset = 0, i;1239 1240	cfg_info = kzalloc(sizeof(struct pcmdevice_config_info), GFP_KERNEL);1241	if (!cfg_info) {1242		*status = -ENOMEM;1243		goto out;1244	}1245 1246	if (pcm_dev->regbin.fw_hdr.binary_version_num >= 0x105) {1247		if (config_offset + 64 > (int)config_size) {1248			*status = -EINVAL;1249			dev_err(pcm_dev->dev,1250				"%s: cfg_name out of boundary\n", __func__);1251			goto out;1252		}1253		memcpy(cfg_info->cfg_name, &config_data[config_offset], 64);1254		config_offset += 64;1255	}1256 1257	if (config_offset + 4 > config_size) {1258		*status = -EINVAL;1259		dev_err(pcm_dev->dev, "%s: nblocks out of boundary\n",1260			__func__);1261		goto out;1262	}1263	cfg_info->nblocks =1264		get_unaligned_be32(&config_data[config_offset]);1265	config_offset += 4;1266 1267	bk_da = cfg_info->blk_data = kcalloc(cfg_info->nblocks,1268		sizeof(struct pcmdevice_block_data *), GFP_KERNEL);1269	if (!bk_da) {1270		*status = -ENOMEM;1271		goto out;1272	}1273	cfg_info->real_nblocks = 0;1274	for (i = 0; i < cfg_info->nblocks; i++) {1275		if (config_offset + 12 > config_size) {1276			*status = -EINVAL;1277			dev_err(pcm_dev->dev,1278				"%s: out of boundary i = %d nblocks = %u\n",1279				__func__, i, cfg_info->nblocks);1280			break;1281		}1282		bk_da[i] = kzalloc(sizeof(struct pcmdevice_block_data),1283			GFP_KERNEL);1284		if (!bk_da[i]) {1285			*status = -ENOMEM;1286			break;1287		}1288		bk_da[i]->dev_idx = config_data[config_offset];1289		config_offset++;1290 1291		bk_da[i]->block_type = config_data[config_offset];1292		config_offset++;1293 1294		if (bk_da[i]->block_type == PCMDEVICE_BIN_BLK_PRE_POWER_UP) {1295			if (bk_da[i]->dev_idx == 0)1296				cfg_info->active_dev =1297					(1 << pcm_dev->ndev) - 1;1298			else1299				cfg_info->active_dev =1300					1 << (bk_da[i]->dev_idx - 1);1301		}1302 1303		bk_da[i]->yram_checksum =1304			get_unaligned_be16(&config_data[config_offset]);1305		config_offset += 2;1306		bk_da[i]->block_size =1307			get_unaligned_be32(&config_data[config_offset]);1308		config_offset += 4;1309 1310		bk_da[i]->n_subblks =1311			get_unaligned_be32(&config_data[config_offset]);1312 1313		config_offset += 4;1314 1315		if (config_offset + bk_da[i]->block_size > config_size) {1316			*status = -EINVAL;1317			dev_err(pcm_dev->dev,1318				"%s: out of boundary: i = %d blks = %u\n",1319				__func__, i, cfg_info->nblocks);1320			break;1321		}1322 1323		bk_da[i]->regdata = kmemdup(&config_data[config_offset],1324			bk_da[i]->block_size, GFP_KERNEL);1325		if (!bk_da[i]->regdata) {1326			*status = -ENOMEM;1327			goto out;1328		}1329		config_offset += bk_da[i]->block_size;1330		cfg_info->real_nblocks += 1;1331	}1332out:1333	return cfg_info;1334}1335 1336static int pcmdev_gain_ctrl_add(struct pcmdevice_priv *pcm_dev,1337	int dev_no, int ctl_id)1338{1339	struct i2c_adapter *adap = pcm_dev->client->adapter;1340	struct snd_soc_component *comp = pcm_dev->component;1341	struct pcmdevice_mixer_control *pcmdev_ctrl;1342	struct snd_kcontrol_new *pcmdev_controls;1343	int ret, mix_index = 0, name_id, chn;1344	unsigned int id = pcm_dev->chip_id;1345	const int nr_chn =1346		pcmdev_gain_ctl_info[id][ctl_id].ctrl_array_size;1347	const char *ctrl_name;1348	char *name;1349 1350	if (!nr_chn) {1351		dev_dbg(pcm_dev->dev, "%s: no gain ctrl for %s\n", __func__,1352			pcm_dev->dev_name);1353		return 0;1354	}1355 1356	pcmdev_controls = devm_kzalloc(pcm_dev->dev,1357		nr_chn * sizeof(struct snd_kcontrol_new), GFP_KERNEL);1358	if (!pcmdev_controls)1359		return -ENOMEM;1360 1361	name_id = pcmdev_gain_ctl_info[id][ctl_id].pcmdev_ctrl_name_id;1362 1363	ctrl_name = pcmdev_ctrl_name[name_id];1364 1365	for (chn = 1; chn <= nr_chn; chn++) {1366		name = devm_kzalloc(pcm_dev->dev,1367			SNDRV_CTL_ELEM_ID_NAME_MAXLEN, GFP_KERNEL);1368		if (!name) {1369			ret = -ENOMEM;1370			goto out;1371		}1372		scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,1373			ctrl_name, pcm_dev->upper_dev_name, adap->nr,1374			dev_no, chn);1375		pcmdev_controls[mix_index].tlv.p =1376			pcmdev_gain_ctl_info[id][ctl_id].gain;1377		pcmdev_ctrl = devm_kmemdup(pcm_dev->dev,1378			&pcmdev_gain_ctl_info[id][ctl_id].pcmdev_ctrl[chn - 1],1379			sizeof(*pcmdev_ctrl), GFP_KERNEL);1380		if (!pcmdev_ctrl) {1381			ret = -ENOMEM;1382			goto out;1383		}1384		pcmdev_ctrl->dev_no = dev_no;1385		pcmdev_controls[mix_index].private_value =1386			(unsigned long)pcmdev_ctrl;1387		pcmdev_controls[mix_index].name = name;1388		pcmdev_controls[mix_index].access =1389			SNDRV_CTL_ELEM_ACCESS_TLV_READ |1390			SNDRV_CTL_ELEM_ACCESS_READWRITE;1391		pcmdev_controls[mix_index].iface =1392			SNDRV_CTL_ELEM_IFACE_MIXER;1393		pcmdev_controls[mix_index].info = pcmdevice_info_volsw;1394		pcmdev_controls[mix_index].get =1395			pcmdev_gain_ctl_info[id][ctl_id].get;1396		pcmdev_controls[mix_index].put =1397			pcmdev_gain_ctl_info[id][ctl_id].put;1398		mix_index++;1399	}1400 1401	ret = snd_soc_add_component_controls(comp, pcmdev_controls, mix_index);1402	if (ret)1403		dev_err(pcm_dev->dev, "%s: add_controls err = %d\n",1404			__func__, ret);1405out:1406	return ret;1407}1408 1409static int pcmdev_profile_ctrl_add(struct pcmdevice_priv *pcm_dev)1410{1411	struct snd_soc_component *comp = pcm_dev->component;1412	struct i2c_adapter *adap = pcm_dev->client->adapter;1413	struct snd_kcontrol_new *pcmdev_ctrl;1414	char *name;1415	int ret;1416 1417	pcmdev_ctrl = devm_kzalloc(pcm_dev->dev,1418		sizeof(struct snd_kcontrol_new), GFP_KERNEL);1419	if (!pcmdev_ctrl)1420		return -ENOMEM;1421 1422	/* Create a mixer item for selecting the active profile */1423	name = devm_kzalloc(pcm_dev->dev, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,1424		GFP_KERNEL);1425	if (!name)1426		return -ENOMEM;1427 1428	scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,1429		"%s i2c%d Profile id", pcm_dev->upper_dev_name, adap->nr);1430	pcmdev_ctrl->name = name;1431	pcmdev_ctrl->iface = SNDRV_CTL_ELEM_IFACE_MIXER;1432	pcmdev_ctrl->info = pcmdevice_info_profile;1433	pcmdev_ctrl->get = pcmdevice_get_profile_id;1434	pcmdev_ctrl->put = pcmdevice_set_profile_id;1435 1436	ret = snd_soc_add_component_controls(comp, pcmdev_ctrl, 1);1437	if (ret)1438		dev_err(pcm_dev->dev, "%s: add_controls err = %d\n",1439			__func__, ret);1440 1441	return ret;1442}1443 1444static void pcmdevice_config_info_remove(void *ctxt)1445{1446	struct pcmdevice_priv *pcm_dev = (struct pcmdevice_priv *) ctxt;1447	struct pcmdevice_regbin *regbin = &(pcm_dev->regbin);1448	struct pcmdevice_config_info **cfg_info = regbin->cfg_info;1449	int i, j;1450 1451	if (!cfg_info)1452		return;1453	for (i = 0; i < regbin->ncfgs; i++) {1454		if (!cfg_info[i])1455			continue;1456		if (cfg_info[i]->blk_data) {1457			for (j = 0; j < (int)cfg_info[i]->real_nblocks; j++) {1458				if (!cfg_info[i]->blk_data[j])1459					continue;1460				kfree(cfg_info[i]->blk_data[j]->regdata);1461				kfree(cfg_info[i]->blk_data[j]);1462			}1463			kfree(cfg_info[i]->blk_data);1464		}1465		kfree(cfg_info[i]);1466	}1467	kfree(cfg_info);1468}1469 1470static int pcmdev_regbin_ready(const struct firmware *fmw, void *ctxt)1471{1472	struct pcmdevice_config_info **cfg_info;1473	struct pcmdevice_priv *pcm_dev = ctxt;1474	struct pcmdevice_regbin_hdr *fw_hdr;1475	struct pcmdevice_regbin *regbin;1476	unsigned int total_config_sz = 0;1477	int offset = 0, ret = 0, i;1478	unsigned char *buf;1479 1480	regbin = &(pcm_dev->regbin);1481	fw_hdr = &(regbin->fw_hdr);1482	if (!fmw || !fmw->data) {1483		dev_err(pcm_dev->dev, "%s: failed to read %s\n",1484			__func__, pcm_dev->bin_name);1485		pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;1486		ret = -EINVAL;1487		goto out;1488	}1489	buf = (unsigned char *)fmw->data;1490 1491	fw_hdr->img_sz = get_unaligned_be32(&buf[offset]);1492	offset += 4;1493	if (fw_hdr->img_sz != fmw->size) {1494		dev_err(pcm_dev->dev, "%s: file size(%d) not match %u",1495			__func__, (int)fmw->size, fw_hdr->img_sz);1496		pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;1497		ret = -EINVAL;1498		goto out;1499	}1500 1501	fw_hdr->checksum = get_unaligned_be32(&buf[offset]);1502	offset += 4;1503	fw_hdr->binary_version_num = get_unaligned_be32(&buf[offset]);1504	if (fw_hdr->binary_version_num < 0x103) {1505		dev_err(pcm_dev->dev, "%s: bin version 0x%04x is out of date",1506			__func__, fw_hdr->binary_version_num);1507		pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;1508		ret = -EINVAL;1509		goto out;1510	}1511	offset += 4;1512	fw_hdr->drv_fw_version = get_unaligned_be32(&buf[offset]);1513	offset += 8;1514	fw_hdr->plat_type = buf[offset];1515	offset += 1;1516	fw_hdr->dev_family = buf[offset];1517	offset += 1;1518	fw_hdr->reserve = buf[offset];1519	offset += 1;1520	fw_hdr->ndev = buf[offset];1521	offset += 1;1522	if (fw_hdr->ndev != pcm_dev->ndev) {1523		dev_err(pcm_dev->dev, "%s: invalid ndev(%u)\n", __func__,1524			fw_hdr->ndev);1525		pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;1526		ret = -EINVAL;1527		goto out;1528	}1529 1530	if (offset + PCMDEVICE_MAX_REGBIN_DEVICES > fw_hdr->img_sz) {1531		dev_err(pcm_dev->dev, "%s: devs out of boundary!\n", __func__);1532		pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;1533		ret = -EINVAL;1534		goto out;1535	}1536 1537	for (i = 0; i < PCMDEVICE_MAX_REGBIN_DEVICES; i++, offset++)1538		fw_hdr->devs[i] = buf[offset];1539 1540	fw_hdr->nconfig = get_unaligned_be32(&buf[offset]);1541	offset += 4;1542 1543	for (i = 0; i < PCMDEVICE_CONFIG_SUM; i++) {1544		fw_hdr->config_size[i] = get_unaligned_be32(&buf[offset]);1545		offset += 4;1546		total_config_sz += fw_hdr->config_size[i];1547	}1548 1549	if (fw_hdr->img_sz - total_config_sz != (unsigned int)offset) {1550		dev_err(pcm_dev->dev, "%s: bin file error!\n", __func__);1551		pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;1552		ret = -EINVAL;1553		goto out;1554	}1555	cfg_info = kcalloc(fw_hdr->nconfig, sizeof(*cfg_info), GFP_KERNEL);1556	if (!cfg_info) {1557		pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;1558		ret = -ENOMEM;1559		goto out;1560	}1561	regbin->cfg_info = cfg_info;1562	regbin->ncfgs = 0;1563	for (i = 0; i < (int)fw_hdr->nconfig; i++) {1564		cfg_info[i] = pcmdevice_add_config(ctxt, &buf[offset],1565				fw_hdr->config_size[i], &ret);1566		if (ret) {1567			/* In case the bin file is partially destroyed. */1568			if (regbin->ncfgs == 0)1569				pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;1570			break;1571		}1572		offset += (int)fw_hdr->config_size[i];1573		regbin->ncfgs += 1;1574	}1575 1576out:1577	if (pcm_dev->fw_state == PCMDEVICE_FW_LOAD_FAILED) {1578		dev_err(pcm_dev->dev,1579			"%s: remove config due to fw load error!\n", __func__);1580		pcmdevice_config_info_remove(pcm_dev);1581	}1582 1583	return ret;1584}1585 1586static int pcmdevice_comp_probe(struct snd_soc_component *comp)1587{1588	struct pcmdevice_priv *pcm_dev = snd_soc_component_get_drvdata(comp);1589	struct i2c_adapter *adap = pcm_dev->client->adapter;1590	const struct firmware *fw_entry = NULL;1591	int ret, i, j;1592 1593	mutex_lock(&pcm_dev->codec_lock);1594 1595	pcm_dev->component = comp;1596 1597	for (i = 0; i < pcm_dev->ndev; i++) {1598		for (j = 0; j < 2; j++) {1599			ret = pcmdev_gain_ctrl_add(pcm_dev, i, j);1600			if (ret < 0)1601				goto out;1602		}1603	}1604 1605	if (comp->name_prefix) {1606		/* There's name_prefix defined in DTS. Bin file name will be1607		 * name_prefix.bin stores the firmware including register1608		 * setting and params for different filters inside chips, it1609		 * must be copied into firmware folder. The same types of1610		 * pcmdevices sitting on the same i2c bus will be aggregated as1611		 * one single codec, all of them share the same bin file.1612		 */1613		scnprintf(pcm_dev->bin_name, PCMDEVICE_BIN_FILENAME_LEN,1614			"%s.bin", comp->name_prefix);1615	} else {1616		/* There's NO name_prefix defined in DTS. Bin file name will be1617		 * device-name[defined in pcmdevice_i2c_id]-i2c-bus_id1618		 * [0,1,...,N]-sum[1,...,4]dev.bin stores the firmware1619		 * including register setting and params for different filters1620		 * inside chips, it must be copied into firmware folder. The1621		 * same types of pcmdevices sitting on the same i2c bus will be1622		 * aggregated as one single codec, all of them share the same1623		 * bin file.1624		 */1625		scnprintf(pcm_dev->bin_name, PCMDEVICE_BIN_FILENAME_LEN,1626			"%s-i2c-%d-%udev.bin", pcm_dev->dev_name, adap->nr,1627			pcm_dev->ndev);1628	}1629 1630	ret = request_firmware(&fw_entry, pcm_dev->bin_name, pcm_dev->dev);1631	if (ret) {1632		dev_err(pcm_dev->dev, "%s: request %s err = %d\n", __func__,1633			pcm_dev->bin_name, ret);1634		goto out;1635	}1636 1637	ret = pcmdev_regbin_ready(fw_entry, pcm_dev);1638	if (ret) {1639		dev_err(pcm_dev->dev, "%s: %s parse err = %d\n", __func__,1640			pcm_dev->bin_name, ret);1641		goto out;1642	}1643	ret = pcmdev_profile_ctrl_add(pcm_dev);1644out:1645	if (fw_entry)1646		release_firmware(fw_entry);1647 1648	mutex_unlock(&pcm_dev->codec_lock);1649	return ret;1650}1651 1652 1653static void pcmdevice_comp_remove(struct snd_soc_component *codec)1654{1655	struct pcmdevice_priv *pcm_dev = snd_soc_component_get_drvdata(codec);1656 1657	if (!pcm_dev)1658		return;1659	mutex_lock(&pcm_dev->codec_lock);1660	pcmdevice_config_info_remove(pcm_dev);1661	mutex_unlock(&pcm_dev->codec_lock);1662}1663 1664static const struct snd_soc_dapm_widget pcmdevice_dapm_widgets[] = {1665	SND_SOC_DAPM_AIF_IN("ASI", "ASI Playback", 0, SND_SOC_NOPM, 0, 0),1666	SND_SOC_DAPM_AIF_OUT("ASI1 OUT", "ASI1 Capture",1667		0, SND_SOC_NOPM, 0, 0),1668	SND_SOC_DAPM_OUTPUT("OUT"),1669	SND_SOC_DAPM_INPUT("MIC"),1670};1671 1672static const struct snd_soc_dapm_route pcmdevice_audio_map[] = {1673	{"OUT", NULL, "ASI"},1674	{"ASI1 OUT", NULL, "MIC"},1675};1676 1677static const struct snd_soc_component_driver1678	soc_codec_driver_pcmdevice = {1679	.probe			= pcmdevice_comp_probe,1680	.remove			= pcmdevice_comp_remove,1681	.dapm_widgets		= pcmdevice_dapm_widgets,1682	.num_dapm_widgets	= ARRAY_SIZE(pcmdevice_dapm_widgets),1683	.dapm_routes		= pcmdevice_audio_map,1684	.num_dapm_routes	= ARRAY_SIZE(pcmdevice_audio_map),1685	.suspend_bias_off	= 1,1686	.idle_bias_on		= 0,1687	.use_pmdown_time	= 1,1688	.endianness		= 1,1689};1690 1691static int pcmdev_single_byte_wr(struct pcmdevice_priv *pcm_dev,1692	unsigned char *data, int devn, int sublocksize)1693{1694	unsigned short len = get_unaligned_be16(&data[2]);1695	int offset = 2;1696	int i, ret;1697 1698	offset += 2;1699	if (offset + 4 * len > sublocksize) {1700		dev_err(pcm_dev->dev, "%s: dev-%d byt wr out of boundary\n",1701			__func__, devn);1702		return -EINVAL;1703	}1704 1705	for (i = 0; i < len; i++) {1706		ret = pcmdev_dev_write(pcm_dev, devn,1707			PCMDEVICE_REG(data[offset + 1], data[offset + 2]),1708			data[offset + 3]);1709		/* skip this error for next operation or next devices */1710		if (ret < 0)1711			dev_err(pcm_dev->dev, "%s: dev-%d single write err\n",1712				__func__, devn);1713 1714		offset += 4;1715	}1716 1717	return offset;1718}1719 1720static int pcmdev_burst_wr(struct pcmdevice_priv *pcm_dev,1721	unsigned char *data, int devn, int sublocksize)1722{1723	unsigned short len = get_unaligned_be16(&data[2]);1724	int offset = 2;1725	int ret;1726 1727	offset += 2;1728	if (offset + 4 + len > sublocksize) {1729		dev_err(pcm_dev->dev, "%s: dev-%d burst Out of boundary\n",1730			__func__, devn);1731		return -EINVAL;1732	}1733	if (len % 4) {1734		dev_err(pcm_dev->dev, "%s: dev-%d bst-len(%u) not div by 4\n",1735			__func__, devn, len);1736		return -EINVAL;1737	}1738	ret = pcmdev_dev_bulk_write(pcm_dev, devn,1739		PCMDEVICE_REG(data[offset + 1], data[offset + 2]),1740		&(data[offset + 4]), len);1741	/* skip this error for next devices */1742	if (ret < 0)1743		dev_err(pcm_dev->dev, "%s: dev-%d bulk_write err = %d\n",1744			__func__, devn, ret);1745 1746	offset += (len + 4);1747 1748	return offset;1749}1750 1751static int pcmdev_delay(struct pcmdevice_priv *pcm_dev,1752	unsigned char *data, int devn, int sublocksize)1753{1754	unsigned int delay_time = 0;1755	int offset = 2;1756 1757	if (offset + 2 > sublocksize) {1758		dev_err(pcm_dev->dev, "%s: dev-%d delay out of boundary\n",1759			__func__, devn);1760		return -EINVAL;1761	}1762	delay_time = get_unaligned_be16(&data[2]) * 1000;1763	usleep_range(delay_time, delay_time + 50);1764	offset += 2;1765 1766	return offset;1767}1768 1769static int pcmdev_bits_wr(struct pcmdevice_priv *pcm_dev,1770	unsigned char *data, int devn, int sublocksize)1771{1772	int offset = 2;1773	int ret;1774 1775	if (offset + 6 > sublocksize) {1776		dev_err(pcm_dev->dev, "%s: dev-%d bit write out of memory\n",1777			__func__, devn);1778		return -EINVAL;1779	}1780	ret = pcmdev_dev_update_bits(pcm_dev, devn,1781		PCMDEVICE_REG(data[offset + 3], data[offset + 4]),1782		data[offset + 1], data[offset + 5]);1783	/* skip this error for next devices */1784	if (ret < 0)1785		dev_err(pcm_dev->dev, "%s: dev-%d update_bits err = %d\n",1786			__func__, devn, ret);1787 1788	offset += 6;1789 1790	return offset;1791}1792 1793static int pcmdevice_process_block(void *ctxt, unsigned char *data,1794	unsigned char dev_idx, int sublocksize)1795{1796	struct pcmdevice_priv *pcm_dev = (struct pcmdevice_priv *)ctxt;1797	int devn, dev_end, ret = 0;1798	unsigned char subblk_typ = data[1];1799 1800	if (dev_idx) {1801		devn = dev_idx - 1;1802		dev_end = dev_idx;1803	} else {1804		devn = 0;1805		dev_end = pcm_dev->ndev;1806	}1807 1808	/* loop in case of several devices sharing the same sub-block */1809	for (; devn < dev_end; devn++) {1810		switch (subblk_typ) {1811		case PCMDEVICE_CMD_SING_W:1812		ret = pcmdev_single_byte_wr(pcm_dev, data, devn, sublocksize);1813			break;1814		case PCMDEVICE_CMD_BURST:1815		ret = pcmdev_burst_wr(pcm_dev, data, devn, sublocksize);1816			break;1817		case PCMDEVICE_CMD_DELAY:1818		ret = pcmdev_delay(pcm_dev, data, devn, sublocksize);1819			break;1820		case PCMDEVICE_CMD_FIELD_W:1821		ret = pcmdev_bits_wr(pcm_dev, data, devn, sublocksize);1822			break;1823		default:1824			break;1825		}1826		/*1827		 * In case of sub-block error, break the loop for the rest of1828		 * devices.1829		 */1830		if (ret < 0)1831			break;1832	}1833 1834	return ret;1835}1836 1837static void pcmdevice_select_cfg_blk(void *ctxt, int conf_no,1838	unsigned char block_type)1839{1840	struct pcmdevice_priv *pcm_dev = (struct pcmdevice_priv *)ctxt;1841	struct pcmdevice_regbin *regbin = &(pcm_dev->regbin);1842	struct pcmdevice_config_info **cfg_info = regbin->cfg_info;1843	struct pcmdevice_block_data **blk_data;1844	int j, k;1845 1846	if (conf_no >= regbin->ncfgs || conf_no < 0 || NULL == cfg_info) {1847		dev_err(pcm_dev->dev, "%s: conf_no should be less than %u\n",1848			__func__, regbin->ncfgs);1849		goto out;1850	}1851	blk_data = cfg_info[conf_no]->blk_data;1852 1853	for (j = 0; j < (int)cfg_info[conf_no]->real_nblocks; j++) {1854		unsigned int length = 0, ret;1855 1856		if (block_type > 5 || block_type < 2) {1857			dev_err(pcm_dev->dev,1858				"%s: block_type should be out of range\n",1859				__func__);1860			goto out;1861		}1862		if (block_type != blk_data[j]->block_type)1863			continue;1864 1865		for (k = 0; k < (int)blk_data[j]->n_subblks; k++) {1866			ret = pcmdevice_process_block(pcm_dev,1867				blk_data[j]->regdata + length,1868				blk_data[j]->dev_idx,1869				blk_data[j]->block_size - length);1870			length += ret;1871			if (blk_data[j]->block_size < length) {1872				dev_err(pcm_dev->dev,1873					"%s: %u %u out of boundary\n",1874					__func__, length,1875					blk_data[j]->block_size);1876				break;1877			}1878		}1879		if (length != blk_data[j]->block_size)1880			dev_err(pcm_dev->dev, "%s: %u %u size is not same\n",1881				__func__, length, blk_data[j]->block_size);1882	}1883 1884out:1885	return;1886}1887 1888static int pcmdevice_mute(struct snd_soc_dai *dai, int mute, int stream)1889{1890	struct snd_soc_component *codec = dai->component;1891	struct pcmdevice_priv *pcm_dev = snd_soc_component_get_drvdata(codec);1892	unsigned char block_type;1893 1894	if (pcm_dev->fw_state == PCMDEVICE_FW_LOAD_FAILED) {1895		dev_err(pcm_dev->dev, "%s: bin file not loaded\n", __func__);1896		return -EINVAL;1897	}1898 1899	if (mute)1900		block_type = PCMDEVICE_BIN_BLK_PRE_SHUTDOWN;1901	else1902		block_type = PCMDEVICE_BIN_BLK_PRE_POWER_UP;1903 1904	mutex_lock(&pcm_dev->codec_lock);1905	pcmdevice_select_cfg_blk(pcm_dev, pcm_dev->cur_conf, block_type);1906	mutex_unlock(&pcm_dev->codec_lock);1907	return 0;1908}1909 1910static int pcmdevice_hw_params(struct snd_pcm_substream *substream,1911	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)1912{1913	struct pcmdevice_priv *pcm_dev = snd_soc_dai_get_drvdata(dai);1914	unsigned int fsrate;1915	unsigned int slot_width;1916	int bclk_rate;1917	int ret = 0;1918 1919	fsrate = params_rate(params);1920	switch (fsrate) {1921	case 48000:1922		break;1923	case 44100:1924		break;1925	default:1926		dev_err(pcm_dev->dev, "%s: incorrect sample rate = %u\n",1927			__func__, fsrate);1928		ret = -EINVAL;1929		goto out;1930	}1931 1932	slot_width = params_width(params);1933	switch (slot_width) {1934	case 16:1935		break;1936	case 20:1937		break;1938	case 24:1939		break;1940	case 32:1941		break;1942	default:1943		dev_err(pcm_dev->dev, "%s: incorrect slot width = %u\n",1944			__func__, slot_width);1945		ret = -EINVAL;1946		goto out;1947	}1948 1949	bclk_rate = snd_soc_params_to_bclk(params);1950	if (bclk_rate < 0) {1951		dev_err(pcm_dev->dev, "%s: incorrect bclk rate = %d\n",1952			__func__, bclk_rate);1953		ret = bclk_rate;1954	}1955 1956out:1957	return ret;1958}1959 1960static const struct snd_soc_dai_ops pcmdevice_dai_ops = {1961	.mute_stream = pcmdevice_mute,1962	.hw_params = pcmdevice_hw_params,1963};1964 1965static struct snd_soc_dai_driver pcmdevice_dai_driver[] = {1966	{1967		.name = "pcmdevice-codec",1968		.capture = {1969			.stream_name	 = "Capture",1970			.channels_min	 = 2,1971			.channels_max	 = PCMDEVICE_MAX_CHANNELS,1972			.rates		 = PCMDEVICE_RATES,1973			.formats	 = PCMDEVICE_FORMATS,1974		},1975		.playback = {1976			.stream_name	 = "Playback",1977			.channels_min	 = 2,1978			.channels_max	 = PCMDEVICE_MAX_CHANNELS,1979			.rates		 = PCMDEVICE_RATES,1980			.formats	 = PCMDEVICE_FORMATS,1981		},1982		.ops = &pcmdevice_dai_ops,1983		.symmetric_rate = 1,1984	}1985};1986 1987#ifdef CONFIG_OF1988static const struct of_device_id pcmdevice_of_match[] = {1989	{ .compatible = "ti,adc3120"  },1990	{ .compatible = "ti,adc5120"  },1991	{ .compatible = "ti,adc6120"  },1992	{ .compatible = "ti,dix4192"  },1993	{ .compatible = "ti,pcm1690"  },1994	{ .compatible = "ti,pcm3120"  },1995	{ .compatible = "ti,pcm3140"  },1996	{ .compatible = "ti,pcm5120"  },1997	{ .compatible = "ti,pcm5140"  },1998	{ .compatible = "ti,pcm6120"  },1999	{ .compatible = "ti,pcm6140"  },2000	{ .compatible = "ti,pcm6240"  },2001	{ .compatible = "ti,pcm6260"  },2002	{ .compatible = "ti,pcm9211"  },2003	{ .compatible = "ti,pcmd3140" },2004	{ .compatible = "ti,pcmd3180" },2005	{ .compatible = "ti,pcmd512x" },2006	{ .compatible = "ti,taa5212"  },2007	{ .compatible = "ti,taa5412"  },2008	{ .compatible = "ti,tad5212"  },2009	{ .compatible = "ti,tad5412"  },2010	{},2011};2012MODULE_DEVICE_TABLE(of, pcmdevice_of_match);2013#endif2014 2015static const struct regmap_range_cfg pcmdevice_ranges[] = {2016	{2017		.range_min = 0,2018		.range_max = 256 * 128,2019		.selector_reg = PCMDEVICE_PAGE_SELECT,2020		.selector_mask = 0xff,2021		.selector_shift = 0,2022		.window_start = 0,2023		.window_len = 128,2024	},2025};2026 2027static const struct regmap_config pcmdevice_i2c_regmap = {2028	.reg_bits = 8,2029	.val_bits = 8,2030	.cache_type = REGCACHE_MAPLE,2031	.ranges = pcmdevice_ranges,2032	.num_ranges = ARRAY_SIZE(pcmdevice_ranges),2033	.max_register = 256 * 128,2034};2035 2036static void pcmdevice_remove(struct pcmdevice_priv *pcm_dev)2037{2038	if (gpio_is_valid(pcm_dev->irq_info.gpio)) {2039		gpio_free(pcm_dev->irq_info.gpio);2040		free_irq(pcm_dev->irq_info.nmb, pcm_dev);2041	}2042	mutex_destroy(&pcm_dev->codec_lock);2043}2044 2045static char *str_to_upper(char *str)2046{2047	char *orig = str;2048 2049	if (!str)2050		return NULL;2051 2052	while (*str) {2053		*str = toupper(*str);2054		str++;2055	}2056 2057	return orig;2058}2059 2060static int pcmdevice_i2c_probe(struct i2c_client *i2c)2061{2062	const struct i2c_device_id *id = i2c_match_id(pcmdevice_i2c_id, i2c);2063	struct pcmdevice_priv *pcm_dev;2064	struct device_node *np;2065	unsigned int dev_addrs[PCMDEVICE_MAX_I2C_DEVICES];2066	int ret = 0, i = 0, ndev = 0;2067 2068	pcm_dev = devm_kzalloc(&i2c->dev, sizeof(*pcm_dev), GFP_KERNEL);2069	if (!pcm_dev)2070		return -ENOMEM;2071 2072	pcm_dev->chip_id = (id != NULL) ? id->driver_data : 0;2073 2074	pcm_dev->dev = &i2c->dev;2075	pcm_dev->client = i2c;2076 2077	if (pcm_dev->chip_id >= MAX_DEVICE)2078		pcm_dev->chip_id = 0;2079 2080	strscpy(pcm_dev->dev_name, pcmdevice_i2c_id[pcm_dev->chip_id].name,2081		sizeof(pcm_dev->dev_name));2082 2083	strscpy(pcm_dev->upper_dev_name,2084		pcmdevice_i2c_id[pcm_dev->chip_id].name,2085		sizeof(pcm_dev->upper_dev_name));2086 2087	str_to_upper(pcm_dev->upper_dev_name);2088 2089	pcm_dev->regmap = devm_regmap_init_i2c(i2c, &pcmdevice_i2c_regmap);2090	if (IS_ERR(pcm_dev->regmap)) {2091		ret = PTR_ERR(pcm_dev->regmap);2092		dev_err(&i2c->dev, "%s: failed to allocate register map: %d\n",2093			__func__, ret);2094		goto out;2095	}2096 2097	i2c_set_clientdata(i2c, pcm_dev);2098	mutex_init(&pcm_dev->codec_lock);2099	np = pcm_dev->dev->of_node;2100 2101	if (IS_ENABLED(CONFIG_OF)) {2102		u64 addr;2103 2104		for (i = 0; i < PCMDEVICE_MAX_I2C_DEVICES; i++) {2105			if (of_property_read_reg(np, i, &addr, NULL))2106				break;2107			dev_addrs[ndev++] = addr;2108		}2109	} else {2110		ndev = 1;2111		dev_addrs[0] = i2c->addr;2112	}2113	pcm_dev->irq_info.gpio = of_irq_get(np, 0);2114 2115	for (i = 0; i < ndev; i++)2116		pcm_dev->addr[i] = dev_addrs[i];2117 2118	pcm_dev->ndev = ndev;2119 2120	pcm_dev->hw_rst = devm_gpiod_get_optional(&i2c->dev,2121			"reset-gpios", GPIOD_OUT_HIGH);2122	/* No reset GPIO, no side-effect */2123	if (IS_ERR(pcm_dev->hw_rst)) {2124		if (pcm_dev->chip_id == PCM9211 || pcm_dev->chip_id == PCM1690)2125			pcm9211_sw_rst(pcm_dev);2126		else2127			pcmdevice_sw_rst(pcm_dev);2128	} else {2129		gpiod_set_value_cansleep(pcm_dev->hw_rst, 0);2130		usleep_range(500, 1000);2131		gpiod_set_value_cansleep(pcm_dev->hw_rst, 1);2132	}2133 2134	if (pcm_dev->chip_id == PCM1690)2135		goto skip_interrupt;2136	if (gpio_is_valid(pcm_dev->irq_info.gpio)) {2137		dev_dbg(pcm_dev->dev, "irq-gpio = %d", pcm_dev->irq_info.gpio);2138 2139		ret = gpio_request(pcm_dev->irq_info.gpio, "PCMDEV-IRQ");2140		if (!ret) {2141			int gpio = pcm_dev->irq_info.gpio;2142 2143			gpio_direction_input(gpio);2144			pcm_dev->irq_info.nmb = gpio_to_irq(gpio);2145 2146		} else2147			dev_err(pcm_dev->dev, "%s: GPIO %d request error\n",2148				__func__, pcm_dev->irq_info.gpio);2149	} else2150		dev_err(pcm_dev->dev, "Looking up irq-gpio failed %d\n",2151			pcm_dev->irq_info.gpio);2152 2153skip_interrupt:2154	ret = devm_snd_soc_register_component(&i2c->dev,2155		&soc_codec_driver_pcmdevice, pcmdevice_dai_driver,2156		ARRAY_SIZE(pcmdevice_dai_driver));2157	if (ret < 0)2158		dev_err(&i2c->dev, "probe register comp failed %d\n", ret);2159 2160out:2161	if (ret < 0)2162		pcmdevice_remove(pcm_dev);2163	return ret;2164}2165 2166static void pcmdevice_i2c_remove(struct i2c_client *i2c)2167{2168	struct pcmdevice_priv *pcm_dev = i2c_get_clientdata(i2c);2169 2170	pcmdevice_remove(pcm_dev);2171}2172 2173static struct i2c_driver pcmdevice_i2c_driver = {2174	.driver = {2175		.name = "pcmdevice-codec",2176		.of_match_table = of_match_ptr(pcmdevice_of_match),2177	},2178	.probe	= pcmdevice_i2c_probe,2179	.remove = pcmdevice_i2c_remove,2180	.id_table = pcmdevice_i2c_id,2181};2182module_i2c_driver(pcmdevice_i2c_driver);2183 2184MODULE_AUTHOR("Shenghao Ding <shenghao-ding@ti.com>");2185MODULE_DESCRIPTION("ASoC PCM6240 Family Audio ADC/DAC Driver");2186MODULE_LICENSE("GPL");2187