linux/sound/soc/codecs/tlv320adc3xxx.c

// SPDX-License-Identifier: GPL-2.0-only
//
// Based on sound/soc/codecs/tlv320aic3x.c by  Vladimir Barinov
//
// Copyright (C) 2010 Mistral Solutions Pvt Ltd.
// Author: Shahina Shaik <[email protected]>
//
// Copyright (C) 2014-2018, Ambarella, Inc.
// Author: Dongge wu <[email protected]>
//
// Copyright (C) 2021 Axis Communications AB
// Author: Ricard Wanderlof <[email protected]>
//

#include <dt-bindings/sound/tlv320adc3xxx.h>
#include <linux/clk.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/io.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/gpio/driver.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/slab.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/tlv.h>
#include <sound/initval.h>

/*
 * General definitions defining exported functionality.
 */

#define ADC3XXX_MICBIAS_PINS
#define ADC3XXX_GPIO_PINS

/* Number of GPIO pins exposed via the gpiolib interface */
#define ADC3XXX_GPIOS_MAX

#define ADC3XXX_RATES
#define ADC3XXX_FORMATS

/*
 * PLL modes, to be used for clk_id for set_sysclk callback.
 *
 * The default behavior (AUTO) is to take the first matching entry in the clock
 * table, which is intended to be the PLL based one if there is more than one.
 *
 * Setting the clock source using simple-card (clocks or
 * system-clock-frequency property) sets clk_id = 0 = ADC3XXX_PLL_AUTO.
 */
#define ADC3XXX_PLL_AUTO
#define ADC3XXX_PLL_ENABLE
#define ADC3XXX_PLL_BYPASS

/* Register definitions. */

#define ADC3XXX_PAGE_SIZE
#define ADC3XXX_REG(page, reg)

/*
 * Page 0 registers.
 */

#define ADC3XXX_PAGE_SELECT
#define ADC3XXX_RESET

/* 2-3 Reserved */

#define ADC3XXX_CLKGEN_MUX
#define ADC3XXX_PLL_PROG_PR
#define ADC3XXX_PLL_PROG_J
#define ADC3XXX_PLL_PROG_D_MSB
#define ADC3XXX_PLL_PROG_D_LSB

/* 9-17 Reserved */

#define ADC3XXX_ADC_NADC
#define ADC3XXX_ADC_MADC
#define ADC3XXX_ADC_AOSR
#define ADC3XXX_ADC_IADC

/* 23-24 Reserved */

#define ADC3XXX_CLKOUT_MUX
#define ADC3XXX_CLKOUT_M_DIV
#define ADC3XXX_INTERFACE_CTRL_1
#define ADC3XXX_CH_OFFSET_1
#define ADC3XXX_INTERFACE_CTRL_2
#define ADC3XXX_BCLK_N_DIV
#define ADC3XXX_INTERFACE_CTRL_3
#define ADC3XXX_INTERFACE_CTRL_4
#define ADC3XXX_INTERFACE_CTRL_5
#define ADC3XXX_I2S_SYNC
/* 35 Reserved */
#define ADC3XXX_ADC_FLAG
#define ADC3XXX_CH_OFFSET_2
#define ADC3XXX_I2S_TDM_CTRL
/* 39-41 Reserved */
#define ADC3XXX_INTR_FLAG_1
#define ADC3XXX_INTR_FLAG_2
/* 44 Reserved */
#define ADC3XXX_INTR_FLAG_ADC1
/* 46 Reserved */
#define ADC3XXX_INTR_FLAG_ADC2
#define ADC3XXX_INT1_CTRL
#define ADC3XXX_INT2_CTRL
/* 50 Reserved */
#define ADC3XXX_GPIO2_CTRL
#define ADC3XXX_GPIO1_CTRL
#define ADC3XXX_DOUT_CTRL
/* 54-56 Reserved */
#define ADC3XXX_SYNC_CTRL_1
#define ADC3XXX_SYNC_CTRL_2
#define ADC3XXX_CIC_GAIN_CTRL
/* 60 Reserved */
#define ADC3XXX_PRB_SELECT
#define ADC3XXX_INST_MODE_CTRL
/* 63-79 Reserved */
#define ADC3XXX_MIC_POLARITY_CTRL
#define ADC3XXX_ADC_DIGITAL
#define ADC3XXX_ADC_FGA
#define ADC3XXX_LADC_VOL
#define ADC3XXX_RADC_VOL
#define ADC3XXX_ADC_PHASE_COMP
#define ADC3XXX_LEFT_CHN_AGC_1
#define ADC3XXX_LEFT_CHN_AGC_2
#define ADC3XXX_LEFT_CHN_AGC_3
#define ADC3XXX_LEFT_CHN_AGC_4
#define ADC3XXX_LEFT_CHN_AGC_5
#define ADC3XXX_LEFT_CHN_AGC_6
#define ADC3XXX_LEFT_CHN_AGC_7
#define ADC3XXX_LEFT_AGC_GAIN
#define ADC3XXX_RIGHT_CHN_AGC_1
#define ADC3XXX_RIGHT_CHN_AGC_2
#define ADC3XXX_RIGHT_CHN_AGC_3
#define ADC3XXX_RIGHT_CHN_AGC_4
#define ADC3XXX_RIGHT_CHN_AGC_5
#define ADC3XXX_RIGHT_CHN_AGC_6
#define ADC3XXX_RIGHT_CHN_AGC_7
#define ADC3XXX_RIGHT_AGC_GAIN
/* 102-127 Reserved */

