linux/sound/soc/codecs/tlv320aic32x4.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * linux/sound/soc/codecs/tlv320aic32x4.c
 *
 * Copyright 2011 Vista Silicon S.L.
 *
 * Author: Javier Martin <[email protected]>
 *
 * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
 */

#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/of_clk.h>
#include <linux/regulator/consumer.h>

#include <sound/tlv320aic32x4.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 "tlv320aic32x4.h"

struct aic32x4_priv {};

static int aic32x4_reset_adc(struct snd_soc_dapm_widget *w,
			     struct snd_kcontrol *kcontrol, int event)
{
	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
	u32 adc_reg;

	/*
	 * Workaround: the datasheet does not mention a required programming
	 * sequence but experiments show the ADC needs to be reset after each
	 * capture to avoid audible artifacts.
	 */
	switch (event) {
	case SND_SOC_DAPM_POST_PMD:
		adc_reg = snd_soc_component_read(component, AIC32X4_ADCSETUP);
		snd_soc_component_write(component, AIC32X4_ADCSETUP, adc_reg |
					AIC32X4_LADC_EN | AIC32X4_RADC_EN);
		snd_soc_component_write(component, AIC32X4_ADCSETUP, adc_reg);
		break;
	}
	return 0;
};

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


static int aic32x4_get_mfp1_gpio(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
	u8 val;

	val = snd_soc_component_read(component, AIC32X4_DINCTL);

	ucontrol->value.integer.value[0] = (val & 0x01);

	return 0;
};

static int aic32x4_set_mfp2_gpio(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
	u8 val;
	u8 gpio_check;

	val = snd_soc_component_read(component, AIC32X4_DOUTCTL);
	gpio_check = (val & AIC32X4_MFP_GPIO_ENABLED);
	if (gpio_check != AIC32X4_MFP_GPIO_ENABLED) {
		printk(KERN_ERR "%s: MFP2 is not configure as a GPIO output\n",
			__func__);
		return -EINVAL;
	}

	if (ucontrol->value.integer.value[0] == (val & AIC32X4_MFP2_GPIO_OUT_HIGH))
		return 0;

	if (ucontrol->value.integer.value[0])
		val |= ucontrol->value.integer.value[0];
	else
		val &= ~AIC32X4_MFP2_GPIO_OUT_HIGH;

	snd_soc_component_write(component, AIC32X4_DOUTCTL, val);

	return 0;
};

static int aic32x4_get_mfp3_gpio(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
	u8 val;

	val = snd_soc_component_read(component, AIC32X4_SCLKCTL);

	ucontrol->value.integer.value[0] = (val & 0x01);

	return 0;
};

static int aic32x4_set_mfp4_gpio(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
	u8 val;
	u8 gpio_check;

	val = snd_soc_component_read(component, AIC32X4_MISOCTL);
	gpio_check = (val & AIC32X4_MFP_GPIO_ENABLED);
	if (gpio_check != AIC32X4_MFP_GPIO_ENABLED) {
		printk(KERN_ERR "%s: MFP4 is not configure as a GPIO output\n",
			__func__);
		return -EINVAL;
	}

	if (ucontrol->value.integer.value[0] == (val & AIC32X4_MFP5_GPIO_OUT_HIGH))
		return 0;

	if (ucontrol->value.integer.value[0])
		val |= ucontrol->value.integer.value[0];
	else
		val &= ~AIC32X4_MFP5_GPIO_OUT_HIGH;

	snd_soc_component_write(component, AIC32X4_MISOCTL, val);

	return 0;
};

static int aic32x4_get_mfp5_gpio(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
	u8 val;

	val = snd_soc_component_read(component, AIC32X4_GPIOCTL);
	ucontrol->value.integer.value[0] = ((val & 0x2) >> 1);

	return 0;
};

