linux/sound/soc/codecs/ak4619.c

// SPDX-License-Identifier: GPL-2.0
/*
 * ak4619.c -- Asahi Kasei ALSA SoC Audio driver
 *
 * Copyright (C) 2023 Renesas Electronics Corporation
 * Khanh Le <[email protected]>
 *
 * Based on ak4613.c by Kuninori Morimoto
 * Based on da7213.c by Adam Thomson
 * Based on ak4641.c by Harald Welte
 */

#include <linux/clk.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/of_device.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <sound/soc.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/tlv.h>

/*
 * Registers
 */

#define PWR_MGMT
#define AU_IFF1
#define AU_IFF2
#define SYS_CLK
#define MIC_AMP1
#define MIC_AMP2
#define LADC1
#define RADC1
#define LADC2
#define RADC2
#define ADC_DF
#define ADC_AI
#define ADC_MHPF
#define LDAC1
#define RDAC1
#define LDAC2
#define RDAC2
#define DAC_IS
#define DAC_DEMP
#define DAC_MF

/*
 * Bit fields
 */

/* Power Management */
#define PMAD2
#define PMAD1
#define PMDA2
#define PMDA1
#define RSTN

/* Audio_I/F Format */
#define DCF_STEREO_I2S
#define DCF_STEREO_MSB
#define DCF_PCM_SF
#define DCF_PCM_LF
#define DSL_32
#define DCF_MASK
#define DSL_MASK
#define BCKP

/* Audio_I/F Format (Extended) */
#define DIDL_24
#define DIDL_20
#define DIDL_16
#define DIDL_32
#define DODL_24
#define DODL_20
#define DODL_16
#define DIDL_MASK
#define DODL_MASK
#define SLOT

/* System Clock Setting */
#define FS_MASK

/* MIC AMP Gain */
#define MGNL_SHIFT
#define MGNR_SHIFT
#define MGN_MAX

/* ADC Digital Volume */
#define VOLAD_SHIFT
#define VOLAD_MAX

/* ADC Digital Filter Setting */
#define AD1SL_SHIFT
#define AD2SL_SHIFT

/* Analog Input Select */
#define AD1LSEL_SHIFT
#define AD1RSEL_SHIFT
#define AD2LSEL_SHIFT
#define AD2RSEL_SHIFT

/* ADC Mute & HPF Control */
#define ATSPAD_SHIFT
#define AD1MUTE_SHIFT
#define AD2MUTE_SHIFT
#define AD1MUTE_MAX
#define AD2MUTE_MAX
#define AD1MUTE_EN
#define AD2MUTE_EN
#define AD1HPFN_SHIFT
#define AD1HPFN_MAX
#define AD2HPFN_SHIFT
#define AD2HPFN_MAX

/* DAC Digital Volume */
#define VOLDA_SHIFT
#define VOLDA_MAX

/* DAC Input Select Setting */
#define DAC1SEL_SHIFT
#define DAC2SEL_SHIFT

/* DAC De-Emphasis Setting */
#define DEM1_32000
#define DEM1_44100
#define DEM1_48000
#define DEM1_OFF
#define DEM2_32000
#define DEM2_44100
#define DEM2_48000
#define DEM2_OFF
#define DEM1_MASK
#define DEM2_MASK
#define DEM1_SHIFT
#define DEM2_SHIFT

/* DAC Mute & Filter Setting */
#define DA1MUTE_SHIFT
#define DA1MUTE_MAX
#define DA2MUTE_SHIFT
#define DA2MUTE_MAX
#define DA1MUTE_EN
#define DA2MUTE_EN
#define ATSPDA_SHIFT
#define DA1SL_SHIFT
#define DA2SL_SHIFT

/* Codec private data */
struct ak4619_priv {};

/*
 * DAC Volume
 *
 * max : 0x00 : +12.0 dB
 *	( 0.5 dB step )
 * min : 0xFE : -115.0 dB
 * mute: 0xFF
 */
static const DECLARE_TLV_DB_SCALE(dac_tlv, -11550, 50, 1);

/*
 * MIC Volume
 *
 * max : 0x0B : +27.0 dB
 *	( 3 dB step )
 * min: 0x00 : -6.0 dB
 */
static const DECLARE_TLV_DB_SCALE(mic_tlv, -600, 300, 0);

/*
 * ADC Volume
 *
 * max : 0x00 : +24.0 dB
 *	( 0.5 dB step )
 * min : 0xFE : -103.0 dB
 * mute: 0xFF
 */
static const DECLARE_TLV_DB_SCALE(adc_tlv, -10350, 50, 1);

/* ADC & DAC Volume Level Transition Time select */
static const char * const ak4619_vol_trans_txt[] =;

static SOC_ENUM_SINGLE_DECL(ak4619_adc_vol_trans, ADC_MHPF, ATSPAD_SHIFT, ak4619_vol_trans_txt);
static SOC_ENUM_SINGLE_DECL(ak4619_dac_vol_trans, DAC_MF,   ATSPDA_SHIFT, ak4619_vol_trans_txt);

/* ADC Digital Filter select */
static const char * const ak4619_adc_digi_fil_txt[] =;

static SOC_ENUM_SINGLE_DECL(ak4619_adc_1_digi_fil, ADC_DF, AD1SL_SHIFT, ak4619_adc_digi_fil_txt);
static SOC_ENUM_SINGLE_DECL(ak4619_adc_2_digi_fil, ADC_DF, AD2SL_SHIFT, ak4619_adc_digi_fil_txt);

/* DAC De-Emphasis Filter select */
static const char * const ak4619_dac_de_emp_txt[] =;