/*
 * Page 1 registers.
 */

/* 1-25 Reserved */
#define ADC3XXX_DITHER_CTRL
/* 27-50 Reserved */
#define ADC3XXX_MICBIAS_CTRL
#define ADC3XXX_LEFT_PGA_SEL_1
/* 53 Reserved */
#define ADC3XXX_LEFT_PGA_SEL_2
#define ADC3XXX_RIGHT_PGA_SEL_1
#define ADC3XXX_RIGHT_PGA_SEL_2
#define ADC3XXX_LEFT_APGA_CTRL
#define ADC3XXX_RIGHT_APGA_CTRL
#define ADC3XXX_LOW_CURRENT_MODES
#define ADC3XXX_ANALOG_PGA_FLAGS
/* 63-127 Reserved */

/*
 * Page 4 registers. First page of coefficient memory for the miniDSP.
 */
#define ADC3XXX_LEFT_ADC_IIR_COEFF_N0_MSB
#define ADC3XXX_LEFT_ADC_IIR_COEFF_N0_LSB
#define ADC3XXX_LEFT_ADC_IIR_COEFF_N1_MSB
#define ADC3XXX_LEFT_ADC_IIR_COEFF_N1_LSB
#define ADC3XXX_LEFT_ADC_IIR_COEFF_D1_MSB
#define ADC3XXX_LEFT_ADC_IIR_COEFF_D1_LSB

#define ADC3XXX_RIGHT_ADC_IIR_COEFF_N0_MSB
#define ADC3XXX_RIGHT_ADC_IIR_COEFF_N0_LSB
#define ADC3XXX_RIGHT_ADC_IIR_COEFF_N1_MSB
#define ADC3XXX_RIGHT_ADC_IIR_COEFF_N1_LSB
#define ADC3XXX_RIGHT_ADC_IIR_COEFF_D1_MSB
#define ADC3XXX_RIGHT_ADC_IIR_COEFF_D1_LSB

/*
 * Register bits.
 */

/* PLL Enable bits */
#define ADC3XXX_ENABLE_PLL_SHIFT
#define ADC3XXX_ENABLE_PLL
#define ADC3XXX_ENABLE_NADC_SHIFT
#define ADC3XXX_ENABLE_NADC
#define ADC3XXX_ENABLE_MADC_SHIFT
#define ADC3XXX_ENABLE_MADC
#define ADC3XXX_ENABLE_BCLK_SHIFT
#define ADC3XXX_ENABLE_BCLK

/* Power bits */
#define ADC3XXX_LADC_PWR_ON
#define ADC3XXX_RADC_PWR_ON

#define ADC3XXX_SOFT_RESET
#define ADC3XXX_BCLK_MASTER
#define ADC3XXX_WCLK_MASTER

/* Interface register masks */
#define ADC3XXX_FORMAT_MASK
#define ADC3XXX_FORMAT_SHIFT
#define ADC3XXX_WLENGTH_MASK
#define ADC3XXX_WLENGTH_SHIFT
#define ADC3XXX_CLKDIR_MASK
#define ADC3XXX_CLKDIR_SHIFT

/* Interface register bit patterns */
#define ADC3XXX_FORMAT_I2S
#define ADC3XXX_FORMAT_DSP
#define ADC3XXX_FORMAT_RJF
#define ADC3XXX_FORMAT_LJF