static int aic32x4_set_mfp5_gpio(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
	u8 val;
	u8 gpio_check;

	val = snd_soc_component_read(component, AIC32X4_GPIOCTL);
	gpio_check = (val & AIC32X4_MFP5_GPIO_OUTPUT);
	if (gpio_check != AIC32X4_MFP5_GPIO_OUTPUT) {
		printk(KERN_ERR "%s: MFP5 is not configure as a GPIO output\n",
			__func__);
		return -EINVAL;
	}

	if (ucontrol->value.integer.value[0] == (val & 0x1))
		return 0;

	if (ucontrol->value.integer.value[0])
		val |= ucontrol->value.integer.value[0];
	else
		val &= 0xfe;

	snd_soc_component_write(component, AIC32X4_GPIOCTL, val);

	return 0;
};

static const struct snd_kcontrol_new aic32x4_mfp1[] =;

static const struct snd_kcontrol_new aic32x4_mfp2[] =;

static const struct snd_kcontrol_new aic32x4_mfp3[] =;

static const struct snd_kcontrol_new aic32x4_mfp4[] =;

static const struct snd_kcontrol_new aic32x4_mfp5[] =;

/* 0dB min, 0.5dB steps */
static DECLARE_TLV_DB_SCALE(tlv_step_0_5, 0, 50, 0);
/* -63.5dB min, 0.5dB steps */
static DECLARE_TLV_DB_SCALE(tlv_pcm, -6350, 50, 0);
/* -6dB min, 1dB steps */
static DECLARE_TLV_DB_SCALE(tlv_driver_gain, -600, 100, 0);
/* -12dB min, 0.5dB steps */
static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0);
/* -6dB min, 1dB steps */
static DECLARE_TLV_DB_SCALE(tlv_tas_driver_gain, -5850, 50, 0);
static DECLARE_TLV_DB_SCALE(tlv_amp_vol, 0, 600, 1);

static const char * const lo_cm_text[] =;

static SOC_ENUM_SINGLE_DECL(lo_cm_enum, AIC32X4_CMMODE, 3, lo_cm_text);

static const char * const ptm_text[] =;

static SOC_ENUM_SINGLE_DECL(l_ptm_enum, AIC32X4_LPLAYBACK, 2, ptm_text);
static SOC_ENUM_SINGLE_DECL(r_ptm_enum, AIC32X4_RPLAYBACK, 2, ptm_text);

static const struct snd_kcontrol_new aic32x4_snd_controls[] =;

static const struct snd_kcontrol_new hpl_output_mixer_controls[] =;

static const struct snd_kcontrol_new hpr_output_mixer_controls[] =;

static const struct snd_kcontrol_new lol_output_mixer_controls[] =;

static const struct snd_kcontrol_new lor_output_mixer_controls[] =;

static const char * const resistor_text[] =;

/* Left mixer pins */
static SOC_ENUM_SINGLE_DECL(in1l_lpga_p_enum, AIC32X4_LMICPGAPIN, 6, resistor_text);
static SOC_ENUM_SINGLE_DECL(in2l_lpga_p_enum, AIC32X4_LMICPGAPIN, 4, resistor_text);
static SOC_ENUM_SINGLE_DECL(in3l_lpga_p_enum, AIC32X4_LMICPGAPIN, 2, resistor_text);
static SOC_ENUM_SINGLE_DECL(in1r_lpga_p_enum, AIC32X4_LMICPGAPIN, 0, resistor_text);

static SOC_ENUM_SINGLE_DECL(cml_lpga_n_enum, AIC32X4_LMICPGANIN, 6, resistor_text);
static SOC_ENUM_SINGLE_DECL(in2r_lpga_n_enum, AIC32X4_LMICPGANIN, 4, resistor_text);
static SOC_ENUM_SINGLE_DECL(in3r_lpga_n_enum, AIC32X4_LMICPGANIN, 2, resistor_text);

static const struct snd_kcontrol_new in1l_to_lmixer_controls[] =;
static const struct snd_kcontrol_new in2l_to_lmixer_controls[] =;
static const struct snd_kcontrol_new in3l_to_lmixer_controls[] =;
static const struct snd_kcontrol_new in1r_to_lmixer_controls[] =;
static const struct snd_kcontrol_new cml_to_lmixer_controls[] =;
static const struct snd_kcontrol_new in2r_to_lmixer_controls[] =;
static const struct snd_kcontrol_new in3r_to_lmixer_controls[] =;