static SOC_ENUM_SINGLE_DECL(ak4619_dac_1_de_emp, DAC_DEMP, DEM1_SHIFT, ak4619_dac_de_emp_txt);
static SOC_ENUM_SINGLE_DECL(ak4619_dac_2_de_emp, DAC_DEMP, DEM2_SHIFT, ak4619_dac_de_emp_txt);

/* DAC Digital Filter select */
static const char * const ak4619_dac_digi_fil_txt[] =;

static SOC_ENUM_SINGLE_DECL(ak4619_dac_1_digi_fil, DAC_MF, DA1SL_SHIFT, ak4619_dac_digi_fil_txt);
static SOC_ENUM_SINGLE_DECL(ak4619_dac_2_digi_fil, DAC_MF, DA2SL_SHIFT, ak4619_dac_digi_fil_txt);

/*
 * Control functions
 */

static void ak4619_set_deemph(struct snd_soc_component *component)
{}

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

static int ak4619_get_deemph(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
	struct ak4619_priv *ak4619 = snd_soc_component_get_drvdata(component);

	ucontrol->value.integer.value[0] = ak4619->deemph_en;

	return 0;
};

/*
 * KControls
 */
static const struct snd_kcontrol_new ak4619_snd_controls[] =;

/*
 * DAPM
 */

/* Analog input mode */
static const char * const ak4619_analog_in_txt[] =;

static SOC_ENUM_SINGLE_DECL(ak4619_ad_1_left_in,  ADC_AI, AD1LSEL_SHIFT, ak4619_analog_in_txt);
static SOC_ENUM_SINGLE_DECL(ak4619_ad_1_right_in, ADC_AI, AD1RSEL_SHIFT, ak4619_analog_in_txt);
static SOC_ENUM_SINGLE_DECL(ak4619_ad_2_left_in,  ADC_AI, AD2LSEL_SHIFT, ak4619_analog_in_txt);
static SOC_ENUM_SINGLE_DECL(ak4619_ad_2_right_in, ADC_AI, AD2RSEL_SHIFT, ak4619_analog_in_txt);

static const struct snd_kcontrol_new ak4619_ad_1_left_in_mux =;
static const struct snd_kcontrol_new ak4619_ad_1_right_in_mux =;
static const struct snd_kcontrol_new ak4619_ad_2_left_in_mux =;
static const struct snd_kcontrol_new ak4619_ad_2_right_in_mux =;

/* DAC source mux */
static const char * const ak4619_dac_in_txt[] =;

static SOC_ENUM_SINGLE_DECL(ak4619_dac_1_in, DAC_IS, DAC1SEL_SHIFT, ak4619_dac_in_txt);
static SOC_ENUM_SINGLE_DECL(ak4619_dac_2_in, DAC_IS, DAC2SEL_SHIFT, ak4619_dac_in_txt);

static const struct snd_kcontrol_new ak4619_dac_1_in_mux =;
static const struct snd_kcontrol_new ak4619_dac_2_in_mux =;

static const struct snd_soc_dapm_widget ak4619_dapm_widgets[] =;

static const struct snd_soc_dapm_route ak4619_intercon[] =;

static const struct reg_default ak4619_reg_defaults[] =;

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

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

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

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

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

static void ak4619_hw_constraints(struct ak4619_priv *ak4619,
				  struct snd_pcm_runtime *runtime)
{
	struct snd_pcm_hw_constraint_list *constraint = &ak4619->constraint;
	int ak4619_rate_mask = 0;
	unsigned int fs;
	int i;
	static const unsigned int ak4619_sr[] = {
		  8000,
		 11025,
		 12000,
		 16000,
		 22050,
		 24000,
		 32000,
		 44100,
		 48000,
		 64000,
		 88200,
		 96000,
		176400,
		192000,
	};

	/*
	 *	[8kHz - 48kHz]		: 256fs, 384fs or 512fs
	 *	[64kHz - 96kHz]		: 256fs
	 *	[176.4kHz, 192kHz]	: 128fs
	 */

	for (i = 0; i < ARRAY_SIZE(ak4619_sr); i++) {
		fs = ak4619->sysclk / ak4619_sr[i];

		switch (fs) {
		case 512:
		case 384:
		case 256:
			ak4619_rate_mask |= (1 << i);
			break;
		case 128:
			switch (i) {
			case (ARRAY_SIZE(ak4619_sr) - 1):
			case (ARRAY_SIZE(ak4619_sr) - 2):
				ak4619_rate_mask |= (1 << i);
				break;
			default:
				break;
			}
			break;
		default:
			break;
		}
	}

	constraint->list	= ak4619_sr;
	constraint->mask	= ak4619_rate_mask;
	constraint->count	= ARRAY_SIZE(ak4619_sr);

	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, constraint);
};

#define PLAYBACK_MODE
#define CAPTURE_MODE

static int ak4619_dai_startup(struct snd_pcm_substream *substream,
			      struct snd_soc_dai *dai)
{}

static u64 ak4619_dai_formats[] =;

static const struct snd_soc_dai_ops ak4619_dai_ops =;

static const struct snd_soc_component_driver soc_component_dev_ak4619 =;

static const struct regmap_config ak4619_regmap_cfg =;

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

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

#define AK4619_RATES

#define AK4619_DAC_FORMATS

#define AK4619_ADC_FORMATS

static struct snd_soc_dai_driver ak4619_dai =;

static int ak4619_i2c_probe(struct i2c_client *i2c)
{}

static struct i2c_driver ak4619_i2c_driver =;
module_i2c_driver();

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