#define ADC3XXX_IFACE_16BITS
#define ADC3XXX_IFACE_20BITS
#define ADC3XXX_IFACE_24BITS
#define ADC3XXX_IFACE_32BITS

/* PLL P/R bit offsets */
#define ADC3XXX_PLLP_SHIFT
#define ADC3XXX_PLLR_SHIFT
#define ADC3XXX_PLL_PR_MASK
#define ADC3XXX_PLLJ_MASK
#define ADC3XXX_PLLD_MSB_MASK
#define ADC3XXX_PLLD_LSB_MASK
#define ADC3XXX_NADC_MASK
#define ADC3XXX_MADC_MASK
#define ADC3XXX_AOSR_MASK
#define ADC3XXX_IADC_MASK
#define ADC3XXX_BDIV_MASK

/* PLL_CLKIN bits */
#define ADC3XXX_PLL_CLKIN_SHIFT
#define ADC3XXX_PLL_CLKIN_MCLK
#define ADC3XXX_PLL_CLKIN_BCLK
#define ADC3XXX_PLL_CLKIN_ZERO

/* CODEC_CLKIN bits */
#define ADC3XXX_CODEC_CLKIN_SHIFT
#define ADC3XXX_CODEC_CLKIN_MCLK
#define ADC3XXX_CODEC_CLKIN_BCLK
#define ADC3XXX_CODEC_CLKIN_PLL_CLK

#define ADC3XXX_USE_PLL
#define ADC3XXX_NO_PLL

/*  Analog PGA control bits */
#define ADC3XXX_LPGA_MUTE
#define ADC3XXX_RPGA_MUTE

#define ADC3XXX_LPGA_GAIN_MASK
#define ADC3XXX_RPGA_GAIN_MASK

/* ADC current modes */
#define ADC3XXX_ADC_LOW_CURR_MODE

/* Left ADC Input selection bits */
#define ADC3XXX_LCH_SEL1_SHIFT
#define ADC3XXX_LCH_SEL2_SHIFT
#define ADC3XXX_LCH_SEL3_SHIFT
#define ADC3XXX_LCH_SEL4_SHIFT

#define ADC3XXX_LCH_SEL1X_SHIFT
#define ADC3XXX_LCH_SEL2X_SHIFT
#define ADC3XXX_LCH_SEL3X_SHIFT
#define ADC3XXX_LCH_COMMON_MODE
#define ADC3XXX_BYPASS_LPGA

/* Right ADC Input selection bits */
#define ADC3XXX_RCH_SEL1_SHIFT
#define ADC3XXX_RCH_SEL2_SHIFT
#define ADC3XXX_RCH_SEL3_SHIFT
#define ADC3XXX_RCH_SEL4_SHIFT

#define ADC3XXX_RCH_SEL1X_SHIFT
#define ADC3XXX_RCH_SEL2X_SHIFT
#define ADC3XXX_RCH_SEL3X_SHIFT
#define ADC3XXX_RCH_COMMON_MODE
#define ADC3XXX_BYPASS_RPGA

/* MICBIAS control bits */
#define ADC3XXX_MICBIAS_MASK
#define ADC3XXX_MICBIAS1_SHIFT
#define ADC3XXX_MICBIAS2_SHIFT

#define ADC3XXX_ADC_MAX_VOLUME
#define ADC3XXX_ADC_POS_VOL

/* GPIO control bits (GPIO1_CTRL and GPIO2_CTRL) */
#define ADC3XXX_GPIO_CTRL_CFG_MASK
#define ADC3XXX_GPIO_CTRL_CFG_SHIFT
#define ADC3XXX_GPIO_CTRL_OUTPUT_CTRL_MASK
#define ADC3XXX_GPIO_CTRL_OUTPUT_CTRL_SHIFT
#define ADC3XXX_GPIO_CTRL_INPUT_VALUE_MASK
#define ADC3XXX_GPIO_CTRL_INPUT_VALUE_SHIFT

enum adc3xxx_type {};

struct adc3xxx {};

static const unsigned int adc3xxx_gpio_ctrl_reg[ADC3XXX_GPIO_PINS] =;

static const unsigned int adc3xxx_micbias_shift[ADC3XXX_MICBIAS_PINS] =;

static const struct reg_default adc3xxx_defaults[] =;

static bool adc3xxx_volatile_reg(struct device *dev, unsigned int reg)
{}