/*	Right mixer pins */
static SOC_ENUM_SINGLE_DECL(in1r_rpga_p_enum, AIC32X4_RMICPGAPIN, 6, resistor_text);
static SOC_ENUM_SINGLE_DECL(in2r_rpga_p_enum, AIC32X4_RMICPGAPIN, 4, resistor_text);
static SOC_ENUM_SINGLE_DECL(in3r_rpga_p_enum, AIC32X4_RMICPGAPIN, 2, resistor_text);
static SOC_ENUM_SINGLE_DECL(in2l_rpga_p_enum, AIC32X4_RMICPGAPIN, 0, resistor_text);
static SOC_ENUM_SINGLE_DECL(cmr_rpga_n_enum, AIC32X4_RMICPGANIN, 6, resistor_text);
static SOC_ENUM_SINGLE_DECL(in1l_rpga_n_enum, AIC32X4_RMICPGANIN, 4, resistor_text);
static SOC_ENUM_SINGLE_DECL(in3l_rpga_n_enum, AIC32X4_RMICPGANIN, 2, resistor_text);

static const struct snd_kcontrol_new in1r_to_rmixer_controls[] =;
static const struct snd_kcontrol_new in2r_to_rmixer_controls[] =;
static const struct snd_kcontrol_new in3r_to_rmixer_controls[] =;
static const struct snd_kcontrol_new in2l_to_rmixer_controls[] =;
static const struct snd_kcontrol_new cmr_to_rmixer_controls[] =;
static const struct snd_kcontrol_new in1l_to_rmixer_controls[] =;
static const struct snd_kcontrol_new in3l_to_rmixer_controls[] =;

static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] =;

static const struct snd_soc_dapm_route aic32x4_dapm_routes[] =;

static const struct regmap_range_cfg aic32x4_regmap_pages[] =;

const struct regmap_config aic32x4_regmap_config =;
EXPORT_SYMBOL();

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

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

static int aic32x4_set_aosr(struct snd_soc_component *component, u8 aosr)
{}

static int aic32x4_set_dosr(struct snd_soc_component *component, u16 dosr)
{}

static int aic32x4_set_processing_blocks(struct snd_soc_component *component,
						u8 r_block, u8 p_block)
{}

static int aic32x4_setup_clocks(struct snd_soc_component *component,
				unsigned int sample_rate, unsigned int channels,
				unsigned int bit_depth)
{}

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

static int aic32x4_mute(struct snd_soc_dai *dai, int mute, int direction)
{}

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

#define AIC32X4_RATES
#define AIC32X4_FORMATS

static const struct snd_soc_dai_ops aic32x4_ops =;

static struct snd_soc_dai_driver aic32x4_dai =;

static void aic32x4_setup_gpios(struct snd_soc_component *component)
{}

static int aic32x4_component_probe(struct snd_soc_component *component)
{}

static const struct snd_soc_component_driver soc_component_dev_aic32x4 =;

static const struct snd_kcontrol_new aic32x4_tas2505_snd_controls[] =;

static const struct snd_kcontrol_new hp_output_mixer_controls[] =;

static const struct snd_soc_dapm_widget aic32x4_tas2505_dapm_widgets[] =;

static const struct snd_soc_dapm_route aic32x4_tas2505_dapm_routes[] =;

static struct snd_soc_dai_driver aic32x4_tas2505_dai =;

static int aic32x4_tas2505_component_probe(struct snd_soc_component *component)
{}

static const struct snd_soc_component_driver soc_component_dev_aic32x4_tas2505 =;

static int aic32x4_parse_dt(struct aic32x4_priv *aic32x4,
		struct device_node *np)
{}

static void aic32x4_disable_regulators(struct aic32x4_priv *aic32x4)
{}

static int aic32x4_setup_regulators(struct device *dev,
		struct aic32x4_priv *aic32x4)
{}

int aic32x4_probe(struct device *dev, struct regmap *regmap,
		  enum aic32x4_type type)
{}
EXPORT_SYMBOL();

void aic32x4_remove(struct device *dev)
{}
EXPORT_SYMBOL();

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