linux/sound/soc/codecs/rt5670.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * rt5670.c  --  RT5670 ALSA SoC audio codec driver
 *
 * Copyright 2014 Realtek Semiconductor Corp.
 * Author: Bard Liao <[email protected]>
 */

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include <linux/spi/spi.h>
#include <linux/dmi.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/jack.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <sound/tlv.h>

#include "rl6231.h"
#include "rt5670.h"
#include "rt5670-dsp.h"

#define RT5670_GPIO1_IS_IRQ
#define RT5670_IN2_DIFF
#define RT5670_DMIC_EN
#define RT5670_DMIC1_IN2P
#define RT5670_DMIC1_GPIO6
#define RT5670_DMIC1_GPIO7
#define RT5670_DMIC2_INR
#define RT5670_DMIC2_GPIO8
#define RT5670_DMIC3_GPIO5
#define RT5670_JD_MODE1
#define RT5670_JD_MODE2
#define RT5670_JD_MODE3
#define RT5670_GPIO1_IS_EXT_SPK_EN

static unsigned long rt5670_quirk;
static unsigned int quirk_override;
module_param_named(quirk, quirk_override, uint, 0444);
MODULE_PARM_DESC();

#define RT5670_DEVICE_ID

#define RT5670_PR_RANGE_BASE
#define RT5670_PR_SPACING

#define RT5670_PR_BASE

static const struct regmap_range_cfg rt5670_ranges[] =;

static const struct reg_sequence init_list[] =;

static const struct reg_default rt5670_reg[] =;

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

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

/**
 * rt5670_headset_detect - Detect headset.
 * @component: SoC audio component device.
 * @jack_insert: Jack insert or not.
 *
 * Detect whether is headset or not when jack inserted.
 *
 * Returns detect status.
 */

static int rt5670_headset_detect(struct snd_soc_component *component, int jack_insert)
{}

void rt5670_jack_suspend(struct snd_soc_component *component)
{}
EXPORT_SYMBOL_GPL();

void rt5670_jack_resume(struct snd_soc_component *component)
{}
EXPORT_SYMBOL_GPL();

static int rt5670_button_detect(struct snd_soc_component *component)
{}

static int rt5670_irq_detection(void *data)
{}

int rt5670_set_jack_detect(struct snd_soc_component *component,
	struct snd_soc_jack *jack)
{}
EXPORT_SYMBOL_GPL();

static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
static const DECLARE_TLV_DB_MINMAX(dac_vol_tlv, -6562, 0);
static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
static const DECLARE_TLV_DB_MINMAX(adc_vol_tlv, -1762, 3000);
static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);

/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
static const DECLARE_TLV_DB_RANGE(bst_tlv,
	0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
	1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
	2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
	3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
	6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
	7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
	8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0)
);

/* Interface data select */
static const char * const rt5670_data_select[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_if2_dac_enum, RT5670_DIG_INF1_DATA,
				RT5670_IF2_DAC_SEL_SFT, rt5670_data_select);

static SOC_ENUM_SINGLE_DECL(rt5670_if2_adc_enum, RT5670_DIG_INF1_DATA,
				RT5670_IF2_ADC_SEL_SFT, rt5670_data_select);

/*
 * For reliable output-mute LED control we need a "DAC1 Playback Switch" control.
 * We emulate this by only clearing the RT5670_M_DAC1_L/_R AD_DA_MIXER register
 * bits when both our emulated DAC1 Playback Switch control and the DAC1 MIXL/R
 * DAPM-mixer DAC1 input are enabled.
 */
static void rt5670_update_ad_da_mixer_dac1_m_bits(struct rt5670_priv *rt5670)
{}

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

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

static const struct snd_kcontrol_new rt5670_snd_controls[] =;

/**
 * set_dmic_clk - Set parameter of dmic.
 *
 * @w: DAPM widget.
 * @kcontrol: The kcontrol of this widget.
 * @event: Event id.
 *
 * Choose dmic clock between 1MHz and 3MHz.
 * It is better for clock to approximate 3MHz.
 */
