blob: 69a2b8174ae16a89b45840d13b163261a2f2d33b [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/*
* linux/sound/soc/codecs/tlv320adc3101.c
*
* Copyright 2019 Baylibre
*
* Author: Nicolas Belin <nbelin@baylibre.com>
*
* Based on sound/soc/codecs/tlv320aic332x4.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include "tlv320adc3101.h"
struct adc3101_rate_divs {
u32 mclk;
u32 rate;
u8 nadc;
u8 madc;
u8 aosr;
};
struct adc3101_priv {
struct regmap *regmap;
u32 sysclk;
int rstn_gpio;
struct clk *mclk;
u32 tdm_offset;
u32 tdm_additional_offset;
u32 right_pin_select;
u32 left_pin_select;
u32 fmt;
struct regulator *supply_iov;
struct regulator *supply_dv;
struct regulator *supply_av;
unsigned int minus6db_left_input;
unsigned int minus6db_right_input;
struct device *dev;
};
static int adc3101_get_adc_left_input_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct adc3101_priv *adc3101 = snd_soc_component_get_drvdata(component);
ucontrol->value.integer.value[0] = adc3101->minus6db_left_input;
return 0;
}
static int adc3101_put_adc_left_input_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct adc3101_priv *adc3101 = snd_soc_component_get_drvdata(component);
unsigned int minus6db_left_input = ucontrol->value.integer.value[0];
if (minus6db_left_input > 1)
return -EINVAL;
adc3101->minus6db_left_input = minus6db_left_input;
snd_soc_component_update_bits(component, ADC3101_LPGAPIN,
ADC3101_PGAPIN_6DB_MASK,
minus6db_left_input ? ADC3101_PGAPIN_6DB_MASK : 0);
snd_soc_component_update_bits(component, ADC3101_LPGAPIN2,
ADC3101_PGAPIN2_6DB_MASK,
minus6db_left_input ? ADC3101_PGAPIN2_6DB_MASK : 0);
return 0;
}
static int adc3101_get_adc_right_input_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct adc3101_priv *adc3101 = snd_soc_component_get_drvdata(component);
ucontrol->value.integer.value[0] = adc3101->minus6db_right_input;
return 0;
}
static int adc3101_put_adc_right_input_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct adc3101_priv *adc3101 = snd_soc_component_get_drvdata(component);
unsigned int minus6db_right_input = ucontrol->value.integer.value[0];
if (minus6db_right_input > 1)
return -EINVAL;
adc3101->minus6db_right_input = minus6db_right_input;
snd_soc_component_update_bits(component, ADC3101_RPGAPIN,
ADC3101_PGAPIN_6DB_MASK,
minus6db_right_input ? ADC3101_PGAPIN_6DB_MASK : 0);
snd_soc_component_update_bits(component, ADC3101_RPGAPIN2,
ADC3101_PGAPIN2_6DB_MASK,
minus6db_right_input ? ADC3101_PGAPIN2_6DB_MASK : 0);
return 0;
}
/* 0dB min, 0.5dB steps */
static DECLARE_TLV_DB_SCALE(tlv_step_0_5, 0, 50, 0);
/* -12dB min, 0.5dB steps */
static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0);
static const struct snd_kcontrol_new adc3101_snd_controls[] = {
SOC_SINGLE("ADC Mute Left Switch", ADC3101_FADCVOL, 7, 1, 0),
SOC_SINGLE("ADC Mute Right Switch", ADC3101_FADCVOL, 3, 1, 0),
SOC_DOUBLE_R_S_TLV("ADC Level Volume", ADC3101_LADCVOL,
ADC3101_RADCVOL, 0, -0x18, 0x28, 6, 0, tlv_adc_vol),
SOC_DOUBLE_R_TLV("PGA Level Volume", ADC3101_LAPGAVOL,
ADC3101_RAPGAVOL, 0, 0x50, 0, tlv_step_0_5),
SOC_SINGLE_BOOL_EXT("Minus 6dB ADC Left input Switch", 0,
adc3101_get_adc_left_input_switch,
adc3101_put_adc_left_input_switch),
SOC_SINGLE_BOOL_EXT("Minus 6dB ADC Right input Switch", 0,
adc3101_get_adc_right_input_switch,
adc3101_put_adc_right_input_switch),
};
static const struct adc3101_rate_divs adc3101_divs[] = {
//conditions
//MCLK 50MHz MAX
//33MHz Max after NADC
//2.8 MHz < AOSR × ADC_fs < 6.2 MHz
/* 8k rate */
{2048000, 8000, 1, 1, 0}, //256 mclk_fs, AOSR=0 means 256
/* 11.025k rate */
{2822400, 11025, 1, 1, 0}, //64 mclk_fs, AOSR=0 means 256
/* 16k rate */
{4096000, 16000, 1, 1, 0}, //256 mclk_fs, AOSR=0 means 256
/* 22.05k rate */
{5644800, 22050, 1, 1, 0}, //256 mclk_fs, AOSR=0 means 256
/* 32k rate */
{4096000, 32000, 1, 1, 128}, //128 mclk_fs
{8192000, 32000, 1, 2, 128}, //256 mclk_fs
{22579200, 32000, 2, 2, 128}, //512 mclk_fs
/* 44.1k rate */
{2822400, 44100, 1, 1, 64}, //64 mclk_fs
{5644800, 44100, 1, 1, 128}, //128 mclk_fs
{11289600, 44100, 1, 2, 128}, //256 mclk_fs
{22579200, 44100, 2, 2, 128}, //512 mclk_fs
/* 48k rate */
{3072000, 48000, 1, 1, 64}, //64 mclk_fs
{6144000, 48000, 1, 1, 128}, //128 mclk_fs
{12288000, 48000, 1, 2, 128}, //256 mclk_fs
{24576000, 48000, 2, 2, 128}, //512 mclk_fs
/* 96k rate */
{24576000, 96000, 2, 2, 64}, //256 mclk_fs
};
static const struct snd_soc_dapm_widget adc3101_dapm_widgets[] = {
SND_SOC_DAPM_ADC("Right ADC", "Right Capture",
ADC3101_ADC_DIGITAL, 6, 0),
SND_SOC_DAPM_ADC("Left ADC", "Left Capture", ADC3101_ADC_DIGITAL, 7, 0),
SND_SOC_DAPM_INPUT("IN1_L"),
SND_SOC_DAPM_INPUT("IN1_R"),
};
static const struct snd_soc_dapm_route adc3101_dapm_routes[] = {
/* Right Input */
{"Right ADC", NULL, "IN1_R"},
/* Left Input */
{"Left ADC", NULL, "IN1_L"},
};
static const struct regmap_range_cfg adc3101_regmap_pages[] = {
{
.name = "Pages",
.selector_reg = 0,
.selector_mask = 0xff,
.window_start = 0,
.window_len = 128,
.range_min = 0,
.range_max = ADC3101_APGAFLAGS,
},
};
const struct regmap_config adc3101_regmap_config = {
.max_register = ADC3101_APGAFLAGS,
.ranges = adc3101_regmap_pages,
.num_ranges = ARRAY_SIZE(adc3101_regmap_pages),
};
EXPORT_SYMBOL(adc3101_regmap_config);
static inline int adc3101_get_divs(int mclk, int rate)
{
int i;
for (i = 0; i < ARRAY_SIZE(adc3101_divs); i++) {
if ((adc3101_divs[i].rate == rate)
&& (adc3101_divs[i].mclk == mclk)) {
return i;
}
}
return -EINVAL;
}
static int adc3101_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_component *component = codec_dai->component;
struct adc3101_priv *adc3101 = snd_soc_component_get_drvdata(component);
dev_dbg(component->dev, "frequency to set DAI system clock=%d\n", freq);
adc3101->sysclk = freq;
return 0;
}
static int adc3101_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
unsigned int rx_mask, int slots, int slot_width)
{
struct snd_soc_component *component = dai->component;
struct adc3101_priv *adc3101 = snd_soc_component_get_drvdata(component);
unsigned int first_slot, last_slot, tdm_offset;
dev_dbg(component->dev,
"%s() tx_mask=0x%x rx_mask=0x%x slots=%d slot_width=%d\n",
__func__, tx_mask, rx_mask, slots, slot_width);
if (!tx_mask) {
dev_err(component->dev, "tdm tx mask must not be 0\n");
return -EINVAL;
}
first_slot = __ffs(tx_mask);
last_slot = __fls(tx_mask);
if (last_slot - first_slot != hweight32(tx_mask) - 1) {
dev_err(component->dev, "tdm tx mask must be contiguous\n");
return -EINVAL;
}
tdm_offset = first_slot * slot_width;
tdm_offset += adc3101->tdm_additional_offset;
if (tdm_offset > 255) {
dev_err(component->dev,
"tdm tx slot selection out of bounds\n");
return -EINVAL;
}
adc3101->tdm_offset = tdm_offset;
dev_dbg(component->dev, "tdm offset is %d\n", adc3101->tdm_offset);
/* tdm offset */
snd_soc_component_write(component, ADC3101_CH_OFFSET_1, tdm_offset);
/* second channel always after the first one */
snd_soc_component_write(component, ADC3101_CH_OFFSET_2, 0);
return 0;
}
static int adc3101_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
{
struct snd_soc_component *component = codec_dai->component;
struct adc3101_priv *adc3101 = snd_soc_component_get_drvdata(component);
dev_dbg(component->dev,
"adc3101: fmt to set DAI fmt=0x%x\n",
fmt);
/* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
dev_err(component->dev,
"adc3101: invalid DAI master mode not supported\n");
return -EINVAL;
case SND_SOC_DAIFMT_CBS_CFS:
break;
default:
dev_err(component->dev,
"adc3101: invalid DAI master/slave interface\n");
return -EINVAL;
}
adc3101->tdm_additional_offset = 0;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_DSP_A:
/* same as B but add offset 1 */
adc3101->tdm_additional_offset = 0x01;
case SND_SOC_DAIFMT_I2S:
case SND_SOC_DAIFMT_DSP_B:
case SND_SOC_DAIFMT_RIGHT_J:
case SND_SOC_DAIFMT_LEFT_J:
adc3101->fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
break;
default:
dev_err(component->dev,
"adc3101: invalid DAI interface format\n");
return -EINVAL;
}
return 0;
}
static int adc3101_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
struct adc3101_priv *adc3101 = snd_soc_component_get_drvdata(component);
u8 iface1_reg = 0;
u8 iface2_reg = 0;
u8 i2s_tdm_reg = 0;
int i;
struct device *dev = adc3101->dev;
i = adc3101_get_divs(adc3101->sysclk, params_rate(params));
if (i < 0) {
dev_err(component->dev,
"adc3101: sampling rate not supported\n");
return i;
}
/* NADC divider value and enable */
snd_soc_component_write(component, ADC3101_NADC, adc3101_divs[i].nadc |
ADC3101_NADCEN);
/* MADC divider value and enable */
snd_soc_component_write(component, ADC3101_MADC, adc3101_divs[i].madc |
ADC3101_MADCEN);
/* AOSR value */
snd_soc_component_write(component, ADC3101_AOSR, adc3101_divs[i].aosr);
/* check the wanted interface configuration */
switch (adc3101->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
break;
case SND_SOC_DAIFMT_DSP_A:
case SND_SOC_DAIFMT_DSP_B:
iface1_reg |= (ADC3101_DSP_MODE <<
ADC3101_IFACE1_DATATYPE_SHIFT);
iface1_reg |= ADC3101_3STATE;
iface2_reg |= ADC3101_BCLKINV_MASK; /* invert bit clock */
i2s_tdm_reg |= ADC3101_TDM_EN | ADC3101_EARLY_STATE_EN;
break;
case SND_SOC_DAIFMT_RIGHT_J:
iface1_reg |= (ADC3101_RIGHT_J_MODE <<
ADC3101_IFACE1_DATATYPE_SHIFT);
break;
case SND_SOC_DAIFMT_LEFT_J:
iface1_reg |= (ADC3101_LEFT_J_MODE <<
ADC3101_IFACE1_DATATYPE_SHIFT);
break;
default:
dev_err(component->dev,
"adc3101: invalid DAI interface format\n");
return -EINVAL;
}
switch (params_width(params)) {
case 16:
iface1_reg |= (ADC3101_WORD_LEN_16BITS <<
ADC3101_IFACE1_DATALEN_SHIFT);
break;
case 20:
iface1_reg |= (ADC3101_WORD_LEN_20BITS <<
ADC3101_IFACE1_DATALEN_SHIFT);
break;
case 24:
iface1_reg |= (ADC3101_WORD_LEN_24BITS <<
ADC3101_IFACE1_DATALEN_SHIFT);
break;
case 32:
iface1_reg |= (ADC3101_WORD_LEN_32BITS <<
ADC3101_IFACE1_DATALEN_SHIFT);
break;
}
/* BDIVCLKIN is always ADC_CLK */
iface2_reg |= ADC3101_BDIVCLKIN_ADC_CLK << ADC3101_BDIVCLKIN_SHIFT;
/* writing the iface 1 & 2 settings */
snd_soc_component_write(component, ADC3101_IFACE1, iface1_reg);
snd_soc_component_write(component, ADC3101_IFACE2, iface2_reg);
/* enabling tdm if needed */
snd_soc_component_write(component, ADC3101_I2S_TDM, i2s_tdm_reg);
return 0;
}
static int adc3101_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_component *component = dai->component;
snd_soc_component_update_bits(component, ADC3101_FADCVOL,
ADC3101_MUTE_MASK, mute ? ADC3101_MUTE : 0);
return 0;
}
static int adc3101_set_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
switch (level) {
case SND_SOC_BIAS_ON:
break;
case SND_SOC_BIAS_PREPARE:
break;
case SND_SOC_BIAS_STANDBY:
break;
case SND_SOC_BIAS_OFF:
break;
}
return 0;
}
#define ADC3101_RATES SNDRV_PCM_RATE_8000_96000
#define ADC3101_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
| SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
static const struct snd_soc_dai_ops adc3101_ops = {
.hw_params = adc3101_hw_params,
.digital_mute = adc3101_mute,
.set_tdm_slot = adc3101_set_tdm_slot,
.set_fmt = adc3101_set_dai_fmt,
.set_sysclk = adc3101_set_dai_sysclk,
};
static struct snd_soc_dai_driver adc3101_dai = {
.name = "tlv320adc3101-aif",
.capture = {
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = ADC3101_RATES,
.formats = ADC3101_FORMATS,
},
.ops = &adc3101_ops,
};
static int adc3101_component_probe(struct snd_soc_component *component)
{
struct adc3101_priv *adc3101 = snd_soc_component_get_drvdata(component);
struct device *dev = adc3101->dev;
u8 clk_mux = 0;
if (gpio_is_valid(adc3101->rstn_gpio)) {
gpio_set_value(adc3101->rstn_gpio, 0);
ndelay(10);
gpio_set_value(adc3101->rstn_gpio, 1);
ndelay(10);
} else {
dev_err(dev,
"invalid reset gpio. Your adc may not work properly\n");
}
/* SW reset */
snd_soc_component_write(component, ADC3101_RESET, ADC3101_RESET_VALUE);
/* MCLK as an input, not supporting anything else */
clk_mux |= (ADC3101_PLL_CLKIN_MCLK << ADC3101_PLL_CLKIN_SHIFT) |
(ADC3101_CODEC_CLKIN_MCLK << ADC3101_CODEC_CLKIN_MCLK);
snd_soc_component_write(component, ADC3101_CLKMUX, clk_mux);
/* left pin selection */
switch (adc3101->left_pin_select) {
case CH_SEL1:
case CH_SEL2:
case CH_SEL3:
case CH_SEL4:
snd_soc_component_update_bits(component, ADC3101_LPGAPIN,
ADC3101_PGAPIN_SEL_MASK <<
(2 * adc3101->left_pin_select),
adc3101->minus6db_left_input);
break;
case CH_SEL1X:
case CH_SEL2X:
case CH_SEL3X:
snd_soc_component_update_bits(component, ADC3101_LPGAPIN2,
ADC3101_PGAPIN_SEL_MASK <<
(2 * adc3101->left_pin_select - 8),
adc3101->minus6db_left_input);
break;
default:
dev_err(component->dev, "wrong left pin selection\n");
return -EINVAL;
}
/* right pin selection */
switch (adc3101->right_pin_select) {
case CH_SEL1:
case CH_SEL2:
case CH_SEL3:
case CH_SEL4:
snd_soc_component_update_bits(component, ADC3101_RPGAPIN,
ADC3101_PGAPIN_SEL_MASK <<
(2 * adc3101->right_pin_select),
adc3101->minus6db_right_input);
break;
case CH_SEL1X:
case CH_SEL2X:
case CH_SEL3X:
snd_soc_component_update_bits(component, ADC3101_RPGAPIN2,
ADC3101_PGAPIN_SEL_MASK <<
(2 * adc3101->right_pin_select - 8),
adc3101->minus6db_right_input);
break;
default:
dev_err(component->dev, "wrong right pin selection\n");
return -EINVAL;
}
/* unmute the left analog PGA */
snd_soc_component_update_bits(component, ADC3101_LAPGAVOL,
ADC3101_APGA_MUTE, 0);
/* unmute the right analog PGA */
snd_soc_component_update_bits(component, ADC3101_RAPGAVOL,
ADC3101_APGA_MUTE, 0);
/* update the soft stepping only */
snd_soc_component_update_bits(component, ADC3101_ADC_DIGITAL,
ADC3101_SOFT_STEPPING_MASK,
ADC3101_SOFT_STEPPING_DISABLE);
/* unmute */
snd_soc_component_update_bits(component, ADC3101_FADCVOL,
ADC3101_MUTE_MASK, 0);
return 0;
}
static const struct snd_soc_component_driver soc_component_dev_adc3101 = {
.probe = adc3101_component_probe,
.set_bias_level = adc3101_set_bias_level,
.controls = adc3101_snd_controls,
.num_controls = ARRAY_SIZE(adc3101_snd_controls),
.dapm_widgets = adc3101_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(adc3101_dapm_widgets),
.dapm_routes = adc3101_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(adc3101_dapm_routes),
.suspend_bias_off = 1,
.idle_bias_on = 1,
.use_pmdown_time = 1,
.endianness = 1,
.non_legacy_dai_naming = 1,
};
static int adc3101_parse_dt(struct adc3101_priv *adc3101,
struct device_node *np)
{
struct device *dev = adc3101->dev;
int ret = 0;
adc3101->rstn_gpio = of_get_named_gpio(np, "rst-gpio", 0);
if (!gpio_is_valid(adc3101->rstn_gpio)) {
dev_err(dev, "Invalid reset gpio\n");
return -EINVAL;
}
ret = of_property_read_u32(np, "left-pin-select",
&adc3101->left_pin_select);
if (!ret) {
if (adc3101->left_pin_select > CH_SEL3X) {
dev_err(dev, "wrong left pin selection\n");
return -EINVAL;
}
} else {
dev_err(dev, "left pin not selected\n");
return ret;
}
ret = of_property_read_u32(np, "right-pin-select",
&adc3101->right_pin_select);
if (!ret) {
if (adc3101->right_pin_select > CH_SEL3X) {
dev_err(dev, "wrong right pin selection\n");
return -EINVAL;
}
} else {
dev_err(dev, "right pin not selected\n");
return ret;
}
return 0;
}
static void adc3101_disable_regulators(struct adc3101_priv *adc3101)
{
if (!IS_ERR(adc3101->supply_iov))
regulator_disable(adc3101->supply_iov);
if (!IS_ERR(adc3101->supply_dv))
regulator_disable(adc3101->supply_dv);
if (!IS_ERR(adc3101->supply_av))
regulator_disable(adc3101->supply_av);
}
static int adc3101_setup_regulators(struct device *dev,
struct adc3101_priv *adc3101)
{
int ret = 0;
adc3101->supply_iov = devm_regulator_get(dev, "iov");
adc3101->supply_dv = devm_regulator_get_optional(dev, "dv");
adc3101->supply_av = devm_regulator_get_optional(dev, "av");
/* Check for the regulators */
if (IS_ERR(adc3101->supply_iov)) {
dev_err(dev, "Missing supply 'iov'\n");
return PTR_ERR(adc3101->supply_iov);
}
if (IS_ERR(adc3101->supply_dv)) {
dev_err(dev, "Missing supply 'dv'\n");
return PTR_ERR(adc3101->supply_dv);
}
if (IS_ERR(adc3101->supply_av)) {
dev_err(dev, "Missing supply 'av'\n");
return PTR_ERR(adc3101->supply_av);
}
ret = regulator_enable(adc3101->supply_iov);
if (ret) {
dev_err(dev, "Failed to enable regulator iov\n");
return ret;
}
ret = regulator_enable(adc3101->supply_dv);
if (ret) {
dev_err(dev, "Failed to enable regulator dv\n");
goto error_dv;
}
ret = regulator_enable(adc3101->supply_av);
if (ret) {
dev_err(dev, "Failed to enable regulator av\n");
goto error_av;
}
return 0;
error_av:
regulator_disable(adc3101->supply_dv);
error_dv:
regulator_disable(adc3101->supply_iov);
return ret;
}
int adc3101_probe(struct device *dev, struct regmap *regmap)
{
struct adc3101_priv *adc3101;
struct device_node *np = dev->of_node;
int ret;
if (IS_ERR(regmap))
return PTR_ERR(regmap);
adc3101 = devm_kzalloc(dev, sizeof(struct adc3101_priv),
GFP_KERNEL);
if (adc3101 == NULL)
return -ENOMEM;
adc3101->dev = dev;
dev_set_drvdata(dev, adc3101);
adc3101->regmap = regmap;
if (np) {
ret = adc3101_parse_dt(adc3101, np);
if (ret) {
dev_err(dev, "Failed to parse DT node\n");
return ret;
}
} else {
dev_err(dev, "Could not parse DT node\n");
return -EINVAL;
}
/* setting default values */
adc3101->fmt = SND_SOC_DAIFMT_DSP_A;
adc3101->sysclk = 0;
adc3101->tdm_offset = 0;
adc3101->tdm_additional_offset = 0;
adc3101->minus6db_left_input = 1;
adc3101->minus6db_right_input = 1;
if (gpio_is_valid(adc3101->rstn_gpio)) {
ret = devm_gpio_request_one(dev, adc3101->rstn_gpio,
GPIOF_OUT_INIT_LOW, "tlv320adc3101 rstn");
if (ret != 0)
return ret;
}
ret = adc3101_setup_regulators(dev, adc3101);
if (ret) {
dev_err(dev, "Failed to setup regulators\n");
return ret;
}
ret = devm_snd_soc_register_component(dev,
&soc_component_dev_adc3101, &adc3101_dai, 1);
if (ret) {
dev_err(dev, "Failed to register component\n");
adc3101_disable_regulators(adc3101);
return ret;
}
if (gpio_is_valid(adc3101->rstn_gpio)) {
gpio_set_value(adc3101->rstn_gpio, 0);
ndelay(10);
gpio_set_value(adc3101->rstn_gpio, 1);
ndelay(10);
} else {
dev_err(dev,
"invalid reset gpio. Your adc may not work properly\n");
}
/* SW reset */
ret = regmap_write(adc3101->regmap, ADC3101_RESET, ADC3101_RESET_VALUE);
if (ret) {
dev_err(adc3101->dev,
"failed to write the reset register: %d\n", ret);
return ret;
}
return 0;
}
EXPORT_SYMBOL(adc3101_probe);
int adc3101_remove(struct device *dev)
{
struct adc3101_priv *adc3101 = dev_get_drvdata(dev);
adc3101_disable_regulators(adc3101);
return 0;
}
EXPORT_SYMBOL(adc3101_remove);
MODULE_DESCRIPTION("ASoC tlv320adc3101 codec driver");
MODULE_AUTHOR("Nicolas Belin <nbelin.com>");
MODULE_LICENSE("GPL v2");