162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// Driver for the Texas Instruments TAS2562 CODEC 462306a36Sopenharmony_ci// Copyright (C) 2019 Texas Instruments Inc. 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/module.h> 862306a36Sopenharmony_ci#include <linux/errno.h> 962306a36Sopenharmony_ci#include <linux/device.h> 1062306a36Sopenharmony_ci#include <linux/i2c.h> 1162306a36Sopenharmony_ci#include <linux/regmap.h> 1262306a36Sopenharmony_ci#include <linux/slab.h> 1362306a36Sopenharmony_ci#include <linux/gpio/consumer.h> 1462306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 1562306a36Sopenharmony_ci#include <linux/delay.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <sound/pcm.h> 1862306a36Sopenharmony_ci#include <sound/pcm_params.h> 1962306a36Sopenharmony_ci#include <sound/soc.h> 2062306a36Sopenharmony_ci#include <sound/soc-dapm.h> 2162306a36Sopenharmony_ci#include <sound/tlv.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include "tas2562.h" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#define TAS2562_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\ 2662306a36Sopenharmony_ci SNDRV_PCM_FORMAT_S32_LE) 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci/* DVC equation involves floating point math 2962306a36Sopenharmony_ci * round(10^(volume in dB/20)*2^30) 3062306a36Sopenharmony_ci * so create a lookup table for 2dB step 3162306a36Sopenharmony_ci */ 3262306a36Sopenharmony_cistatic const unsigned int float_vol_db_lookup[] = { 3362306a36Sopenharmony_ci0x00000d43, 0x000010b2, 0x00001505, 0x00001a67, 0x00002151, 3462306a36Sopenharmony_ci0x000029f1, 0x000034cd, 0x00004279, 0x000053af, 0x0000695b, 3562306a36Sopenharmony_ci0x0000695b, 0x0000a6fa, 0x0000d236, 0x000108a4, 0x00014d2a, 3662306a36Sopenharmony_ci0x0001a36e, 0x00021008, 0x000298c0, 0x000344df, 0x00041d8f, 3762306a36Sopenharmony_ci0x00052e5a, 0x000685c8, 0x00083621, 0x000a566d, 0x000d03a7, 3862306a36Sopenharmony_ci0x0010624d, 0x0014a050, 0x0019f786, 0x0020b0bc, 0x0029279d, 3962306a36Sopenharmony_ci0x0033cf8d, 0x004139d3, 0x00521d50, 0x00676044, 0x0082248a, 4062306a36Sopenharmony_ci0x00a3d70a, 0x00ce4328, 0x0103ab3d, 0x0146e75d, 0x019b8c27, 4162306a36Sopenharmony_ci0x02061b89, 0x028c423f, 0x03352529, 0x0409c2b0, 0x05156d68, 4262306a36Sopenharmony_ci0x080e9f96, 0x0a24b062, 0x0cc509ab, 0x10137987, 0x143d1362, 4362306a36Sopenharmony_ci0x197a967f, 0x2013739e, 0x28619ae9, 0x32d64617, 0x40000000 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistruct tas2562_data { 4762306a36Sopenharmony_ci struct snd_soc_component *component; 4862306a36Sopenharmony_ci struct gpio_desc *sdz_gpio; 4962306a36Sopenharmony_ci struct regmap *regmap; 5062306a36Sopenharmony_ci struct device *dev; 5162306a36Sopenharmony_ci struct i2c_client *client; 5262306a36Sopenharmony_ci int v_sense_slot; 5362306a36Sopenharmony_ci int i_sense_slot; 5462306a36Sopenharmony_ci int volume_lvl; 5562306a36Sopenharmony_ci int model_id; 5662306a36Sopenharmony_ci bool dac_powered; 5762306a36Sopenharmony_ci bool unmuted; 5862306a36Sopenharmony_ci}; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cienum tas256x_model { 6162306a36Sopenharmony_ci TAS2562, 6262306a36Sopenharmony_ci TAS2563, 6362306a36Sopenharmony_ci TAS2564, 6462306a36Sopenharmony_ci TAS2110, 6562306a36Sopenharmony_ci}; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic int tas2562_set_samplerate(struct tas2562_data *tas2562, int samplerate) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci int samp_rate; 7062306a36Sopenharmony_ci int ramp_rate; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci switch (samplerate) { 7362306a36Sopenharmony_ci case 7350: 7462306a36Sopenharmony_ci ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1; 7562306a36Sopenharmony_ci samp_rate = TAS2562_TDM_CFG0_SAMPRATE_7305_8KHZ; 7662306a36Sopenharmony_ci break; 7762306a36Sopenharmony_ci case 8000: 7862306a36Sopenharmony_ci ramp_rate = 0; 7962306a36Sopenharmony_ci samp_rate = TAS2562_TDM_CFG0_SAMPRATE_7305_8KHZ; 8062306a36Sopenharmony_ci break; 8162306a36Sopenharmony_ci case 14700: 8262306a36Sopenharmony_ci ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1; 8362306a36Sopenharmony_ci samp_rate = TAS2562_TDM_CFG0_SAMPRATE_14_7_16KHZ; 8462306a36Sopenharmony_ci break; 8562306a36Sopenharmony_ci case 16000: 8662306a36Sopenharmony_ci ramp_rate = 0; 8762306a36Sopenharmony_ci samp_rate = TAS2562_TDM_CFG0_SAMPRATE_14_7_16KHZ; 8862306a36Sopenharmony_ci break; 8962306a36Sopenharmony_ci case 22050: 9062306a36Sopenharmony_ci ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1; 9162306a36Sopenharmony_ci samp_rate = TAS2562_TDM_CFG0_SAMPRATE_22_05_24KHZ; 9262306a36Sopenharmony_ci break; 9362306a36Sopenharmony_ci case 24000: 9462306a36Sopenharmony_ci ramp_rate = 0; 9562306a36Sopenharmony_ci samp_rate = TAS2562_TDM_CFG0_SAMPRATE_22_05_24KHZ; 9662306a36Sopenharmony_ci break; 9762306a36Sopenharmony_ci case 29400: 9862306a36Sopenharmony_ci ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1; 9962306a36Sopenharmony_ci samp_rate = TAS2562_TDM_CFG0_SAMPRATE_29_4_32KHZ; 10062306a36Sopenharmony_ci break; 10162306a36Sopenharmony_ci case 32000: 10262306a36Sopenharmony_ci ramp_rate = 0; 10362306a36Sopenharmony_ci samp_rate = TAS2562_TDM_CFG0_SAMPRATE_29_4_32KHZ; 10462306a36Sopenharmony_ci break; 10562306a36Sopenharmony_ci case 44100: 10662306a36Sopenharmony_ci ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1; 10762306a36Sopenharmony_ci samp_rate = TAS2562_TDM_CFG0_SAMPRATE_44_1_48KHZ; 10862306a36Sopenharmony_ci break; 10962306a36Sopenharmony_ci case 48000: 11062306a36Sopenharmony_ci ramp_rate = 0; 11162306a36Sopenharmony_ci samp_rate = TAS2562_TDM_CFG0_SAMPRATE_44_1_48KHZ; 11262306a36Sopenharmony_ci break; 11362306a36Sopenharmony_ci case 88200: 11462306a36Sopenharmony_ci ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1; 11562306a36Sopenharmony_ci samp_rate = TAS2562_TDM_CFG0_SAMPRATE_88_2_96KHZ; 11662306a36Sopenharmony_ci break; 11762306a36Sopenharmony_ci case 96000: 11862306a36Sopenharmony_ci ramp_rate = 0; 11962306a36Sopenharmony_ci samp_rate = TAS2562_TDM_CFG0_SAMPRATE_88_2_96KHZ; 12062306a36Sopenharmony_ci break; 12162306a36Sopenharmony_ci case 176400: 12262306a36Sopenharmony_ci ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1; 12362306a36Sopenharmony_ci samp_rate = TAS2562_TDM_CFG0_SAMPRATE_176_4_192KHZ; 12462306a36Sopenharmony_ci break; 12562306a36Sopenharmony_ci case 192000: 12662306a36Sopenharmony_ci ramp_rate = 0; 12762306a36Sopenharmony_ci samp_rate = TAS2562_TDM_CFG0_SAMPRATE_176_4_192KHZ; 12862306a36Sopenharmony_ci break; 12962306a36Sopenharmony_ci default: 13062306a36Sopenharmony_ci dev_info(tas2562->dev, "%s, unsupported sample rate, %d\n", 13162306a36Sopenharmony_ci __func__, samplerate); 13262306a36Sopenharmony_ci return -EINVAL; 13362306a36Sopenharmony_ci } 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG0, 13662306a36Sopenharmony_ci TAS2562_TDM_CFG0_RAMPRATE_MASK, ramp_rate); 13762306a36Sopenharmony_ci snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG0, 13862306a36Sopenharmony_ci TAS2562_TDM_CFG0_SAMPRATE_MASK, samp_rate); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci return 0; 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistatic int tas2562_set_dai_tdm_slot(struct snd_soc_dai *dai, 14462306a36Sopenharmony_ci unsigned int tx_mask, unsigned int rx_mask, 14562306a36Sopenharmony_ci int slots, int slot_width) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 14862306a36Sopenharmony_ci struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); 14962306a36Sopenharmony_ci int left_slot, right_slot; 15062306a36Sopenharmony_ci int slots_cfg; 15162306a36Sopenharmony_ci int ret; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci if (!tx_mask) { 15462306a36Sopenharmony_ci dev_err(component->dev, "tx masks must not be 0\n"); 15562306a36Sopenharmony_ci return -EINVAL; 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci if (slots == 1) { 15962306a36Sopenharmony_ci if (tx_mask != 1) 16062306a36Sopenharmony_ci return -EINVAL; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci left_slot = 0; 16362306a36Sopenharmony_ci right_slot = 0; 16462306a36Sopenharmony_ci } else { 16562306a36Sopenharmony_ci left_slot = __ffs(tx_mask); 16662306a36Sopenharmony_ci tx_mask &= ~(1 << left_slot); 16762306a36Sopenharmony_ci if (tx_mask == 0) { 16862306a36Sopenharmony_ci right_slot = left_slot; 16962306a36Sopenharmony_ci } else { 17062306a36Sopenharmony_ci right_slot = __ffs(tx_mask); 17162306a36Sopenharmony_ci } 17262306a36Sopenharmony_ci } 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci slots_cfg = (right_slot << TAS2562_RIGHT_SLOT_SHIFT) | left_slot; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci ret = snd_soc_component_write(component, TAS2562_TDM_CFG3, slots_cfg); 17762306a36Sopenharmony_ci if (ret < 0) 17862306a36Sopenharmony_ci return ret; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci switch (slot_width) { 18162306a36Sopenharmony_ci case 16: 18262306a36Sopenharmony_ci ret = snd_soc_component_update_bits(component, 18362306a36Sopenharmony_ci TAS2562_TDM_CFG2, 18462306a36Sopenharmony_ci TAS2562_TDM_CFG2_RXLEN_MASK, 18562306a36Sopenharmony_ci TAS2562_TDM_CFG2_RXLEN_16B); 18662306a36Sopenharmony_ci break; 18762306a36Sopenharmony_ci case 24: 18862306a36Sopenharmony_ci ret = snd_soc_component_update_bits(component, 18962306a36Sopenharmony_ci TAS2562_TDM_CFG2, 19062306a36Sopenharmony_ci TAS2562_TDM_CFG2_RXLEN_MASK, 19162306a36Sopenharmony_ci TAS2562_TDM_CFG2_RXLEN_24B); 19262306a36Sopenharmony_ci break; 19362306a36Sopenharmony_ci case 32: 19462306a36Sopenharmony_ci ret = snd_soc_component_update_bits(component, 19562306a36Sopenharmony_ci TAS2562_TDM_CFG2, 19662306a36Sopenharmony_ci TAS2562_TDM_CFG2_RXLEN_MASK, 19762306a36Sopenharmony_ci TAS2562_TDM_CFG2_RXLEN_32B); 19862306a36Sopenharmony_ci break; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci case 0: 20162306a36Sopenharmony_ci /* Do not change slot width */ 20262306a36Sopenharmony_ci break; 20362306a36Sopenharmony_ci default: 20462306a36Sopenharmony_ci dev_err(tas2562->dev, "slot width not supported"); 20562306a36Sopenharmony_ci ret = -EINVAL; 20662306a36Sopenharmony_ci } 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci if (ret < 0) 20962306a36Sopenharmony_ci return ret; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG5, 21262306a36Sopenharmony_ci TAS2562_TDM_CFG5_VSNS_SLOT_MASK, 21362306a36Sopenharmony_ci tas2562->v_sense_slot); 21462306a36Sopenharmony_ci if (ret < 0) 21562306a36Sopenharmony_ci return ret; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG6, 21862306a36Sopenharmony_ci TAS2562_TDM_CFG6_ISNS_SLOT_MASK, 21962306a36Sopenharmony_ci tas2562->i_sense_slot); 22062306a36Sopenharmony_ci if (ret < 0) 22162306a36Sopenharmony_ci return ret; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci return 0; 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistatic int tas2562_set_bitwidth(struct tas2562_data *tas2562, int bitwidth) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci int ret; 22962306a36Sopenharmony_ci int val; 23062306a36Sopenharmony_ci int sense_en; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci switch (bitwidth) { 23362306a36Sopenharmony_ci case SNDRV_PCM_FORMAT_S16_LE: 23462306a36Sopenharmony_ci snd_soc_component_update_bits(tas2562->component, 23562306a36Sopenharmony_ci TAS2562_TDM_CFG2, 23662306a36Sopenharmony_ci TAS2562_TDM_CFG2_RXWLEN_MASK, 23762306a36Sopenharmony_ci TAS2562_TDM_CFG2_RXWLEN_16B); 23862306a36Sopenharmony_ci break; 23962306a36Sopenharmony_ci case SNDRV_PCM_FORMAT_S24_LE: 24062306a36Sopenharmony_ci snd_soc_component_update_bits(tas2562->component, 24162306a36Sopenharmony_ci TAS2562_TDM_CFG2, 24262306a36Sopenharmony_ci TAS2562_TDM_CFG2_RXWLEN_MASK, 24362306a36Sopenharmony_ci TAS2562_TDM_CFG2_RXWLEN_24B); 24462306a36Sopenharmony_ci break; 24562306a36Sopenharmony_ci case SNDRV_PCM_FORMAT_S32_LE: 24662306a36Sopenharmony_ci snd_soc_component_update_bits(tas2562->component, 24762306a36Sopenharmony_ci TAS2562_TDM_CFG2, 24862306a36Sopenharmony_ci TAS2562_TDM_CFG2_RXWLEN_MASK, 24962306a36Sopenharmony_ci TAS2562_TDM_CFG2_RXWLEN_32B); 25062306a36Sopenharmony_ci break; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci default: 25362306a36Sopenharmony_ci dev_info(tas2562->dev, "Unsupported bitwidth format\n"); 25462306a36Sopenharmony_ci return -EINVAL; 25562306a36Sopenharmony_ci } 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci val = snd_soc_component_read(tas2562->component, TAS2562_PWR_CTRL); 25862306a36Sopenharmony_ci if (val < 0) 25962306a36Sopenharmony_ci return val; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci if (val & (1 << TAS2562_VSENSE_POWER_EN)) 26262306a36Sopenharmony_ci sense_en = 0; 26362306a36Sopenharmony_ci else 26462306a36Sopenharmony_ci sense_en = TAS2562_TDM_CFG5_VSNS_EN; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci ret = snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG5, 26762306a36Sopenharmony_ci TAS2562_TDM_CFG5_VSNS_EN, sense_en); 26862306a36Sopenharmony_ci if (ret < 0) 26962306a36Sopenharmony_ci return ret; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci if (val & (1 << TAS2562_ISENSE_POWER_EN)) 27262306a36Sopenharmony_ci sense_en = 0; 27362306a36Sopenharmony_ci else 27462306a36Sopenharmony_ci sense_en = TAS2562_TDM_CFG6_ISNS_EN; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci ret = snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG6, 27762306a36Sopenharmony_ci TAS2562_TDM_CFG6_ISNS_EN, sense_en); 27862306a36Sopenharmony_ci if (ret < 0) 27962306a36Sopenharmony_ci return ret; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci return 0; 28262306a36Sopenharmony_ci} 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_cistatic int tas2562_hw_params(struct snd_pcm_substream *substream, 28562306a36Sopenharmony_ci struct snd_pcm_hw_params *params, 28662306a36Sopenharmony_ci struct snd_soc_dai *dai) 28762306a36Sopenharmony_ci{ 28862306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 28962306a36Sopenharmony_ci struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); 29062306a36Sopenharmony_ci int ret; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci ret = tas2562_set_bitwidth(tas2562, params_format(params)); 29362306a36Sopenharmony_ci if (ret) { 29462306a36Sopenharmony_ci dev_err(tas2562->dev, "set bitwidth failed, %d\n", ret); 29562306a36Sopenharmony_ci return ret; 29662306a36Sopenharmony_ci } 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci ret = tas2562_set_samplerate(tas2562, params_rate(params)); 29962306a36Sopenharmony_ci if (ret) 30062306a36Sopenharmony_ci dev_err(tas2562->dev, "set sample rate failed, %d\n", ret); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci return ret; 30362306a36Sopenharmony_ci} 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_cistatic int tas2562_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 30662306a36Sopenharmony_ci{ 30762306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 30862306a36Sopenharmony_ci struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); 30962306a36Sopenharmony_ci u8 asi_cfg_1 = 0; 31062306a36Sopenharmony_ci u8 tdm_rx_start_slot = 0; 31162306a36Sopenharmony_ci int ret; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 31462306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_NF: 31562306a36Sopenharmony_ci asi_cfg_1 = 0; 31662306a36Sopenharmony_ci break; 31762306a36Sopenharmony_ci case SND_SOC_DAIFMT_IB_NF: 31862306a36Sopenharmony_ci asi_cfg_1 |= TAS2562_TDM_CFG1_RX_FALLING; 31962306a36Sopenharmony_ci break; 32062306a36Sopenharmony_ci default: 32162306a36Sopenharmony_ci dev_err(tas2562->dev, "ASI format Inverse is not found\n"); 32262306a36Sopenharmony_ci return -EINVAL; 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG1, 32662306a36Sopenharmony_ci TAS2562_TDM_CFG1_RX_EDGE_MASK, 32762306a36Sopenharmony_ci asi_cfg_1); 32862306a36Sopenharmony_ci if (ret < 0) { 32962306a36Sopenharmony_ci dev_err(tas2562->dev, "Failed to set RX edge\n"); 33062306a36Sopenharmony_ci return ret; 33162306a36Sopenharmony_ci } 33262306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 33362306a36Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 33462306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_B: 33562306a36Sopenharmony_ci tdm_rx_start_slot = 0; 33662306a36Sopenharmony_ci break; 33762306a36Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 33862306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_A: 33962306a36Sopenharmony_ci tdm_rx_start_slot = 1; 34062306a36Sopenharmony_ci break; 34162306a36Sopenharmony_ci default: 34262306a36Sopenharmony_ci dev_err(tas2562->dev, 34362306a36Sopenharmony_ci "DAI Format is not found, fmt=0x%x\n", fmt); 34462306a36Sopenharmony_ci return -EINVAL; 34562306a36Sopenharmony_ci } 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG1, 34862306a36Sopenharmony_ci TAS2562_RX_OFF_MASK, (tdm_rx_start_slot << 1)); 34962306a36Sopenharmony_ci if (ret < 0) 35062306a36Sopenharmony_ci return ret; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci return 0; 35362306a36Sopenharmony_ci} 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cistatic int tas2562_update_pwr_ctrl(struct tas2562_data *tas2562) 35662306a36Sopenharmony_ci{ 35762306a36Sopenharmony_ci struct snd_soc_component *component = tas2562->component; 35862306a36Sopenharmony_ci unsigned int val; 35962306a36Sopenharmony_ci int ret; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci if (tas2562->dac_powered) 36262306a36Sopenharmony_ci val = tas2562->unmuted ? 36362306a36Sopenharmony_ci TAS2562_ACTIVE : TAS2562_MUTE; 36462306a36Sopenharmony_ci else 36562306a36Sopenharmony_ci val = TAS2562_SHUTDOWN; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci ret = snd_soc_component_update_bits(component, TAS2562_PWR_CTRL, 36862306a36Sopenharmony_ci TAS2562_MODE_MASK, val); 36962306a36Sopenharmony_ci if (ret < 0) 37062306a36Sopenharmony_ci return ret; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci return 0; 37362306a36Sopenharmony_ci} 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_cistatic int tas2562_mute(struct snd_soc_dai *dai, int mute, int direction) 37662306a36Sopenharmony_ci{ 37762306a36Sopenharmony_ci struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(dai->component); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci tas2562->unmuted = !mute; 38062306a36Sopenharmony_ci return tas2562_update_pwr_ctrl(tas2562); 38162306a36Sopenharmony_ci} 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_cistatic int tas2562_codec_probe(struct snd_soc_component *component) 38462306a36Sopenharmony_ci{ 38562306a36Sopenharmony_ci struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci tas2562->component = component; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci if (tas2562->sdz_gpio) 39062306a36Sopenharmony_ci gpiod_set_value_cansleep(tas2562->sdz_gpio, 1); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci return 0; 39362306a36Sopenharmony_ci} 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci#ifdef CONFIG_PM 39662306a36Sopenharmony_cistatic int tas2562_suspend(struct snd_soc_component *component) 39762306a36Sopenharmony_ci{ 39862306a36Sopenharmony_ci struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci regcache_cache_only(tas2562->regmap, true); 40162306a36Sopenharmony_ci regcache_mark_dirty(tas2562->regmap); 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci if (tas2562->sdz_gpio) 40462306a36Sopenharmony_ci gpiod_set_value_cansleep(tas2562->sdz_gpio, 0); 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci return 0; 40762306a36Sopenharmony_ci} 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_cistatic int tas2562_resume(struct snd_soc_component *component) 41062306a36Sopenharmony_ci{ 41162306a36Sopenharmony_ci struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci if (tas2562->sdz_gpio) 41462306a36Sopenharmony_ci gpiod_set_value_cansleep(tas2562->sdz_gpio, 1); 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci regcache_cache_only(tas2562->regmap, false); 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci return regcache_sync(tas2562->regmap); 41962306a36Sopenharmony_ci} 42062306a36Sopenharmony_ci#else 42162306a36Sopenharmony_ci#define tas2562_suspend NULL 42262306a36Sopenharmony_ci#define tas2562_resume NULL 42362306a36Sopenharmony_ci#endif 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_cistatic const char * const tas2562_ASI1_src[] = { 42662306a36Sopenharmony_ci "I2C offset", "Left", "Right", "LeftRightDiv2", 42762306a36Sopenharmony_ci}; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(tas2562_ASI1_src_enum, TAS2562_TDM_CFG2, 4, 43062306a36Sopenharmony_ci tas2562_ASI1_src); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_cistatic const struct snd_kcontrol_new tas2562_asi1_mux = 43362306a36Sopenharmony_ci SOC_DAPM_ENUM("ASI1 Source", tas2562_ASI1_src_enum); 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_cistatic int tas2562_dac_event(struct snd_soc_dapm_widget *w, 43662306a36Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 43762306a36Sopenharmony_ci{ 43862306a36Sopenharmony_ci struct snd_soc_component *component = 43962306a36Sopenharmony_ci snd_soc_dapm_to_component(w->dapm); 44062306a36Sopenharmony_ci struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); 44162306a36Sopenharmony_ci int ret = 0; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci switch (event) { 44462306a36Sopenharmony_ci case SND_SOC_DAPM_POST_PMU: 44562306a36Sopenharmony_ci tas2562->dac_powered = true; 44662306a36Sopenharmony_ci ret = tas2562_update_pwr_ctrl(tas2562); 44762306a36Sopenharmony_ci break; 44862306a36Sopenharmony_ci case SND_SOC_DAPM_PRE_PMD: 44962306a36Sopenharmony_ci tas2562->dac_powered = false; 45062306a36Sopenharmony_ci ret = tas2562_update_pwr_ctrl(tas2562); 45162306a36Sopenharmony_ci break; 45262306a36Sopenharmony_ci default: 45362306a36Sopenharmony_ci dev_err(tas2562->dev, "Not supported evevt\n"); 45462306a36Sopenharmony_ci return -EINVAL; 45562306a36Sopenharmony_ci } 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci return ret; 45862306a36Sopenharmony_ci} 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_cistatic int tas2562_volume_control_get(struct snd_kcontrol *kcontrol, 46162306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 46262306a36Sopenharmony_ci{ 46362306a36Sopenharmony_ci struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 46462306a36Sopenharmony_ci struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci ucontrol->value.integer.value[0] = tas2562->volume_lvl; 46762306a36Sopenharmony_ci return 0; 46862306a36Sopenharmony_ci} 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_cistatic int tas2562_volume_control_put(struct snd_kcontrol *kcontrol, 47162306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 47262306a36Sopenharmony_ci{ 47362306a36Sopenharmony_ci struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 47462306a36Sopenharmony_ci struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); 47562306a36Sopenharmony_ci int ret; 47662306a36Sopenharmony_ci u32 reg_val; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci reg_val = float_vol_db_lookup[ucontrol->value.integer.value[0]/2]; 47962306a36Sopenharmony_ci ret = snd_soc_component_write(component, TAS2562_DVC_CFG4, 48062306a36Sopenharmony_ci (reg_val & 0xff)); 48162306a36Sopenharmony_ci if (ret) 48262306a36Sopenharmony_ci return ret; 48362306a36Sopenharmony_ci ret = snd_soc_component_write(component, TAS2562_DVC_CFG3, 48462306a36Sopenharmony_ci ((reg_val >> 8) & 0xff)); 48562306a36Sopenharmony_ci if (ret) 48662306a36Sopenharmony_ci return ret; 48762306a36Sopenharmony_ci ret = snd_soc_component_write(component, TAS2562_DVC_CFG2, 48862306a36Sopenharmony_ci ((reg_val >> 16) & 0xff)); 48962306a36Sopenharmony_ci if (ret) 49062306a36Sopenharmony_ci return ret; 49162306a36Sopenharmony_ci ret = snd_soc_component_write(component, TAS2562_DVC_CFG1, 49262306a36Sopenharmony_ci ((reg_val >> 24) & 0xff)); 49362306a36Sopenharmony_ci if (ret) 49462306a36Sopenharmony_ci return ret; 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci tas2562->volume_lvl = ucontrol->value.integer.value[0]; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci return 0; 49962306a36Sopenharmony_ci} 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci/* Digital Volume Control. From 0 dB to -110 dB in 1 dB steps */ 50262306a36Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(dvc_tlv, -11000, 100, 0); 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(tas2562_dac_tlv, 850, 50, 0); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_cistatic const struct snd_kcontrol_new isense_switch = 50762306a36Sopenharmony_ci SOC_DAPM_SINGLE("Switch", TAS2562_PWR_CTRL, TAS2562_ISENSE_POWER_EN, 50862306a36Sopenharmony_ci 1, 1); 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_cistatic const struct snd_kcontrol_new vsense_switch = 51162306a36Sopenharmony_ci SOC_DAPM_SINGLE("Switch", TAS2562_PWR_CTRL, TAS2562_VSENSE_POWER_EN, 51262306a36Sopenharmony_ci 1, 1); 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_cistatic const struct snd_kcontrol_new tas2562_snd_controls[] = { 51562306a36Sopenharmony_ci SOC_SINGLE_TLV("Amp Gain Volume", TAS2562_PB_CFG1, 1, 0x1c, 0, 51662306a36Sopenharmony_ci tas2562_dac_tlv), 51762306a36Sopenharmony_ci { 51862306a36Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 51962306a36Sopenharmony_ci .name = "Digital Volume Control", 52062306a36Sopenharmony_ci .index = 0, 52162306a36Sopenharmony_ci .tlv.p = dvc_tlv, 52262306a36Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE, 52362306a36Sopenharmony_ci .info = snd_soc_info_volsw, 52462306a36Sopenharmony_ci .get = tas2562_volume_control_get, 52562306a36Sopenharmony_ci .put = tas2562_volume_control_put, 52662306a36Sopenharmony_ci .private_value = SOC_SINGLE_VALUE(TAS2562_DVC_CFG1, 0, 110, 0, 0), 52762306a36Sopenharmony_ci }, 52862306a36Sopenharmony_ci}; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget tas2110_dapm_widgets[] = { 53162306a36Sopenharmony_ci SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0), 53262306a36Sopenharmony_ci SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2562_asi1_mux), 53362306a36Sopenharmony_ci SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2562_dac_event, 53462306a36Sopenharmony_ci SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 53562306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("OUT"), 53662306a36Sopenharmony_ci}; 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_cistatic const struct snd_soc_dapm_route tas2110_audio_map[] = { 53962306a36Sopenharmony_ci {"ASI1 Sel", "I2C offset", "ASI1"}, 54062306a36Sopenharmony_ci {"ASI1 Sel", "Left", "ASI1"}, 54162306a36Sopenharmony_ci {"ASI1 Sel", "Right", "ASI1"}, 54262306a36Sopenharmony_ci {"ASI1 Sel", "LeftRightDiv2", "ASI1"}, 54362306a36Sopenharmony_ci { "DAC", NULL, "ASI1 Sel" }, 54462306a36Sopenharmony_ci { "OUT", NULL, "DAC" }, 54562306a36Sopenharmony_ci}; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_cistatic const struct snd_soc_component_driver soc_component_dev_tas2110 = { 54862306a36Sopenharmony_ci .probe = tas2562_codec_probe, 54962306a36Sopenharmony_ci .suspend = tas2562_suspend, 55062306a36Sopenharmony_ci .resume = tas2562_resume, 55162306a36Sopenharmony_ci .controls = tas2562_snd_controls, 55262306a36Sopenharmony_ci .num_controls = ARRAY_SIZE(tas2562_snd_controls), 55362306a36Sopenharmony_ci .dapm_widgets = tas2110_dapm_widgets, 55462306a36Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(tas2110_dapm_widgets), 55562306a36Sopenharmony_ci .dapm_routes = tas2110_audio_map, 55662306a36Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(tas2110_audio_map), 55762306a36Sopenharmony_ci .idle_bias_on = 1, 55862306a36Sopenharmony_ci .use_pmdown_time = 1, 55962306a36Sopenharmony_ci .endianness = 1, 56062306a36Sopenharmony_ci}; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget tas2562_dapm_widgets[] = { 56362306a36Sopenharmony_ci SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0), 56462306a36Sopenharmony_ci SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2562_asi1_mux), 56562306a36Sopenharmony_ci SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2562_dac_event, 56662306a36Sopenharmony_ci SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 56762306a36Sopenharmony_ci SND_SOC_DAPM_SWITCH("ISENSE", TAS2562_PWR_CTRL, 3, 1, &isense_switch), 56862306a36Sopenharmony_ci SND_SOC_DAPM_SWITCH("VSENSE", TAS2562_PWR_CTRL, 2, 1, &vsense_switch), 56962306a36Sopenharmony_ci SND_SOC_DAPM_SIGGEN("VMON"), 57062306a36Sopenharmony_ci SND_SOC_DAPM_SIGGEN("IMON"), 57162306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("OUT"), 57262306a36Sopenharmony_ci}; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_cistatic const struct snd_soc_dapm_route tas2562_audio_map[] = { 57562306a36Sopenharmony_ci {"ASI1 Sel", "I2C offset", "ASI1"}, 57662306a36Sopenharmony_ci {"ASI1 Sel", "Left", "ASI1"}, 57762306a36Sopenharmony_ci {"ASI1 Sel", "Right", "ASI1"}, 57862306a36Sopenharmony_ci {"ASI1 Sel", "LeftRightDiv2", "ASI1"}, 57962306a36Sopenharmony_ci { "DAC", NULL, "ASI1 Sel" }, 58062306a36Sopenharmony_ci { "OUT", NULL, "DAC" }, 58162306a36Sopenharmony_ci {"ISENSE", "Switch", "IMON"}, 58262306a36Sopenharmony_ci {"VSENSE", "Switch", "VMON"}, 58362306a36Sopenharmony_ci}; 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_cistatic const struct snd_soc_component_driver soc_component_dev_tas2562 = { 58662306a36Sopenharmony_ci .probe = tas2562_codec_probe, 58762306a36Sopenharmony_ci .suspend = tas2562_suspend, 58862306a36Sopenharmony_ci .resume = tas2562_resume, 58962306a36Sopenharmony_ci .controls = tas2562_snd_controls, 59062306a36Sopenharmony_ci .num_controls = ARRAY_SIZE(tas2562_snd_controls), 59162306a36Sopenharmony_ci .dapm_widgets = tas2562_dapm_widgets, 59262306a36Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(tas2562_dapm_widgets), 59362306a36Sopenharmony_ci .dapm_routes = tas2562_audio_map, 59462306a36Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(tas2562_audio_map), 59562306a36Sopenharmony_ci .idle_bias_on = 1, 59662306a36Sopenharmony_ci .use_pmdown_time = 1, 59762306a36Sopenharmony_ci .endianness = 1, 59862306a36Sopenharmony_ci}; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_cistatic const struct snd_soc_dai_ops tas2562_speaker_dai_ops = { 60162306a36Sopenharmony_ci .hw_params = tas2562_hw_params, 60262306a36Sopenharmony_ci .set_fmt = tas2562_set_dai_fmt, 60362306a36Sopenharmony_ci .set_tdm_slot = tas2562_set_dai_tdm_slot, 60462306a36Sopenharmony_ci .mute_stream = tas2562_mute, 60562306a36Sopenharmony_ci .no_capture_mute = 1, 60662306a36Sopenharmony_ci}; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_cistatic struct snd_soc_dai_driver tas2562_dai[] = { 60962306a36Sopenharmony_ci { 61062306a36Sopenharmony_ci .name = "tas2562-amplifier", 61162306a36Sopenharmony_ci .id = 0, 61262306a36Sopenharmony_ci .playback = { 61362306a36Sopenharmony_ci .stream_name = "ASI1 Playback", 61462306a36Sopenharmony_ci .channels_min = 2, 61562306a36Sopenharmony_ci .channels_max = 2, 61662306a36Sopenharmony_ci .rates = SNDRV_PCM_RATE_8000_192000, 61762306a36Sopenharmony_ci .formats = TAS2562_FORMATS, 61862306a36Sopenharmony_ci }, 61962306a36Sopenharmony_ci .capture = { 62062306a36Sopenharmony_ci .stream_name = "ASI1 Capture", 62162306a36Sopenharmony_ci .channels_min = 0, 62262306a36Sopenharmony_ci .channels_max = 2, 62362306a36Sopenharmony_ci .rates = SNDRV_PCM_RATE_8000_192000, 62462306a36Sopenharmony_ci .formats = TAS2562_FORMATS, 62562306a36Sopenharmony_ci }, 62662306a36Sopenharmony_ci .ops = &tas2562_speaker_dai_ops, 62762306a36Sopenharmony_ci }, 62862306a36Sopenharmony_ci}; 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_cistatic const struct regmap_range_cfg tas2562_ranges[] = { 63162306a36Sopenharmony_ci { 63262306a36Sopenharmony_ci .range_min = 0, 63362306a36Sopenharmony_ci .range_max = 5 * 128, 63462306a36Sopenharmony_ci .selector_reg = TAS2562_PAGE_CTRL, 63562306a36Sopenharmony_ci .selector_mask = 0xff, 63662306a36Sopenharmony_ci .selector_shift = 0, 63762306a36Sopenharmony_ci .window_start = 0, 63862306a36Sopenharmony_ci .window_len = 128, 63962306a36Sopenharmony_ci }, 64062306a36Sopenharmony_ci}; 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_cistatic const struct reg_default tas2562_reg_defaults[] = { 64362306a36Sopenharmony_ci { TAS2562_PAGE_CTRL, 0x00 }, 64462306a36Sopenharmony_ci { TAS2562_SW_RESET, 0x00 }, 64562306a36Sopenharmony_ci { TAS2562_PWR_CTRL, 0x0e }, 64662306a36Sopenharmony_ci { TAS2562_PB_CFG1, 0x20 }, 64762306a36Sopenharmony_ci { TAS2562_TDM_CFG0, 0x09 }, 64862306a36Sopenharmony_ci { TAS2562_TDM_CFG1, 0x02 }, 64962306a36Sopenharmony_ci { TAS2562_DVC_CFG1, 0x40 }, 65062306a36Sopenharmony_ci { TAS2562_DVC_CFG2, 0x40 }, 65162306a36Sopenharmony_ci { TAS2562_DVC_CFG3, 0x00 }, 65262306a36Sopenharmony_ci { TAS2562_DVC_CFG4, 0x00 }, 65362306a36Sopenharmony_ci}; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_cistatic const struct regmap_config tas2562_regmap_config = { 65662306a36Sopenharmony_ci .reg_bits = 8, 65762306a36Sopenharmony_ci .val_bits = 8, 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci .max_register = 5 * 128, 66062306a36Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 66162306a36Sopenharmony_ci .reg_defaults = tas2562_reg_defaults, 66262306a36Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(tas2562_reg_defaults), 66362306a36Sopenharmony_ci .ranges = tas2562_ranges, 66462306a36Sopenharmony_ci .num_ranges = ARRAY_SIZE(tas2562_ranges), 66562306a36Sopenharmony_ci}; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_cistatic int tas2562_parse_dt(struct tas2562_data *tas2562) 66862306a36Sopenharmony_ci{ 66962306a36Sopenharmony_ci struct device *dev = tas2562->dev; 67062306a36Sopenharmony_ci int ret = 0; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH); 67362306a36Sopenharmony_ci if (IS_ERR(tas2562->sdz_gpio)) { 67462306a36Sopenharmony_ci if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER) 67562306a36Sopenharmony_ci return -EPROBE_DEFER; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci tas2562->sdz_gpio = NULL; 67862306a36Sopenharmony_ci } 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci /* 68162306a36Sopenharmony_ci * The shut-down property is deprecated but needs to be checked for 68262306a36Sopenharmony_ci * backwards compatibility. 68362306a36Sopenharmony_ci */ 68462306a36Sopenharmony_ci if (tas2562->sdz_gpio == NULL) { 68562306a36Sopenharmony_ci tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shut-down", 68662306a36Sopenharmony_ci GPIOD_OUT_HIGH); 68762306a36Sopenharmony_ci if (IS_ERR(tas2562->sdz_gpio)) 68862306a36Sopenharmony_ci if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER) 68962306a36Sopenharmony_ci return -EPROBE_DEFER; 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci tas2562->sdz_gpio = NULL; 69262306a36Sopenharmony_ci } 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci if (tas2562->model_id == TAS2110) 69562306a36Sopenharmony_ci return ret; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci ret = fwnode_property_read_u32(dev->fwnode, "ti,imon-slot-no", 69862306a36Sopenharmony_ci &tas2562->i_sense_slot); 69962306a36Sopenharmony_ci if (ret) { 70062306a36Sopenharmony_ci dev_err(dev, "Property %s is missing setting default slot\n", 70162306a36Sopenharmony_ci "ti,imon-slot-no"); 70262306a36Sopenharmony_ci tas2562->i_sense_slot = 0; 70362306a36Sopenharmony_ci } 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci ret = fwnode_property_read_u32(dev->fwnode, "ti,vmon-slot-no", 70762306a36Sopenharmony_ci &tas2562->v_sense_slot); 70862306a36Sopenharmony_ci if (ret) { 70962306a36Sopenharmony_ci dev_info(dev, "Property %s is missing setting default slot\n", 71062306a36Sopenharmony_ci "ti,vmon-slot-no"); 71162306a36Sopenharmony_ci tas2562->v_sense_slot = 2; 71262306a36Sopenharmony_ci } 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci if (tas2562->v_sense_slot < tas2562->i_sense_slot) { 71562306a36Sopenharmony_ci dev_err(dev, "Vsense slot must be greater than Isense slot\n"); 71662306a36Sopenharmony_ci return -EINVAL; 71762306a36Sopenharmony_ci } 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci return ret; 72062306a36Sopenharmony_ci} 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_cistatic const struct i2c_device_id tas2562_id[] = { 72362306a36Sopenharmony_ci { "tas2562", TAS2562 }, 72462306a36Sopenharmony_ci { "tas2563", TAS2563 }, 72562306a36Sopenharmony_ci { "tas2564", TAS2564 }, 72662306a36Sopenharmony_ci { "tas2110", TAS2110 }, 72762306a36Sopenharmony_ci { } 72862306a36Sopenharmony_ci}; 72962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, tas2562_id); 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_cistatic int tas2562_probe(struct i2c_client *client) 73262306a36Sopenharmony_ci{ 73362306a36Sopenharmony_ci struct device *dev = &client->dev; 73462306a36Sopenharmony_ci struct tas2562_data *data; 73562306a36Sopenharmony_ci int ret; 73662306a36Sopenharmony_ci const struct i2c_device_id *id; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 73962306a36Sopenharmony_ci if (!data) 74062306a36Sopenharmony_ci return -ENOMEM; 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci id = i2c_match_id(tas2562_id, client); 74362306a36Sopenharmony_ci data->client = client; 74462306a36Sopenharmony_ci data->dev = &client->dev; 74562306a36Sopenharmony_ci data->model_id = id->driver_data; 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci tas2562_parse_dt(data); 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci data->regmap = devm_regmap_init_i2c(client, &tas2562_regmap_config); 75062306a36Sopenharmony_ci if (IS_ERR(data->regmap)) { 75162306a36Sopenharmony_ci ret = PTR_ERR(data->regmap); 75262306a36Sopenharmony_ci dev_err(dev, "failed to allocate register map: %d\n", ret); 75362306a36Sopenharmony_ci return ret; 75462306a36Sopenharmony_ci } 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci dev_set_drvdata(&client->dev, data); 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci if (data->model_id == TAS2110) 75962306a36Sopenharmony_ci return devm_snd_soc_register_component(dev, 76062306a36Sopenharmony_ci &soc_component_dev_tas2110, 76162306a36Sopenharmony_ci tas2562_dai, 76262306a36Sopenharmony_ci ARRAY_SIZE(tas2562_dai)); 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci return devm_snd_soc_register_component(dev, &soc_component_dev_tas2562, 76562306a36Sopenharmony_ci tas2562_dai, 76662306a36Sopenharmony_ci ARRAY_SIZE(tas2562_dai)); 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci} 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci#ifdef CONFIG_OF 77162306a36Sopenharmony_cistatic const struct of_device_id tas2562_of_match[] = { 77262306a36Sopenharmony_ci { .compatible = "ti,tas2562", }, 77362306a36Sopenharmony_ci { .compatible = "ti,tas2563", }, 77462306a36Sopenharmony_ci { .compatible = "ti,tas2564", }, 77562306a36Sopenharmony_ci { .compatible = "ti,tas2110", }, 77662306a36Sopenharmony_ci { }, 77762306a36Sopenharmony_ci}; 77862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, tas2562_of_match); 77962306a36Sopenharmony_ci#endif 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_cistatic struct i2c_driver tas2562_i2c_driver = { 78262306a36Sopenharmony_ci .driver = { 78362306a36Sopenharmony_ci .name = "tas2562", 78462306a36Sopenharmony_ci .of_match_table = of_match_ptr(tas2562_of_match), 78562306a36Sopenharmony_ci }, 78662306a36Sopenharmony_ci .probe = tas2562_probe, 78762306a36Sopenharmony_ci .id_table = tas2562_id, 78862306a36Sopenharmony_ci}; 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_cimodule_i2c_driver(tas2562_i2c_driver); 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ciMODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>"); 79362306a36Sopenharmony_ciMODULE_DESCRIPTION("TAS2562 Audio amplifier driver"); 79462306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 795