static int set_dmic_clk(struct snd_soc_dapm_widget *w,
	struct snd_kcontrol *kcontrol, int event)
{}

static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
			 struct snd_soc_dapm_widget *sink)
{}

static int is_using_asrc(struct snd_soc_dapm_widget *source,
			 struct snd_soc_dapm_widget *sink)
{}

static int can_use_asrc(struct snd_soc_dapm_widget *source,
			 struct snd_soc_dapm_widget *sink)
{}


/**
 * rt5670_sel_asrc_clk_src - select ASRC clock source for a set of filters
 * @component: SoC audio component device.
 * @filter_mask: mask of filters.
 * @clk_src: clock source
 *
 * The ASRC function is for asynchronous MCLK and LRCK. Also, since RT5670 can
 * only support standard 32fs or 64fs i2s format, ASRC should be enabled to
 * support special i2s clock format such as Intel's 100fs(100 * sampling rate).
 * ASRC function will track i2s clock and generate a corresponding system clock
 * for codec. This function provides an API to select the clock source for a
 * set of filters specified by the mask. And the codec driver will turn on ASRC
 * for these filters if ASRC is selected as their clock source.
 */
int rt5670_sel_asrc_clk_src(struct snd_soc_component *component,
			    unsigned int filter_mask, unsigned int clk_src)
{}
EXPORT_SYMBOL_GPL();

/* Digital Mixer */
static const struct snd_kcontrol_new rt5670_sto1_adc_l_mix[] =;

static const struct snd_kcontrol_new rt5670_sto1_adc_r_mix[] =;

static const struct snd_kcontrol_new rt5670_sto2_adc_l_mix[] =;

static const struct snd_kcontrol_new rt5670_sto2_adc_r_mix[] =;

static const struct snd_kcontrol_new rt5670_mono_adc_l_mix[] =;

static const struct snd_kcontrol_new rt5670_mono_adc_r_mix[] =;

/* See comment above rt5670_update_ad_da_mixer_dac1_m_bits() */
static int rt5670_put_dac1_mix_dac1_switch(struct snd_kcontrol *kcontrol,
					   struct snd_ctl_elem_value *ucontrol)
{}

#define SOC_DAPM_SINGLE_RT5670_DAC1_SW(name, shift)

static const struct snd_kcontrol_new rt5670_dac_l_mix[] =;

static const struct snd_kcontrol_new rt5670_dac_r_mix[] =;

static const struct snd_kcontrol_new rt5670_sto_dac_l_mix[] =;

static const struct snd_kcontrol_new rt5670_sto_dac_r_mix[] =;

static const struct snd_kcontrol_new rt5670_mono_dac_l_mix[] =;

static const struct snd_kcontrol_new rt5670_mono_dac_r_mix[] =;

static const struct snd_kcontrol_new rt5670_dig_l_mix[] =;

static const struct snd_kcontrol_new rt5670_dig_r_mix[] =;

/* Analog Input Mixer */
static const struct snd_kcontrol_new rt5670_rec_l_mix[] =;

static const struct snd_kcontrol_new rt5670_rec_r_mix[] =;

static const struct snd_kcontrol_new rt5670_out_l_mix[] =;

static const struct snd_kcontrol_new rt5670_out_r_mix[] =;

static const struct snd_kcontrol_new rt5670_hpo_mix[] =;

static const struct snd_kcontrol_new rt5670_hpvoll_mix[] =;

static const struct snd_kcontrol_new rt5670_hpvolr_mix[] =;

static const struct snd_kcontrol_new rt5670_lout_mix[] =;

static const struct snd_kcontrol_new lout_l_enable_control =;

static const struct snd_kcontrol_new lout_r_enable_control =;

/* DAC1 L/R source */ /* MX-29 [9:8] [11:10] */
static const char * const rt5670_dac1_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_dac1l_enum, RT5670_AD_DA_MIXER,
	RT5670_DAC1_L_SEL_SFT, rt5670_dac1_src);

static const struct snd_kcontrol_new rt5670_dac1l_mux =;

