#include <linux/module.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/input.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/log2.h>
#include <sound/jack.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/tlv.h>
#define SUN8I_SYSCLK_CTL …
#define SUN8I_SYSCLK_CTL_AIF1CLK_ENA …
#define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL …
#define SUN8I_SYSCLK_CTL_AIF2CLK_ENA …
#define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL …
#define SUN8I_SYSCLK_CTL_SYSCLK_ENA …
#define SUN8I_SYSCLK_CTL_SYSCLK_SRC …
#define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK …
#define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF2CLK …
#define SUN8I_MOD_CLK_ENA …
#define SUN8I_MOD_CLK_ENA_AIF1 …
#define SUN8I_MOD_CLK_ENA_AIF2 …
#define SUN8I_MOD_CLK_ENA_AIF3 …
#define SUN8I_MOD_CLK_ENA_ADC …
#define SUN8I_MOD_CLK_ENA_DAC …
#define SUN8I_MOD_RST_CTL …
#define SUN8I_MOD_RST_CTL_AIF1 …
#define SUN8I_MOD_RST_CTL_AIF2 …
#define SUN8I_MOD_RST_CTL_AIF3 …
#define SUN8I_MOD_RST_CTL_ADC …
#define SUN8I_MOD_RST_CTL_DAC …
#define SUN8I_SYS_SR_CTRL …
#define SUN8I_SYS_SR_CTRL_AIF1_FS …
#define SUN8I_SYS_SR_CTRL_AIF2_FS …
#define SUN8I_AIF_CLK_CTRL(n) …
#define SUN8I_AIF_CLK_CTRL_MSTR_MOD …
#define SUN8I_AIF_CLK_CTRL_CLK_INV …
#define SUN8I_AIF_CLK_CTRL_BCLK_DIV …
#define SUN8I_AIF_CLK_CTRL_LRCK_DIV …
#define SUN8I_AIF_CLK_CTRL_WORD_SIZ …
#define SUN8I_AIF_CLK_CTRL_DATA_FMT …
#define SUN8I_AIF1_ADCDAT_CTRL …
#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA …
#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA …
#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC …
#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC …
#define SUN8I_AIF1_DACDAT_CTRL …
#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA …
#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA …
#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_SRC …
#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_SRC …
#define SUN8I_AIF1_MXR_SRC …
#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L …
#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL …
#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL …
#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR …
#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R …
#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR …
#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR …
#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL …
#define SUN8I_AIF1_VOL_CTRL1 …
#define SUN8I_AIF1_VOL_CTRL1_AD0L_VOL …
#define SUN8I_AIF1_VOL_CTRL1_AD0R_VOL …
#define SUN8I_AIF1_VOL_CTRL3 …
#define SUN8I_AIF1_VOL_CTRL3_DA0L_VOL …
#define SUN8I_AIF1_VOL_CTRL3_DA0R_VOL …
#define SUN8I_AIF2_ADCDAT_CTRL …
#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_ENA …
#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_ENA …
#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_SRC …
#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_SRC …
#define SUN8I_AIF2_DACDAT_CTRL …
#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_ENA …
#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_ENA …
#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_SRC …
#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_SRC …
#define SUN8I_AIF2_MXR_SRC …
#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA0L …
#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA1L …
#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF2DACR …
#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_ADCL …
#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA0R …
#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA1R …
#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF2DACL …
#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_ADCR …
#define SUN8I_AIF2_VOL_CTRL1 …
#define SUN8I_AIF2_VOL_CTRL1_ADCL_VOL …
#define SUN8I_AIF2_VOL_CTRL1_ADCR_VOL …
#define SUN8I_AIF2_VOL_CTRL2 …
#define SUN8I_AIF2_VOL_CTRL2_DACL_VOL …
#define SUN8I_AIF2_VOL_CTRL2_DACR_VOL …
#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF1 …
#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF2 …
#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF1CLK …
#define SUN8I_AIF3_PATH_CTRL …
#define SUN8I_AIF3_PATH_CTRL_AIF3_ADC_SRC …
#define SUN8I_AIF3_PATH_CTRL_AIF2_DAC_SRC …
#define SUN8I_AIF3_PATH_CTRL_AIF3_PINS_TRI …
#define SUN8I_ADC_DIG_CTRL …
#define SUN8I_ADC_DIG_CTRL_ENAD …
#define SUN8I_ADC_DIG_CTRL_ADOUT_DTS …
#define SUN8I_ADC_DIG_CTRL_ADOUT_DLY …
#define SUN8I_ADC_VOL_CTRL …
#define SUN8I_ADC_VOL_CTRL_ADCL_VOL …
#define SUN8I_ADC_VOL_CTRL_ADCR_VOL …
#define SUN8I_HMIC_CTRL1 …
#define SUN8I_HMIC_CTRL1_HMIC_M …
#define SUN8I_HMIC_CTRL1_HMIC_N …
#define SUN8I_HMIC_CTRL1_MDATA_THRESHOLD_DB …
#define SUN8I_HMIC_CTRL1_JACK_OUT_IRQ_EN …
#define SUN8I_HMIC_CTRL1_JACK_IN_IRQ_EN …
#define SUN8I_HMIC_CTRL1_HMIC_DATA_IRQ_EN …
#define SUN8I_HMIC_CTRL2 …
#define SUN8I_HMIC_CTRL2_HMIC_SAMPLE …
#define SUN8I_HMIC_CTRL2_HMIC_MDATA_THRESHOLD …
#define SUN8I_HMIC_CTRL2_HMIC_SF …
#define SUN8I_HMIC_STS …
#define SUN8I_HMIC_STS_MDATA_DISCARD …
#define SUN8I_HMIC_STS_HMIC_DATA …
#define SUN8I_HMIC_STS_JACK_OUT_IRQ_ST …
#define SUN8I_HMIC_STS_JACK_IN_IRQ_ST …
#define SUN8I_HMIC_STS_HMIC_DATA_IRQ_ST …
#define SUN8I_DAC_DIG_CTRL …
#define SUN8I_DAC_DIG_CTRL_ENDA …
#define SUN8I_DAC_VOL_CTRL …
#define SUN8I_DAC_VOL_CTRL_DACL_VOL …
#define SUN8I_DAC_VOL_CTRL_DACR_VOL …
#define SUN8I_DAC_MXR_SRC …
#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L …
#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L …
#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL …
#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL …
#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R …
#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R …
#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR …
#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR …
#define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK …
#define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK …
#define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK …
#define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK …
#define SUN8I_AIF_CLK_CTRL_CLK_INV_MASK …
#define SUN8I_AIF_CLK_CTRL_BCLK_DIV_MASK …
#define SUN8I_AIF_CLK_CTRL_LRCK_DIV_MASK …
#define SUN8I_AIF_CLK_CTRL_WORD_SIZ_MASK …
#define SUN8I_AIF_CLK_CTRL_DATA_FMT_MASK …
#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_MASK …
#define SUN8I_HMIC_CTRL1_HMIC_M_MASK …
#define SUN8I_HMIC_CTRL1_HMIC_N_MASK …
#define SUN8I_HMIC_CTRL1_MDATA_THRESHOLD_DB_MASK …
#define SUN8I_HMIC_CTRL2_HMIC_SAMPLE_MASK …
#define SUN8I_HMIC_CTRL2_HMIC_SF_MASK …
#define SUN8I_HMIC_STS_HMIC_DATA_MASK …
#define SUN8I_CODEC_BUTTONS …
#define SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE …
#define SUN8I_CODEC_PCM_FORMATS …
#define SUN8I_CODEC_PCM_RATES …
enum { … };
struct sun8i_codec_aif { … };
struct sun8i_codec_quirks { … };
enum { … };
struct sun8i_codec { … };
static struct snd_soc_dai_driver sun8i_codec_dais[];
static int sun8i_codec_runtime_resume(struct device *dev)
{ … }
static int sun8i_codec_runtime_suspend(struct device *dev)
{ … }
static int sun8i_codec_get_hw_rate(unsigned int sample_rate)
{ … }
static int sun8i_codec_update_sample_rate(struct sun8i_codec *scodec)
{ … }
static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{ … }
static int sun8i_codec_set_tdm_slot(struct snd_soc_dai *dai,
unsigned int tx_mask, unsigned int rx_mask,
int slots, int slot_width)
{ … }
static const unsigned int sun8i_codec_rates[] = …;
static const struct snd_pcm_hw_constraint_list sun8i_codec_all_rates = …;
static const struct snd_pcm_hw_constraint_list sun8i_codec_22M_rates = …;
static const struct snd_pcm_hw_constraint_list sun8i_codec_24M_rates = …;
static int sun8i_codec_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{ … }
struct sun8i_codec_clk_div { … };
static const struct sun8i_codec_clk_div sun8i_codec_bclk_div[] = …;
static int sun8i_codec_get_bclk_div(unsigned int sysclk_rate,
unsigned int lrck_div_order,
unsigned int sample_rate)
{ … }
static int sun8i_codec_get_lrck_div_order(unsigned int slots,
unsigned int slot_width)
{ … }
static unsigned int sun8i_codec_get_sysclk_rate(unsigned int sample_rate)
{ … }
static int sun8i_codec_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{ … }
static int sun8i_codec_hw_free(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{ … }
static const struct snd_soc_dai_ops sun8i_codec_dai_ops = …;
static struct snd_soc_dai_driver sun8i_codec_dais[] = …;
static const DECLARE_TLV_DB_SCALE(sun8i_codec_vol_scale, -12000, 75, 1);
static const struct snd_kcontrol_new sun8i_codec_controls[] = …;
static int sun8i_codec_aif_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{ … }
static const char *const sun8i_aif_stereo_mux_enum_values[] = …;
static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_ad0_stereo_mux_enum,
SUN8I_AIF1_ADCDAT_CTRL,
SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC,
SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC,
sun8i_aif_stereo_mux_enum_values);
static const struct snd_kcontrol_new sun8i_aif1_ad0_stereo_mux_control = …;
static SOC_ENUM_DOUBLE_DECL(sun8i_aif2_adc_stereo_mux_enum,
SUN8I_AIF2_ADCDAT_CTRL,
SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_SRC,
SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_SRC,
sun8i_aif_stereo_mux_enum_values);
static const struct snd_kcontrol_new sun8i_aif2_adc_stereo_mux_control = …;
static const char *const sun8i_aif3_adc_mux_enum_values[] = …;
static SOC_ENUM_SINGLE_DECL(sun8i_aif3_adc_mux_enum,
SUN8I_AIF3_PATH_CTRL,
SUN8I_AIF3_PATH_CTRL_AIF3_ADC_SRC,
sun8i_aif3_adc_mux_enum_values);
static const struct snd_kcontrol_new sun8i_aif3_adc_mux_control = …;
static const struct snd_kcontrol_new sun8i_aif1_ad0_mixer_controls[] = …;
static const struct snd_kcontrol_new sun8i_aif2_adc_mixer_controls[] = …;
static const char *const sun8i_aif2_dac_mux_enum_values[] = …;
static SOC_ENUM_SINGLE_DECL(sun8i_aif2_dac_mux_enum,
SUN8I_AIF3_PATH_CTRL,
SUN8I_AIF3_PATH_CTRL_AIF2_DAC_SRC,
sun8i_aif2_dac_mux_enum_values);
static const struct snd_kcontrol_new sun8i_aif2_dac_mux_control = …;
static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_da0_stereo_mux_enum,
SUN8I_AIF1_DACDAT_CTRL,
SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_SRC,
SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_SRC,
sun8i_aif_stereo_mux_enum_values);
static const struct snd_kcontrol_new sun8i_aif1_da0_stereo_mux_control = …;
static SOC_ENUM_DOUBLE_DECL(sun8i_aif2_dac_stereo_mux_enum,
SUN8I_AIF2_DACDAT_CTRL,
SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_SRC,
SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_SRC,
sun8i_aif_stereo_mux_enum_values);
static const struct snd_kcontrol_new sun8i_aif2_dac_stereo_mux_control = …;
static const struct snd_kcontrol_new sun8i_dac_mixer_controls[] = …;
static const struct snd_soc_dapm_widget sun8i_codec_dapm_widgets[] = …;
static const struct snd_soc_dapm_route sun8i_codec_dapm_routes[] = …;
static const struct snd_soc_dapm_widget sun8i_codec_legacy_widgets[] = …;
static const struct snd_soc_dapm_route sun8i_codec_legacy_routes[] = …;
static int sun8i_codec_component_probe(struct snd_soc_component *component)
{ … }
static void sun8i_codec_set_hmic_bias(struct sun8i_codec *scodec, bool enable)
{ … }
static void sun8i_codec_jack_work(struct work_struct *work)
{ … }
static irqreturn_t sun8i_codec_jack_irq(int irq, void *dev_id)
{ … }
static int sun8i_codec_enable_jack_detect(struct snd_soc_component *component,
struct snd_soc_jack *jack, void *data)
{ … }
static void sun8i_codec_disable_jack_detect(struct snd_soc_component *component)
{ … }
static int sun8i_codec_component_set_jack(struct snd_soc_component *component,
struct snd_soc_jack *jack, void *data)
{ … }
static const struct snd_soc_component_driver sun8i_soc_component = …;
static bool sun8i_codec_volatile_reg(struct device *dev, unsigned int reg)
{ … }
static const struct regmap_config sun8i_codec_regmap_config = …;
static int sun8i_codec_probe(struct platform_device *pdev)
{ … }
static void sun8i_codec_remove(struct platform_device *pdev)
{ … }
static const struct sun8i_codec_quirks sun8i_a33_quirks = …;
static const struct sun8i_codec_quirks sun50i_a64_quirks = …;
static const struct of_device_id sun8i_codec_of_match[] = …;
MODULE_DEVICE_TABLE(of, sun8i_codec_of_match);
static const struct dev_pm_ops sun8i_codec_pm_ops = …;
static struct platform_driver sun8i_codec_driver = …;
module_platform_driver(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_AUTHOR(…) …;
MODULE_LICENSE(…) …;
MODULE_ALIAS(…) …;