static const struct regmap_range_cfg adc3xxx_ranges[] =;

static const struct regmap_config adc3xxx_regmap =;

struct adc3xxx_rate_divs {};

/*
 * PLL and Clock settings.
 * If p member is 0, PLL is not used.
 * The order of the entries in this table have the PLL entries before
 * the non-PLL entries, so that the PLL modes are preferred unless
 * the PLL mode setting says otherwise.
 */
static const struct adc3xxx_rate_divs adc3xxx_divs[] =;

static int adc3xxx_get_divs(struct device *dev, int mclk, int rate, int pll_mode)
{}

static int adc3xxx_pll_delay(struct snd_soc_dapm_widget *w,
			     struct snd_kcontrol *kcontrol, int event)
{}

static int adc3xxx_coefficient_info(struct snd_kcontrol *kcontrol,
				    struct snd_ctl_elem_info *uinfo)
{}

static int adc3xxx_coefficient_get(struct snd_kcontrol *kcontrol,
				   struct snd_ctl_elem_value *ucontrol)
{}

static int adc3xxx_coefficient_put(struct snd_kcontrol *kcontrol,
				   struct snd_ctl_elem_value *ucontrol)
{}

/* All on-chip filters have coefficients which are expressed in terms of
 * 16 bit values, so represent them as strings of 16-bit integers.
 */
#define TI_COEFFICIENTS(xname, reg, numcoeffs)

static const char * const adc_softstepping_text[] =;
static SOC_ENUM_SINGLE_DECL(adc_softstepping_enum, ADC3XXX_ADC_DIGITAL, 0,
			    adc_softstepping_text);

static const char * const multiplier_text[] =;
static SOC_ENUM_SINGLE_DECL(left_agc_attack_mult_enum,
			    ADC3XXX_LEFT_CHN_AGC_4, 0, multiplier_text);
static SOC_ENUM_SINGLE_DECL(right_agc_attack_mult_enum,
			    ADC3XXX_RIGHT_CHN_AGC_4, 0, multiplier_text);
static SOC_ENUM_SINGLE_DECL(left_agc_decay_mult_enum,
			    ADC3XXX_LEFT_CHN_AGC_5, 0, multiplier_text);
static SOC_ENUM_SINGLE_DECL(right_agc_decay_mult_enum,
			    ADC3XXX_RIGHT_CHN_AGC_5, 0, multiplier_text);

static const char * const dither_dc_offset_text[] =;
static const unsigned int dither_dc_offset_values[] =;
static SOC_VALUE_ENUM_DOUBLE_DECL(dither_dc_offset_enum,
				  ADC3XXX_DITHER_CTRL,
				  4, 0, 0xf, dither_dc_offset_text,
				  dither_dc_offset_values);

static const DECLARE_TLV_DB_SCALE(pga_tlv, 0, 50, 0);
static const DECLARE_TLV_DB_SCALE(adc_tlv, -1200, 50, 0);
static const DECLARE_TLV_DB_SCALE(adc_fine_tlv, -40, 10, 0);
/* AGC target: 8 values: -5.5, -8, -10, -12, -14, -17, -20, -24 dB */
/* It would be nice to declare these in the order above, but empirically
 * TLV_DB_SCALE_ITEM doesn't take lightly to the increment (second) parameter
 * being negative, despite there being examples to the contrary in other
 * drivers. So declare these in the order from lowest to highest, and
 * set the invert flag in the SOC_DOUBLE_R_TLV declaration instead.
 */
static const DECLARE_TLV_DB_RANGE(agc_target_tlv,
	0, 0, TLV_DB_SCALE_ITEM(-2400, 0, 0),
	1, 3, TLV_DB_SCALE_ITEM(-2000, 300, 0),
	4, 6, TLV_DB_SCALE_ITEM(-1200, 200, 0),
	7, 7, TLV_DB_SCALE_ITEM(-550, 0, 0));
/* Since the 'disabled' value (mute) is at the highest value in the dB
 * range (i.e. just before -32 dB) rather than the lowest, we need to resort
 * to using a TLV_DB_RANGE in order to get the mute value in the right place.
 */
static const DECLARE_TLV_DB_RANGE(agc_thresh_tlv,
	0, 30, TLV_DB_SCALE_ITEM(-9000, 200, 0),
	31, 31, TLV_DB_SCALE_ITEM(0, 0, 1)); /* disabled = mute */