static SOC_ENUM_SINGLE_DECL(rt5670_dac1r_enum, RT5670_AD_DA_MIXER,
	RT5670_DAC1_R_SEL_SFT, rt5670_dac1_src);

static const struct snd_kcontrol_new rt5670_dac1r_mux =;

/*DAC2 L/R source*/ /* MX-1B [6:4] [2:0] */
/* TODO Use SOC_VALUE_ENUM_SINGLE_DECL */
static const char * const rt5670_dac12_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_dac2l_enum, RT5670_DAC_CTRL,
	RT5670_DAC2_L_SEL_SFT, rt5670_dac12_src);

static const struct snd_kcontrol_new rt5670_dac_l2_mux =;

static const char * const rt5670_dacr2_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_dac2r_enum, RT5670_DAC_CTRL,
	RT5670_DAC2_R_SEL_SFT, rt5670_dacr2_src);

static const struct snd_kcontrol_new rt5670_dac_r2_mux =;

/*RxDP source*/ /* MX-2D [15:13] */
static const char * const rt5670_rxdp_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_rxdp_enum, RT5670_DSP_PATH1,
	RT5670_RXDP_SEL_SFT, rt5670_rxdp_src);

static const struct snd_kcontrol_new rt5670_rxdp_mux =;

/* MX-2D [1] [0] */
static const char * const rt5670_dsp_bypass_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_dsp_ul_enum, RT5670_DSP_PATH1,
	RT5670_DSP_UL_SFT, rt5670_dsp_bypass_src);

static const struct snd_kcontrol_new rt5670_dsp_ul_mux =;

static SOC_ENUM_SINGLE_DECL(rt5670_dsp_dl_enum, RT5670_DSP_PATH1,
	RT5670_DSP_DL_SFT, rt5670_dsp_bypass_src);

static const struct snd_kcontrol_new rt5670_dsp_dl_mux =;

/* Stereo2 ADC source */
/* MX-26 [15] */
static const char * const rt5670_stereo2_adc_lr_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc_lr_enum, RT5670_STO2_ADC_MIXER,
	RT5670_STO2_ADC_SRC_SFT, rt5670_stereo2_adc_lr_src);

static const struct snd_kcontrol_new rt5670_sto2_adc_lr_mux =;

/* Stereo1 ADC source */
/* MX-27 MX-26 [12] */
static const char * const rt5670_stereo_adc1_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_adc1_enum, RT5670_STO1_ADC_MIXER,
	RT5670_ADC_1_SRC_SFT, rt5670_stereo_adc1_src);

static const struct snd_kcontrol_new rt5670_sto_adc_1_mux =;

static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc1_enum, RT5670_STO2_ADC_MIXER,
	RT5670_ADC_1_SRC_SFT, rt5670_stereo_adc1_src);

static const struct snd_kcontrol_new rt5670_sto2_adc_1_mux =;


/* MX-27 MX-26 [11] */
static const char * const rt5670_stereo_adc2_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_adc2_enum, RT5670_STO1_ADC_MIXER,
	RT5670_ADC_2_SRC_SFT, rt5670_stereo_adc2_src);

static const struct snd_kcontrol_new rt5670_sto_adc_2_mux =;

static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc2_enum, RT5670_STO2_ADC_MIXER,
	RT5670_ADC_2_SRC_SFT, rt5670_stereo_adc2_src);

static const struct snd_kcontrol_new rt5670_sto2_adc_2_mux =;

/* MX-27 MX-26 [9:8] */
static const char * const rt5670_stereo_dmic_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_dmic_enum, RT5670_STO1_ADC_MIXER,
	RT5670_DMIC_SRC_SFT, rt5670_stereo_dmic_src);

static const struct snd_kcontrol_new rt5670_sto1_dmic_mux =;

static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_dmic_enum, RT5670_STO2_ADC_MIXER,
	RT5670_DMIC_SRC_SFT, rt5670_stereo_dmic_src);

static const struct snd_kcontrol_new rt5670_sto2_dmic_mux =;

/* Mono ADC source */
/* MX-28 [12] */
static const char * const rt5670_mono_adc_l1_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_mono_adc_l1_enum, RT5670_MONO_ADC_MIXER,
	RT5670_MONO_ADC_L1_SRC_SFT, rt5670_mono_adc_l1_src);

static const struct snd_kcontrol_new rt5670_mono_adc_l1_mux =;
/* MX-28 [11] */
static const char * const rt5670_mono_adc_l2_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_mono_adc_l2_enum, RT5670_MONO_ADC_MIXER,
	RT5670_MONO_ADC_L2_SRC_SFT, rt5670_mono_adc_l2_src);

static const struct snd_kcontrol_new rt5670_mono_adc_l2_mux =;

/* MX-28 [9:8] */
static const char * const rt5670_mono_dmic_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_mono_dmic_l_enum, RT5670_MONO_ADC_MIXER,
	RT5670_MONO_DMIC_L_SRC_SFT, rt5670_mono_dmic_src);

static const struct snd_kcontrol_new rt5670_mono_dmic_l_mux =;
/* MX-28 [1:0] */
static SOC_ENUM_SINGLE_DECL(rt5670_mono_dmic_r_enum, RT5670_MONO_ADC_MIXER,
	RT5670_MONO_DMIC_R_SRC_SFT, rt5670_mono_dmic_src);

static const struct snd_kcontrol_new rt5670_mono_dmic_r_mux =;
/* MX-28 [4] */
static const char * const rt5670_mono_adc_r1_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_mono_adc_r1_enum, RT5670_MONO_ADC_MIXER,
	RT5670_MONO_ADC_R1_SRC_SFT, rt5670_mono_adc_r1_src);

static const struct snd_kcontrol_new rt5670_mono_adc_r1_mux =;
/* MX-28 [3] */
static const char * const rt5670_mono_adc_r2_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_mono_adc_r2_enum, RT5670_MONO_ADC_MIXER,
	RT5670_MONO_ADC_R2_SRC_SFT, rt5670_mono_adc_r2_src);

static const struct snd_kcontrol_new rt5670_mono_adc_r2_mux =;

/* MX-2D [3:2] */
static const char * const rt5670_txdp_slot_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_txdp_slot_enum, RT5670_DSP_PATH1,
	RT5670_TXDP_SLOT_SEL_SFT, rt5670_txdp_slot_src);

static const struct snd_kcontrol_new rt5670_txdp_slot_mux =;

/* MX-2F [15] */
static const char * const rt5670_if1_adc2_in_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_if1_adc2_in_enum, RT5670_DIG_INF1_DATA,
	RT5670_IF1_ADC2_IN_SFT, rt5670_if1_adc2_in_src);

static const struct snd_kcontrol_new rt5670_if1_adc2_in_mux =;

/* MX-2F [14:12] */
static const char * const rt5670_if2_adc_in_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_if2_adc_in_enum, RT5670_DIG_INF1_DATA,
	RT5670_IF2_ADC_IN_SFT, rt5670_if2_adc_in_src);

static const struct snd_kcontrol_new rt5670_if2_adc_in_mux =;

/* MX-31 [15] [13] [11] [9] */
static const char * const rt5670_pdm_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_pdm1_l_enum, RT5670_PDM_OUT_CTRL,
	RT5670_PDM1_L_SFT, rt5670_pdm_src);

static const struct snd_kcontrol_new rt5670_pdm1_l_mux =;

static SOC_ENUM_SINGLE_DECL(rt5670_pdm1_r_enum, RT5670_PDM_OUT_CTRL,
	RT5670_PDM1_R_SFT, rt5670_pdm_src);

static const struct snd_kcontrol_new rt5670_pdm1_r_mux =;

static SOC_ENUM_SINGLE_DECL(rt5670_pdm2_l_enum, RT5670_PDM_OUT_CTRL,
	RT5670_PDM2_L_SFT, rt5670_pdm_src);

static const struct snd_kcontrol_new rt5670_pdm2_l_mux =;