/* AGC hysteresis: 4 values: 1, 2, 4 dB, disabled (= mute) */
static const DECLARE_TLV_DB_RANGE(agc_hysteresis_tlv,
	0, 1, TLV_DB_SCALE_ITEM(100, 100, 0),
	2, 2, TLV_DB_SCALE_ITEM(400, 0, 0),
	3, 3, TLV_DB_SCALE_ITEM(0, 0, 1)); /* disabled = mute */
static const DECLARE_TLV_DB_SCALE(agc_max_tlv, 0, 50, 0);
/* Input attenuation: -6 dB or 0 dB */
static const DECLARE_TLV_DB_SCALE(input_attenuation_tlv, -600, 600, 0);

static const struct snd_kcontrol_new adc3xxx_snd_controls[] =;

/* Left input selection, Single Ended inputs and Differential inputs */
static const struct snd_kcontrol_new left_input_mixer_controls[] =;

/* Right input selection, Single Ended inputs and Differential inputs */
static const struct snd_kcontrol_new right_input_mixer_controls[] =;

/* Left Digital Mic input for left ADC */
static const struct snd_kcontrol_new left_input_dmic_controls[] =;

/* Right Digital Mic input for Right ADC */
static const struct snd_kcontrol_new right_input_dmic_controls[] =;

/* DAPM widgets */
static const struct snd_soc_dapm_widget adc3xxx_dapm_widgets[] =;

static const struct snd_soc_dapm_route adc3xxx_intercon[] =;

static const struct snd_soc_dapm_route adc3xxx_pll_intercon[] =;

static const struct snd_soc_dapm_route adc3xxx_bclk_out_intercon[] =;

static int adc3xxx_gpio_request(struct gpio_chip *chip, unsigned int offset)
{}

static int adc3xxx_gpio_direction_out(struct gpio_chip *chip,
				      unsigned int offset, int value)
{}

/* With only GPIO outputs configured, we never get the .direction_out call,
 * so we set the output mode and output value in the same call. Hence
 * .set in practice does the same thing as .direction_out .
 */
static void adc3xxx_gpio_set(struct gpio_chip *chip, unsigned int offset,
			     int value)
{}

/* Even though we only support GPIO output for now, some GPIO clients
 * want to read the current pin state using the .get callback.
 */
static int adc3xxx_gpio_get(struct gpio_chip *chip, unsigned int offset)
{}

static const struct gpio_chip adc3xxx_gpio_chip =;

static void adc3xxx_free_gpio(struct adc3xxx *adc3xxx)
{}

static void adc3xxx_init_gpio(struct adc3xxx *adc3xxx)
{}

static int adc3xxx_parse_dt_gpio(struct adc3xxx *adc3xxx,
				 const char *propname, unsigned int *cfg)
{}

static int adc3xxx_parse_dt_micbias_gpo(struct adc3xxx *adc3xxx,
					const char *propname,
					unsigned int *cfg)
{}

static int adc3xxx_parse_dt_micbias_vg(struct adc3xxx *adc3xxx,
				       const char *propname, unsigned int *vg)
{}

static int adc3xxx_parse_pll_mode(uint32_t val, unsigned int *pll_mode)
{}

static void adc3xxx_setup_pll(struct snd_soc_component *component,
			      int div_entry)
{}

static int adc3xxx_hw_params(struct snd_pcm_substream *substream,
			     struct snd_pcm_hw_params *params,
			     struct snd_soc_dai *dai)
{}

static const char *adc3xxx_pll_mode_text(int pll_mode)
{}

static int adc3xxx_set_dai_sysclk(struct snd_soc_dai *codec_dai,
				  int clk_id, unsigned int freq, int dir)
{}

static int adc3xxx_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
{}

static const struct snd_soc_dai_ops adc3xxx_dai_ops =;

static struct snd_soc_dai_driver adc3xxx_dai =;

static const struct snd_soc_component_driver soc_component_dev_adc3xxx =;

static const struct i2c_device_id adc3xxx_i2c_id[] =;
MODULE_DEVICE_TABLE(i2c, adc3xxx_i2c_id);

static int adc3xxx_i2c_probe(struct i2c_client *i2c)
{}

static void adc3xxx_i2c_remove(struct i2c_client *client)
{}

static const struct of_device_id tlv320adc3xxx_of_match[] =;
MODULE_DEVICE_TABLE(of, tlv320adc3xxx_of_match);

static struct i2c_driver adc3xxx_i2c_driver =;

module_i2c_driver();

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();