static SOC_ENUM_SINGLE_DECL(rt5670_pdm2_r_enum, RT5670_PDM_OUT_CTRL,
	RT5670_PDM2_R_SFT, rt5670_pdm_src);

static const struct snd_kcontrol_new rt5670_pdm2_r_mux =;

/* MX-FA [12] */
static const char * const rt5670_if1_adc1_in1_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_if1_adc1_in1_enum, RT5670_DIG_MISC,
	RT5670_IF1_ADC1_IN1_SFT, rt5670_if1_adc1_in1_src);

static const struct snd_kcontrol_new rt5670_if1_adc1_in1_mux =;

/* MX-FA [11] */
static const char * const rt5670_if1_adc1_in2_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_if1_adc1_in2_enum, RT5670_DIG_MISC,
	RT5670_IF1_ADC1_IN2_SFT, rt5670_if1_adc1_in2_src);

static const struct snd_kcontrol_new rt5670_if1_adc1_in2_mux =;

/* MX-FA [10] */
static const char * const rt5670_if1_adc2_in1_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_if1_adc2_in1_enum, RT5670_DIG_MISC,
	RT5670_IF1_ADC2_IN1_SFT, rt5670_if1_adc2_in1_src);

static const struct snd_kcontrol_new rt5670_if1_adc2_in1_mux =;

/* MX-9D [9:8] */
static const char * const rt5670_vad_adc_src[] =;

static SOC_ENUM_SINGLE_DECL(rt5670_vad_adc_enum, RT5670_VAD_CTRL4,
	RT5670_VAD_SEL_SFT, rt5670_vad_adc_src);

static const struct snd_kcontrol_new rt5670_vad_adc_mux =;

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

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

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

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

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

static const struct snd_soc_dapm_widget rt5670_dapm_widgets[] =;

static const struct snd_soc_dapm_widget rt5670_specific_dapm_widgets[] =;

static const struct snd_soc_dapm_widget rt5672_specific_dapm_widgets[] =;

static const struct snd_soc_dapm_route rt5670_dapm_routes[] =;

static const struct snd_soc_dapm_route rt5670_specific_dapm_routes[] =;

static const struct snd_soc_dapm_route rt5672_specific_dapm_routes[] =;

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

static int rt5670_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{}

static int rt5670_set_codec_sysclk(struct snd_soc_component *component, int clk_id,
				   int source, unsigned int freq, int dir)
{}

static int rt5670_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
			unsigned int freq_in, unsigned int freq_out)
{}

static int rt5670_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
			unsigned int rx_mask, int slots, int slot_width)
{}

static int rt5670_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
{}

static int rt5670_set_bias_level(struct snd_soc_component *component,
			enum snd_soc_bias_level level)
{}

static int rt5670_probe(struct snd_soc_component *component)
{}

static void rt5670_remove(struct snd_soc_component *component)
{}

#ifdef CONFIG_PM
static int rt5670_suspend(struct snd_soc_component *component)
{}

static int rt5670_resume(struct snd_soc_component *component)
{}
#else
#define rt5670_suspend
#define rt5670_resume
#endif

#define RT5670_STEREO_RATES
#define RT5670_FORMATS

static const struct snd_soc_dai_ops rt5670_aif_dai_ops =;

static struct snd_soc_dai_driver rt5670_dai[] =;

static const struct snd_soc_component_driver soc_component_dev_rt5670 =;

static const struct regmap_config rt5670_regmap =;

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

#ifdef CONFIG_ACPI
static const struct acpi_device_id rt5670_acpi_match[] =;
MODULE_DEVICE_TABLE(acpi, rt5670_acpi_match);
#endif

static int rt5670_quirk_cb(const struct dmi_system_id *id)
{}

static const struct dmi_system_id dmi_platform_intel_quirks[] =;

const char *rt5670_components(void)
{}
EXPORT_SYMBOL_GPL();

static int rt5670_i2c_probe(struct i2c_client *i2c)
{}

static void rt5670_i2c_remove(struct i2c_client *i2c)
{}

static struct i2c_driver rt5670_i2c_driver =;

module_i2c_driver();

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