162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * ADAV80X Audio Codec driver supporting ADAV801, ADAV803 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2011 Analog Devices Inc. 662306a36Sopenharmony_ci * Author: Yi Li <yi.li@analog.com> 762306a36Sopenharmony_ci * Author: Lars-Peter Clausen <lars@metafoo.de> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/regmap.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <sound/pcm.h> 1662306a36Sopenharmony_ci#include <sound/pcm_params.h> 1762306a36Sopenharmony_ci#include <sound/soc.h> 1862306a36Sopenharmony_ci#include <sound/tlv.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include "adav80x.h" 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define ADAV80X_PLAYBACK_CTRL 0x04 2362306a36Sopenharmony_ci#define ADAV80X_AUX_IN_CTRL 0x05 2462306a36Sopenharmony_ci#define ADAV80X_REC_CTRL 0x06 2562306a36Sopenharmony_ci#define ADAV80X_AUX_OUT_CTRL 0x07 2662306a36Sopenharmony_ci#define ADAV80X_DPATH_CTRL1 0x62 2762306a36Sopenharmony_ci#define ADAV80X_DPATH_CTRL2 0x63 2862306a36Sopenharmony_ci#define ADAV80X_DAC_CTRL1 0x64 2962306a36Sopenharmony_ci#define ADAV80X_DAC_CTRL2 0x65 3062306a36Sopenharmony_ci#define ADAV80X_DAC_CTRL3 0x66 3162306a36Sopenharmony_ci#define ADAV80X_DAC_L_VOL 0x68 3262306a36Sopenharmony_ci#define ADAV80X_DAC_R_VOL 0x69 3362306a36Sopenharmony_ci#define ADAV80X_PGA_L_VOL 0x6c 3462306a36Sopenharmony_ci#define ADAV80X_PGA_R_VOL 0x6d 3562306a36Sopenharmony_ci#define ADAV80X_ADC_CTRL1 0x6e 3662306a36Sopenharmony_ci#define ADAV80X_ADC_CTRL2 0x6f 3762306a36Sopenharmony_ci#define ADAV80X_ADC_L_VOL 0x70 3862306a36Sopenharmony_ci#define ADAV80X_ADC_R_VOL 0x71 3962306a36Sopenharmony_ci#define ADAV80X_PLL_CTRL1 0x74 4062306a36Sopenharmony_ci#define ADAV80X_PLL_CTRL2 0x75 4162306a36Sopenharmony_ci#define ADAV80X_ICLK_CTRL1 0x76 4262306a36Sopenharmony_ci#define ADAV80X_ICLK_CTRL2 0x77 4362306a36Sopenharmony_ci#define ADAV80X_PLL_CLK_SRC 0x78 4462306a36Sopenharmony_ci#define ADAV80X_PLL_OUTE 0x7a 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define ADAV80X_PLL_CLK_SRC_PLL_XIN(pll) 0x00 4762306a36Sopenharmony_ci#define ADAV80X_PLL_CLK_SRC_PLL_MCLKI(pll) (0x40 << (pll)) 4862306a36Sopenharmony_ci#define ADAV80X_PLL_CLK_SRC_PLL_MASK(pll) (0x40 << (pll)) 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#define ADAV80X_ICLK_CTRL1_DAC_SRC(src) ((src) << 5) 5162306a36Sopenharmony_ci#define ADAV80X_ICLK_CTRL1_ADC_SRC(src) ((src) << 2) 5262306a36Sopenharmony_ci#define ADAV80X_ICLK_CTRL1_ICLK2_SRC(src) (src) 5362306a36Sopenharmony_ci#define ADAV80X_ICLK_CTRL2_ICLK1_SRC(src) ((src) << 3) 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#define ADAV80X_PLL_CTRL1_PLLDIV 0x10 5662306a36Sopenharmony_ci#define ADAV80X_PLL_CTRL1_PLLPD(pll) (0x04 << (pll)) 5762306a36Sopenharmony_ci#define ADAV80X_PLL_CTRL1_XTLPD 0x02 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci#define ADAV80X_PLL_CTRL2_FIELD(pll, x) ((x) << ((pll) * 4)) 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci#define ADAV80X_PLL_CTRL2_FS_48(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x00) 6262306a36Sopenharmony_ci#define ADAV80X_PLL_CTRL2_FS_32(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x08) 6362306a36Sopenharmony_ci#define ADAV80X_PLL_CTRL2_FS_44(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x0c) 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci#define ADAV80X_PLL_CTRL2_SEL(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x02) 6662306a36Sopenharmony_ci#define ADAV80X_PLL_CTRL2_DOUB(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x01) 6762306a36Sopenharmony_ci#define ADAV80X_PLL_CTRL2_PLL_MASK(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x0f) 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci#define ADAV80X_ADC_CTRL1_MODULATOR_MASK 0x80 7062306a36Sopenharmony_ci#define ADAV80X_ADC_CTRL1_MODULATOR_128FS 0x00 7162306a36Sopenharmony_ci#define ADAV80X_ADC_CTRL1_MODULATOR_64FS 0x80 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci#define ADAV80X_DAC_CTRL1_PD 0x80 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci#define ADAV80X_DAC_CTRL2_DIV1 0x00 7662306a36Sopenharmony_ci#define ADAV80X_DAC_CTRL2_DIV1_5 0x10 7762306a36Sopenharmony_ci#define ADAV80X_DAC_CTRL2_DIV2 0x20 7862306a36Sopenharmony_ci#define ADAV80X_DAC_CTRL2_DIV3 0x30 7962306a36Sopenharmony_ci#define ADAV80X_DAC_CTRL2_DIV_MASK 0x30 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci#define ADAV80X_DAC_CTRL2_INTERPOL_256FS 0x00 8262306a36Sopenharmony_ci#define ADAV80X_DAC_CTRL2_INTERPOL_128FS 0x40 8362306a36Sopenharmony_ci#define ADAV80X_DAC_CTRL2_INTERPOL_64FS 0x80 8462306a36Sopenharmony_ci#define ADAV80X_DAC_CTRL2_INTERPOL_MASK 0xc0 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci#define ADAV80X_DAC_CTRL2_DEEMPH_NONE 0x00 8762306a36Sopenharmony_ci#define ADAV80X_DAC_CTRL2_DEEMPH_44 0x01 8862306a36Sopenharmony_ci#define ADAV80X_DAC_CTRL2_DEEMPH_32 0x02 8962306a36Sopenharmony_ci#define ADAV80X_DAC_CTRL2_DEEMPH_48 0x03 9062306a36Sopenharmony_ci#define ADAV80X_DAC_CTRL2_DEEMPH_MASK 0x01 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci#define ADAV80X_CAPTURE_MODE_MASTER 0x20 9362306a36Sopenharmony_ci#define ADAV80X_CAPTURE_WORD_LEN24 0x00 9462306a36Sopenharmony_ci#define ADAV80X_CAPTURE_WORD_LEN20 0x04 9562306a36Sopenharmony_ci#define ADAV80X_CAPTRUE_WORD_LEN18 0x08 9662306a36Sopenharmony_ci#define ADAV80X_CAPTURE_WORD_LEN16 0x0c 9762306a36Sopenharmony_ci#define ADAV80X_CAPTURE_WORD_LEN_MASK 0x0c 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci#define ADAV80X_CAPTURE_MODE_LEFT_J 0x00 10062306a36Sopenharmony_ci#define ADAV80X_CAPTURE_MODE_I2S 0x01 10162306a36Sopenharmony_ci#define ADAV80X_CAPTURE_MODE_RIGHT_J 0x03 10262306a36Sopenharmony_ci#define ADAV80X_CAPTURE_MODE_MASK 0x03 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci#define ADAV80X_PLAYBACK_MODE_MASTER 0x10 10562306a36Sopenharmony_ci#define ADAV80X_PLAYBACK_MODE_LEFT_J 0x00 10662306a36Sopenharmony_ci#define ADAV80X_PLAYBACK_MODE_I2S 0x01 10762306a36Sopenharmony_ci#define ADAV80X_PLAYBACK_MODE_RIGHT_J_24 0x04 10862306a36Sopenharmony_ci#define ADAV80X_PLAYBACK_MODE_RIGHT_J_20 0x05 10962306a36Sopenharmony_ci#define ADAV80X_PLAYBACK_MODE_RIGHT_J_18 0x06 11062306a36Sopenharmony_ci#define ADAV80X_PLAYBACK_MODE_RIGHT_J_16 0x07 11162306a36Sopenharmony_ci#define ADAV80X_PLAYBACK_MODE_MASK 0x07 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci#define ADAV80X_PLL_OUTE_SYSCLKPD(x) BIT(2 - (x)) 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistatic const struct reg_default adav80x_reg_defaults[] = { 11662306a36Sopenharmony_ci { ADAV80X_PLAYBACK_CTRL, 0x01 }, 11762306a36Sopenharmony_ci { ADAV80X_AUX_IN_CTRL, 0x01 }, 11862306a36Sopenharmony_ci { ADAV80X_REC_CTRL, 0x02 }, 11962306a36Sopenharmony_ci { ADAV80X_AUX_OUT_CTRL, 0x01 }, 12062306a36Sopenharmony_ci { ADAV80X_DPATH_CTRL1, 0xc0 }, 12162306a36Sopenharmony_ci { ADAV80X_DPATH_CTRL2, 0x11 }, 12262306a36Sopenharmony_ci { ADAV80X_DAC_CTRL1, 0x00 }, 12362306a36Sopenharmony_ci { ADAV80X_DAC_CTRL2, 0x00 }, 12462306a36Sopenharmony_ci { ADAV80X_DAC_CTRL3, 0x00 }, 12562306a36Sopenharmony_ci { ADAV80X_DAC_L_VOL, 0xff }, 12662306a36Sopenharmony_ci { ADAV80X_DAC_R_VOL, 0xff }, 12762306a36Sopenharmony_ci { ADAV80X_PGA_L_VOL, 0x00 }, 12862306a36Sopenharmony_ci { ADAV80X_PGA_R_VOL, 0x00 }, 12962306a36Sopenharmony_ci { ADAV80X_ADC_CTRL1, 0x00 }, 13062306a36Sopenharmony_ci { ADAV80X_ADC_CTRL2, 0x00 }, 13162306a36Sopenharmony_ci { ADAV80X_ADC_L_VOL, 0xff }, 13262306a36Sopenharmony_ci { ADAV80X_ADC_R_VOL, 0xff }, 13362306a36Sopenharmony_ci { ADAV80X_PLL_CTRL1, 0x00 }, 13462306a36Sopenharmony_ci { ADAV80X_PLL_CTRL2, 0x00 }, 13562306a36Sopenharmony_ci { ADAV80X_ICLK_CTRL1, 0x00 }, 13662306a36Sopenharmony_ci { ADAV80X_ICLK_CTRL2, 0x00 }, 13762306a36Sopenharmony_ci { ADAV80X_PLL_CLK_SRC, 0x00 }, 13862306a36Sopenharmony_ci { ADAV80X_PLL_OUTE, 0x00 }, 13962306a36Sopenharmony_ci}; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistruct adav80x { 14262306a36Sopenharmony_ci struct regmap *regmap; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci enum adav80x_clk_src clk_src; 14562306a36Sopenharmony_ci unsigned int sysclk; 14662306a36Sopenharmony_ci enum adav80x_pll_src pll_src; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci unsigned int dai_fmt[2]; 14962306a36Sopenharmony_ci unsigned int rate; 15062306a36Sopenharmony_ci bool deemph; 15162306a36Sopenharmony_ci bool sysclk_pd[3]; 15262306a36Sopenharmony_ci}; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistatic const char *adav80x_mux_text[] = { 15562306a36Sopenharmony_ci "ADC", 15662306a36Sopenharmony_ci "Playback", 15762306a36Sopenharmony_ci "Aux Playback", 15862306a36Sopenharmony_ci}; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic const unsigned int adav80x_mux_values[] = { 16162306a36Sopenharmony_ci 0, 2, 3, 16262306a36Sopenharmony_ci}; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci#define ADAV80X_MUX_ENUM_DECL(name, reg, shift) \ 16562306a36Sopenharmony_ci SOC_VALUE_ENUM_DOUBLE_DECL(name, reg, shift, 7, \ 16662306a36Sopenharmony_ci ARRAY_SIZE(adav80x_mux_text), adav80x_mux_text, \ 16762306a36Sopenharmony_ci adav80x_mux_values) 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_cistatic ADAV80X_MUX_ENUM_DECL(adav80x_aux_capture_enum, ADAV80X_DPATH_CTRL1, 0); 17062306a36Sopenharmony_cistatic ADAV80X_MUX_ENUM_DECL(adav80x_capture_enum, ADAV80X_DPATH_CTRL1, 3); 17162306a36Sopenharmony_cistatic ADAV80X_MUX_ENUM_DECL(adav80x_dac_enum, ADAV80X_DPATH_CTRL2, 3); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_cistatic const struct snd_kcontrol_new adav80x_aux_capture_mux_ctrl = 17462306a36Sopenharmony_ci SOC_DAPM_ENUM("Route", adav80x_aux_capture_enum); 17562306a36Sopenharmony_cistatic const struct snd_kcontrol_new adav80x_capture_mux_ctrl = 17662306a36Sopenharmony_ci SOC_DAPM_ENUM("Route", adav80x_capture_enum); 17762306a36Sopenharmony_cistatic const struct snd_kcontrol_new adav80x_dac_mux_ctrl = 17862306a36Sopenharmony_ci SOC_DAPM_ENUM("Route", adav80x_dac_enum); 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci#define ADAV80X_MUX(name, ctrl) \ 18162306a36Sopenharmony_ci SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, 0, 0, ctrl) 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget adav80x_dapm_widgets[] = { 18462306a36Sopenharmony_ci SND_SOC_DAPM_DAC("DAC", NULL, ADAV80X_DAC_CTRL1, 7, 1), 18562306a36Sopenharmony_ci SND_SOC_DAPM_ADC("ADC", NULL, ADAV80X_ADC_CTRL1, 5, 1), 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci SND_SOC_DAPM_PGA("Right PGA", ADAV80X_ADC_CTRL1, 0, 1, NULL, 0), 18862306a36Sopenharmony_ci SND_SOC_DAPM_PGA("Left PGA", ADAV80X_ADC_CTRL1, 1, 1, NULL, 0), 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("AIFOUT", "HiFi Capture", 0, SND_SOC_NOPM, 0, 0), 19162306a36Sopenharmony_ci SND_SOC_DAPM_AIF_IN("AIFIN", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0), 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("AIFAUXOUT", "Aux Capture", 0, SND_SOC_NOPM, 0, 0), 19462306a36Sopenharmony_ci SND_SOC_DAPM_AIF_IN("AIFAUXIN", "Aux Playback", 0, SND_SOC_NOPM, 0, 0), 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci ADAV80X_MUX("Aux Capture Select", &adav80x_aux_capture_mux_ctrl), 19762306a36Sopenharmony_ci ADAV80X_MUX("Capture Select", &adav80x_capture_mux_ctrl), 19862306a36Sopenharmony_ci ADAV80X_MUX("DAC Select", &adav80x_dac_mux_ctrl), 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("VINR"), 20162306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("VINL"), 20262306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("VOUTR"), 20362306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("VOUTL"), 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("SYSCLK", SND_SOC_NOPM, 0, 0, NULL, 0), 20662306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("PLL1", ADAV80X_PLL_CTRL1, 2, 1, NULL, 0), 20762306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("PLL2", ADAV80X_PLL_CTRL1, 3, 1, NULL, 0), 20862306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("OSC", ADAV80X_PLL_CTRL1, 1, 1, NULL, 0), 20962306a36Sopenharmony_ci}; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistatic int adav80x_dapm_sysclk_check(struct snd_soc_dapm_widget *source, 21262306a36Sopenharmony_ci struct snd_soc_dapm_widget *sink) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); 21562306a36Sopenharmony_ci struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 21662306a36Sopenharmony_ci const char *clk; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci switch (adav80x->clk_src) { 21962306a36Sopenharmony_ci case ADAV80X_CLK_PLL1: 22062306a36Sopenharmony_ci clk = "PLL1"; 22162306a36Sopenharmony_ci break; 22262306a36Sopenharmony_ci case ADAV80X_CLK_PLL2: 22362306a36Sopenharmony_ci clk = "PLL2"; 22462306a36Sopenharmony_ci break; 22562306a36Sopenharmony_ci case ADAV80X_CLK_XTAL: 22662306a36Sopenharmony_ci clk = "OSC"; 22762306a36Sopenharmony_ci break; 22862306a36Sopenharmony_ci default: 22962306a36Sopenharmony_ci return 0; 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci return strcmp(source->name, clk) == 0; 23362306a36Sopenharmony_ci} 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_cistatic int adav80x_dapm_pll_check(struct snd_soc_dapm_widget *source, 23662306a36Sopenharmony_ci struct snd_soc_dapm_widget *sink) 23762306a36Sopenharmony_ci{ 23862306a36Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); 23962306a36Sopenharmony_ci struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci return adav80x->pll_src == ADAV80X_PLL_SRC_XTAL; 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistatic const struct snd_soc_dapm_route adav80x_dapm_routes[] = { 24662306a36Sopenharmony_ci { "DAC Select", "ADC", "ADC" }, 24762306a36Sopenharmony_ci { "DAC Select", "Playback", "AIFIN" }, 24862306a36Sopenharmony_ci { "DAC Select", "Aux Playback", "AIFAUXIN" }, 24962306a36Sopenharmony_ci { "DAC", NULL, "DAC Select" }, 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci { "Capture Select", "ADC", "ADC" }, 25262306a36Sopenharmony_ci { "Capture Select", "Playback", "AIFIN" }, 25362306a36Sopenharmony_ci { "Capture Select", "Aux Playback", "AIFAUXIN" }, 25462306a36Sopenharmony_ci { "AIFOUT", NULL, "Capture Select" }, 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci { "Aux Capture Select", "ADC", "ADC" }, 25762306a36Sopenharmony_ci { "Aux Capture Select", "Playback", "AIFIN" }, 25862306a36Sopenharmony_ci { "Aux Capture Select", "Aux Playback", "AIFAUXIN" }, 25962306a36Sopenharmony_ci { "AIFAUXOUT", NULL, "Aux Capture Select" }, 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci { "VOUTR", NULL, "DAC" }, 26262306a36Sopenharmony_ci { "VOUTL", NULL, "DAC" }, 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci { "Left PGA", NULL, "VINL" }, 26562306a36Sopenharmony_ci { "Right PGA", NULL, "VINR" }, 26662306a36Sopenharmony_ci { "ADC", NULL, "Left PGA" }, 26762306a36Sopenharmony_ci { "ADC", NULL, "Right PGA" }, 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci { "SYSCLK", NULL, "PLL1", adav80x_dapm_sysclk_check }, 27062306a36Sopenharmony_ci { "SYSCLK", NULL, "PLL2", adav80x_dapm_sysclk_check }, 27162306a36Sopenharmony_ci { "SYSCLK", NULL, "OSC", adav80x_dapm_sysclk_check }, 27262306a36Sopenharmony_ci { "PLL1", NULL, "OSC", adav80x_dapm_pll_check }, 27362306a36Sopenharmony_ci { "PLL2", NULL, "OSC", adav80x_dapm_pll_check }, 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci { "ADC", NULL, "SYSCLK" }, 27662306a36Sopenharmony_ci { "DAC", NULL, "SYSCLK" }, 27762306a36Sopenharmony_ci { "AIFOUT", NULL, "SYSCLK" }, 27862306a36Sopenharmony_ci { "AIFAUXOUT", NULL, "SYSCLK" }, 27962306a36Sopenharmony_ci { "AIFIN", NULL, "SYSCLK" }, 28062306a36Sopenharmony_ci { "AIFAUXIN", NULL, "SYSCLK" }, 28162306a36Sopenharmony_ci}; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic int adav80x_set_deemph(struct snd_soc_component *component) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 28662306a36Sopenharmony_ci unsigned int val; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci if (adav80x->deemph) { 28962306a36Sopenharmony_ci switch (adav80x->rate) { 29062306a36Sopenharmony_ci case 32000: 29162306a36Sopenharmony_ci val = ADAV80X_DAC_CTRL2_DEEMPH_32; 29262306a36Sopenharmony_ci break; 29362306a36Sopenharmony_ci case 44100: 29462306a36Sopenharmony_ci val = ADAV80X_DAC_CTRL2_DEEMPH_44; 29562306a36Sopenharmony_ci break; 29662306a36Sopenharmony_ci case 48000: 29762306a36Sopenharmony_ci case 64000: 29862306a36Sopenharmony_ci case 88200: 29962306a36Sopenharmony_ci case 96000: 30062306a36Sopenharmony_ci val = ADAV80X_DAC_CTRL2_DEEMPH_48; 30162306a36Sopenharmony_ci break; 30262306a36Sopenharmony_ci default: 30362306a36Sopenharmony_ci val = ADAV80X_DAC_CTRL2_DEEMPH_NONE; 30462306a36Sopenharmony_ci break; 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci } else { 30762306a36Sopenharmony_ci val = ADAV80X_DAC_CTRL2_DEEMPH_NONE; 30862306a36Sopenharmony_ci } 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci return regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL2, 31162306a36Sopenharmony_ci ADAV80X_DAC_CTRL2_DEEMPH_MASK, val); 31262306a36Sopenharmony_ci} 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_cistatic int adav80x_put_deemph(struct snd_kcontrol *kcontrol, 31562306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 31662306a36Sopenharmony_ci{ 31762306a36Sopenharmony_ci struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 31862306a36Sopenharmony_ci struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 31962306a36Sopenharmony_ci unsigned int deemph = ucontrol->value.integer.value[0]; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci if (deemph > 1) 32262306a36Sopenharmony_ci return -EINVAL; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci adav80x->deemph = deemph; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci return adav80x_set_deemph(component); 32762306a36Sopenharmony_ci} 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_cistatic int adav80x_get_deemph(struct snd_kcontrol *kcontrol, 33062306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 33162306a36Sopenharmony_ci{ 33262306a36Sopenharmony_ci struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 33362306a36Sopenharmony_ci struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci ucontrol->value.integer.value[0] = adav80x->deemph; 33662306a36Sopenharmony_ci return 0; 33762306a36Sopenharmony_ci}; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(adav80x_inpga_tlv, 0, 50, 0); 34062306a36Sopenharmony_cistatic const DECLARE_TLV_DB_MINMAX(adav80x_digital_tlv, -9563, 0); 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_cistatic const struct snd_kcontrol_new adav80x_controls[] = { 34362306a36Sopenharmony_ci SOC_DOUBLE_R_TLV("Master Playback Volume", ADAV80X_DAC_L_VOL, 34462306a36Sopenharmony_ci ADAV80X_DAC_R_VOL, 0, 0xff, 0, adav80x_digital_tlv), 34562306a36Sopenharmony_ci SOC_DOUBLE_R_TLV("Master Capture Volume", ADAV80X_ADC_L_VOL, 34662306a36Sopenharmony_ci ADAV80X_ADC_R_VOL, 0, 0xff, 0, adav80x_digital_tlv), 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci SOC_DOUBLE_R_TLV("PGA Capture Volume", ADAV80X_PGA_L_VOL, 34962306a36Sopenharmony_ci ADAV80X_PGA_R_VOL, 0, 0x30, 0, adav80x_inpga_tlv), 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci SOC_DOUBLE("Master Playback Switch", ADAV80X_DAC_CTRL1, 0, 1, 1, 0), 35262306a36Sopenharmony_ci SOC_DOUBLE("Master Capture Switch", ADAV80X_ADC_CTRL1, 2, 3, 1, 1), 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci SOC_SINGLE("ADC High Pass Filter Switch", ADAV80X_ADC_CTRL1, 6, 1, 0), 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci SOC_SINGLE_BOOL_EXT("Playback De-emphasis Switch", 0, 35762306a36Sopenharmony_ci adav80x_get_deemph, adav80x_put_deemph), 35862306a36Sopenharmony_ci}; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_cistatic unsigned int adav80x_port_ctrl_regs[2][2] = { 36162306a36Sopenharmony_ci { ADAV80X_REC_CTRL, ADAV80X_PLAYBACK_CTRL, }, 36262306a36Sopenharmony_ci { ADAV80X_AUX_OUT_CTRL, ADAV80X_AUX_IN_CTRL }, 36362306a36Sopenharmony_ci}; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_cistatic int adav80x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 36662306a36Sopenharmony_ci{ 36762306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 36862306a36Sopenharmony_ci struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 36962306a36Sopenharmony_ci unsigned int capture = 0x00; 37062306a36Sopenharmony_ci unsigned int playback = 0x00; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { 37362306a36Sopenharmony_ci case SND_SOC_DAIFMT_CBP_CFP: 37462306a36Sopenharmony_ci capture |= ADAV80X_CAPTURE_MODE_MASTER; 37562306a36Sopenharmony_ci playback |= ADAV80X_PLAYBACK_MODE_MASTER; 37662306a36Sopenharmony_ci break; 37762306a36Sopenharmony_ci case SND_SOC_DAIFMT_CBC_CFC: 37862306a36Sopenharmony_ci break; 37962306a36Sopenharmony_ci default: 38062306a36Sopenharmony_ci return -EINVAL; 38162306a36Sopenharmony_ci } 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 38462306a36Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 38562306a36Sopenharmony_ci capture |= ADAV80X_CAPTURE_MODE_I2S; 38662306a36Sopenharmony_ci playback |= ADAV80X_PLAYBACK_MODE_I2S; 38762306a36Sopenharmony_ci break; 38862306a36Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 38962306a36Sopenharmony_ci capture |= ADAV80X_CAPTURE_MODE_LEFT_J; 39062306a36Sopenharmony_ci playback |= ADAV80X_PLAYBACK_MODE_LEFT_J; 39162306a36Sopenharmony_ci break; 39262306a36Sopenharmony_ci case SND_SOC_DAIFMT_RIGHT_J: 39362306a36Sopenharmony_ci capture |= ADAV80X_CAPTURE_MODE_RIGHT_J; 39462306a36Sopenharmony_ci playback |= ADAV80X_PLAYBACK_MODE_RIGHT_J_24; 39562306a36Sopenharmony_ci break; 39662306a36Sopenharmony_ci default: 39762306a36Sopenharmony_ci return -EINVAL; 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 40162306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_NF: 40262306a36Sopenharmony_ci break; 40362306a36Sopenharmony_ci default: 40462306a36Sopenharmony_ci return -EINVAL; 40562306a36Sopenharmony_ci } 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci regmap_update_bits(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][0], 40862306a36Sopenharmony_ci ADAV80X_CAPTURE_MODE_MASK | ADAV80X_CAPTURE_MODE_MASTER, 40962306a36Sopenharmony_ci capture); 41062306a36Sopenharmony_ci regmap_write(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][1], 41162306a36Sopenharmony_ci playback); 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci adav80x->dai_fmt[dai->id] = fmt & SND_SOC_DAIFMT_FORMAT_MASK; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci return 0; 41662306a36Sopenharmony_ci} 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_cistatic int adav80x_set_adc_clock(struct snd_soc_component *component, 41962306a36Sopenharmony_ci unsigned int sample_rate) 42062306a36Sopenharmony_ci{ 42162306a36Sopenharmony_ci struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 42262306a36Sopenharmony_ci unsigned int val; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci if (sample_rate <= 48000) 42562306a36Sopenharmony_ci val = ADAV80X_ADC_CTRL1_MODULATOR_128FS; 42662306a36Sopenharmony_ci else 42762306a36Sopenharmony_ci val = ADAV80X_ADC_CTRL1_MODULATOR_64FS; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci regmap_update_bits(adav80x->regmap, ADAV80X_ADC_CTRL1, 43062306a36Sopenharmony_ci ADAV80X_ADC_CTRL1_MODULATOR_MASK, val); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci return 0; 43362306a36Sopenharmony_ci} 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_cistatic int adav80x_set_dac_clock(struct snd_soc_component *component, 43662306a36Sopenharmony_ci unsigned int sample_rate) 43762306a36Sopenharmony_ci{ 43862306a36Sopenharmony_ci struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 43962306a36Sopenharmony_ci unsigned int val; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci if (sample_rate <= 48000) 44262306a36Sopenharmony_ci val = ADAV80X_DAC_CTRL2_DIV1 | ADAV80X_DAC_CTRL2_INTERPOL_256FS; 44362306a36Sopenharmony_ci else 44462306a36Sopenharmony_ci val = ADAV80X_DAC_CTRL2_DIV2 | ADAV80X_DAC_CTRL2_INTERPOL_128FS; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL2, 44762306a36Sopenharmony_ci ADAV80X_DAC_CTRL2_DIV_MASK | ADAV80X_DAC_CTRL2_INTERPOL_MASK, 44862306a36Sopenharmony_ci val); 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci return 0; 45162306a36Sopenharmony_ci} 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_cistatic int adav80x_set_capture_pcm_format(struct snd_soc_component *component, 45462306a36Sopenharmony_ci struct snd_soc_dai *dai, struct snd_pcm_hw_params *params) 45562306a36Sopenharmony_ci{ 45662306a36Sopenharmony_ci struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 45762306a36Sopenharmony_ci unsigned int val; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci switch (params_width(params)) { 46062306a36Sopenharmony_ci case 16: 46162306a36Sopenharmony_ci val = ADAV80X_CAPTURE_WORD_LEN16; 46262306a36Sopenharmony_ci break; 46362306a36Sopenharmony_ci case 18: 46462306a36Sopenharmony_ci val = ADAV80X_CAPTRUE_WORD_LEN18; 46562306a36Sopenharmony_ci break; 46662306a36Sopenharmony_ci case 20: 46762306a36Sopenharmony_ci val = ADAV80X_CAPTURE_WORD_LEN20; 46862306a36Sopenharmony_ci break; 46962306a36Sopenharmony_ci case 24: 47062306a36Sopenharmony_ci val = ADAV80X_CAPTURE_WORD_LEN24; 47162306a36Sopenharmony_ci break; 47262306a36Sopenharmony_ci default: 47362306a36Sopenharmony_ci return -EINVAL; 47462306a36Sopenharmony_ci } 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci regmap_update_bits(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][0], 47762306a36Sopenharmony_ci ADAV80X_CAPTURE_WORD_LEN_MASK, val); 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci return 0; 48062306a36Sopenharmony_ci} 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_cistatic int adav80x_set_playback_pcm_format(struct snd_soc_component *component, 48362306a36Sopenharmony_ci struct snd_soc_dai *dai, struct snd_pcm_hw_params *params) 48462306a36Sopenharmony_ci{ 48562306a36Sopenharmony_ci struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 48662306a36Sopenharmony_ci unsigned int val; 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci if (adav80x->dai_fmt[dai->id] != SND_SOC_DAIFMT_RIGHT_J) 48962306a36Sopenharmony_ci return 0; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci switch (params_width(params)) { 49262306a36Sopenharmony_ci case 16: 49362306a36Sopenharmony_ci val = ADAV80X_PLAYBACK_MODE_RIGHT_J_16; 49462306a36Sopenharmony_ci break; 49562306a36Sopenharmony_ci case 18: 49662306a36Sopenharmony_ci val = ADAV80X_PLAYBACK_MODE_RIGHT_J_18; 49762306a36Sopenharmony_ci break; 49862306a36Sopenharmony_ci case 20: 49962306a36Sopenharmony_ci val = ADAV80X_PLAYBACK_MODE_RIGHT_J_20; 50062306a36Sopenharmony_ci break; 50162306a36Sopenharmony_ci case 24: 50262306a36Sopenharmony_ci val = ADAV80X_PLAYBACK_MODE_RIGHT_J_24; 50362306a36Sopenharmony_ci break; 50462306a36Sopenharmony_ci default: 50562306a36Sopenharmony_ci return -EINVAL; 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci regmap_update_bits(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][1], 50962306a36Sopenharmony_ci ADAV80X_PLAYBACK_MODE_MASK, val); 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci return 0; 51262306a36Sopenharmony_ci} 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_cistatic int adav80x_hw_params(struct snd_pcm_substream *substream, 51562306a36Sopenharmony_ci struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 51662306a36Sopenharmony_ci{ 51762306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 51862306a36Sopenharmony_ci struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 51962306a36Sopenharmony_ci unsigned int rate = params_rate(params); 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci if (rate * 256 != adav80x->sysclk) 52262306a36Sopenharmony_ci return -EINVAL; 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 52562306a36Sopenharmony_ci adav80x_set_playback_pcm_format(component, dai, params); 52662306a36Sopenharmony_ci adav80x_set_dac_clock(component, rate); 52762306a36Sopenharmony_ci } else { 52862306a36Sopenharmony_ci adav80x_set_capture_pcm_format(component, dai, params); 52962306a36Sopenharmony_ci adav80x_set_adc_clock(component, rate); 53062306a36Sopenharmony_ci } 53162306a36Sopenharmony_ci adav80x->rate = rate; 53262306a36Sopenharmony_ci adav80x_set_deemph(component); 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci return 0; 53562306a36Sopenharmony_ci} 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_cistatic int adav80x_set_sysclk(struct snd_soc_component *component, 53862306a36Sopenharmony_ci int clk_id, int source, 53962306a36Sopenharmony_ci unsigned int freq, int dir) 54062306a36Sopenharmony_ci{ 54162306a36Sopenharmony_ci struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 54262306a36Sopenharmony_ci struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci if (dir == SND_SOC_CLOCK_IN) { 54562306a36Sopenharmony_ci switch (clk_id) { 54662306a36Sopenharmony_ci case ADAV80X_CLK_XIN: 54762306a36Sopenharmony_ci case ADAV80X_CLK_XTAL: 54862306a36Sopenharmony_ci case ADAV80X_CLK_MCLKI: 54962306a36Sopenharmony_ci case ADAV80X_CLK_PLL1: 55062306a36Sopenharmony_ci case ADAV80X_CLK_PLL2: 55162306a36Sopenharmony_ci break; 55262306a36Sopenharmony_ci default: 55362306a36Sopenharmony_ci return -EINVAL; 55462306a36Sopenharmony_ci } 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci adav80x->sysclk = freq; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci if (adav80x->clk_src != clk_id) { 55962306a36Sopenharmony_ci unsigned int iclk_ctrl1, iclk_ctrl2; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci adav80x->clk_src = clk_id; 56262306a36Sopenharmony_ci if (clk_id == ADAV80X_CLK_XTAL) 56362306a36Sopenharmony_ci clk_id = ADAV80X_CLK_XIN; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci iclk_ctrl1 = ADAV80X_ICLK_CTRL1_DAC_SRC(clk_id) | 56662306a36Sopenharmony_ci ADAV80X_ICLK_CTRL1_ADC_SRC(clk_id) | 56762306a36Sopenharmony_ci ADAV80X_ICLK_CTRL1_ICLK2_SRC(clk_id); 56862306a36Sopenharmony_ci iclk_ctrl2 = ADAV80X_ICLK_CTRL2_ICLK1_SRC(clk_id); 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL1, 57162306a36Sopenharmony_ci iclk_ctrl1); 57262306a36Sopenharmony_ci regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL2, 57362306a36Sopenharmony_ci iclk_ctrl2); 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci snd_soc_dapm_sync(dapm); 57662306a36Sopenharmony_ci } 57762306a36Sopenharmony_ci } else { 57862306a36Sopenharmony_ci unsigned int mask; 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci switch (clk_id) { 58162306a36Sopenharmony_ci case ADAV80X_CLK_SYSCLK1: 58262306a36Sopenharmony_ci case ADAV80X_CLK_SYSCLK2: 58362306a36Sopenharmony_ci case ADAV80X_CLK_SYSCLK3: 58462306a36Sopenharmony_ci break; 58562306a36Sopenharmony_ci default: 58662306a36Sopenharmony_ci return -EINVAL; 58762306a36Sopenharmony_ci } 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci clk_id -= ADAV80X_CLK_SYSCLK1; 59062306a36Sopenharmony_ci mask = ADAV80X_PLL_OUTE_SYSCLKPD(clk_id); 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci if (freq == 0) { 59362306a36Sopenharmony_ci regmap_update_bits(adav80x->regmap, ADAV80X_PLL_OUTE, 59462306a36Sopenharmony_ci mask, mask); 59562306a36Sopenharmony_ci adav80x->sysclk_pd[clk_id] = true; 59662306a36Sopenharmony_ci } else { 59762306a36Sopenharmony_ci regmap_update_bits(adav80x->regmap, ADAV80X_PLL_OUTE, 59862306a36Sopenharmony_ci mask, 0); 59962306a36Sopenharmony_ci adav80x->sysclk_pd[clk_id] = false; 60062306a36Sopenharmony_ci } 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci snd_soc_dapm_mutex_lock(dapm); 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci if (adav80x->sysclk_pd[0]) 60562306a36Sopenharmony_ci snd_soc_dapm_disable_pin_unlocked(dapm, "PLL1"); 60662306a36Sopenharmony_ci else 60762306a36Sopenharmony_ci snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL1"); 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2]) 61062306a36Sopenharmony_ci snd_soc_dapm_disable_pin_unlocked(dapm, "PLL2"); 61162306a36Sopenharmony_ci else 61262306a36Sopenharmony_ci snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL2"); 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci snd_soc_dapm_sync_unlocked(dapm); 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci snd_soc_dapm_mutex_unlock(dapm); 61762306a36Sopenharmony_ci } 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci return 0; 62062306a36Sopenharmony_ci} 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_cistatic int adav80x_set_pll(struct snd_soc_component *component, int pll_id, 62362306a36Sopenharmony_ci int source, unsigned int freq_in, unsigned int freq_out) 62462306a36Sopenharmony_ci{ 62562306a36Sopenharmony_ci struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 62662306a36Sopenharmony_ci struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 62762306a36Sopenharmony_ci unsigned int pll_ctrl1 = 0; 62862306a36Sopenharmony_ci unsigned int pll_ctrl2 = 0; 62962306a36Sopenharmony_ci unsigned int pll_src; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci switch (source) { 63262306a36Sopenharmony_ci case ADAV80X_PLL_SRC_XTAL: 63362306a36Sopenharmony_ci case ADAV80X_PLL_SRC_XIN: 63462306a36Sopenharmony_ci case ADAV80X_PLL_SRC_MCLKI: 63562306a36Sopenharmony_ci break; 63662306a36Sopenharmony_ci default: 63762306a36Sopenharmony_ci return -EINVAL; 63862306a36Sopenharmony_ci } 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci if (!freq_out) 64162306a36Sopenharmony_ci return 0; 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci switch (freq_in) { 64462306a36Sopenharmony_ci case 27000000: 64562306a36Sopenharmony_ci break; 64662306a36Sopenharmony_ci case 54000000: 64762306a36Sopenharmony_ci if (source == ADAV80X_PLL_SRC_XIN) { 64862306a36Sopenharmony_ci pll_ctrl1 |= ADAV80X_PLL_CTRL1_PLLDIV; 64962306a36Sopenharmony_ci break; 65062306a36Sopenharmony_ci } 65162306a36Sopenharmony_ci fallthrough; 65262306a36Sopenharmony_ci default: 65362306a36Sopenharmony_ci return -EINVAL; 65462306a36Sopenharmony_ci } 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci if (freq_out > 12288000) { 65762306a36Sopenharmony_ci pll_ctrl2 |= ADAV80X_PLL_CTRL2_DOUB(pll_id); 65862306a36Sopenharmony_ci freq_out /= 2; 65962306a36Sopenharmony_ci } 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci /* freq_out = sample_rate * 256 */ 66262306a36Sopenharmony_ci switch (freq_out) { 66362306a36Sopenharmony_ci case 8192000: 66462306a36Sopenharmony_ci pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_32(pll_id); 66562306a36Sopenharmony_ci break; 66662306a36Sopenharmony_ci case 11289600: 66762306a36Sopenharmony_ci pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_44(pll_id); 66862306a36Sopenharmony_ci break; 66962306a36Sopenharmony_ci case 12288000: 67062306a36Sopenharmony_ci pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_48(pll_id); 67162306a36Sopenharmony_ci break; 67262306a36Sopenharmony_ci default: 67362306a36Sopenharmony_ci return -EINVAL; 67462306a36Sopenharmony_ci } 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci regmap_update_bits(adav80x->regmap, ADAV80X_PLL_CTRL1, 67762306a36Sopenharmony_ci ADAV80X_PLL_CTRL1_PLLDIV, pll_ctrl1); 67862306a36Sopenharmony_ci regmap_update_bits(adav80x->regmap, ADAV80X_PLL_CTRL2, 67962306a36Sopenharmony_ci ADAV80X_PLL_CTRL2_PLL_MASK(pll_id), pll_ctrl2); 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci if (source != adav80x->pll_src) { 68262306a36Sopenharmony_ci if (source == ADAV80X_PLL_SRC_MCLKI) 68362306a36Sopenharmony_ci pll_src = ADAV80X_PLL_CLK_SRC_PLL_MCLKI(pll_id); 68462306a36Sopenharmony_ci else 68562306a36Sopenharmony_ci pll_src = ADAV80X_PLL_CLK_SRC_PLL_XIN(pll_id); 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci regmap_update_bits(adav80x->regmap, ADAV80X_PLL_CLK_SRC, 68862306a36Sopenharmony_ci ADAV80X_PLL_CLK_SRC_PLL_MASK(pll_id), pll_src); 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci adav80x->pll_src = source; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci snd_soc_dapm_sync(dapm); 69362306a36Sopenharmony_ci } 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci return 0; 69662306a36Sopenharmony_ci} 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_cistatic int adav80x_set_bias_level(struct snd_soc_component *component, 69962306a36Sopenharmony_ci enum snd_soc_bias_level level) 70062306a36Sopenharmony_ci{ 70162306a36Sopenharmony_ci struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 70262306a36Sopenharmony_ci unsigned int mask = ADAV80X_DAC_CTRL1_PD; 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci switch (level) { 70562306a36Sopenharmony_ci case SND_SOC_BIAS_ON: 70662306a36Sopenharmony_ci break; 70762306a36Sopenharmony_ci case SND_SOC_BIAS_PREPARE: 70862306a36Sopenharmony_ci break; 70962306a36Sopenharmony_ci case SND_SOC_BIAS_STANDBY: 71062306a36Sopenharmony_ci regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL1, mask, 71162306a36Sopenharmony_ci 0x00); 71262306a36Sopenharmony_ci break; 71362306a36Sopenharmony_ci case SND_SOC_BIAS_OFF: 71462306a36Sopenharmony_ci regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL1, mask, 71562306a36Sopenharmony_ci mask); 71662306a36Sopenharmony_ci break; 71762306a36Sopenharmony_ci } 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci return 0; 72062306a36Sopenharmony_ci} 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci/* Enforce the same sample rate on all audio interfaces */ 72362306a36Sopenharmony_cistatic int adav80x_dai_startup(struct snd_pcm_substream *substream, 72462306a36Sopenharmony_ci struct snd_soc_dai *dai) 72562306a36Sopenharmony_ci{ 72662306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 72762306a36Sopenharmony_ci struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci if (!snd_soc_component_active(component) || !adav80x->rate) 73062306a36Sopenharmony_ci return 0; 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci return snd_pcm_hw_constraint_single(substream->runtime, 73362306a36Sopenharmony_ci SNDRV_PCM_HW_PARAM_RATE, adav80x->rate); 73462306a36Sopenharmony_ci} 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_cistatic void adav80x_dai_shutdown(struct snd_pcm_substream *substream, 73762306a36Sopenharmony_ci struct snd_soc_dai *dai) 73862306a36Sopenharmony_ci{ 73962306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 74062306a36Sopenharmony_ci struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci if (!snd_soc_component_active(component)) 74362306a36Sopenharmony_ci adav80x->rate = 0; 74462306a36Sopenharmony_ci} 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_cistatic const struct snd_soc_dai_ops adav80x_dai_ops = { 74762306a36Sopenharmony_ci .set_fmt = adav80x_set_dai_fmt, 74862306a36Sopenharmony_ci .hw_params = adav80x_hw_params, 74962306a36Sopenharmony_ci .startup = adav80x_dai_startup, 75062306a36Sopenharmony_ci .shutdown = adav80x_dai_shutdown, 75162306a36Sopenharmony_ci}; 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci#define ADAV80X_PLAYBACK_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ 75462306a36Sopenharmony_ci SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | \ 75562306a36Sopenharmony_ci SNDRV_PCM_RATE_96000) 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci#define ADAV80X_CAPTURE_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci#define ADAV80X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \ 76062306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_cistatic struct snd_soc_dai_driver adav80x_dais[] = { 76362306a36Sopenharmony_ci { 76462306a36Sopenharmony_ci .name = "adav80x-hifi", 76562306a36Sopenharmony_ci .id = 0, 76662306a36Sopenharmony_ci .playback = { 76762306a36Sopenharmony_ci .stream_name = "HiFi Playback", 76862306a36Sopenharmony_ci .channels_min = 2, 76962306a36Sopenharmony_ci .channels_max = 2, 77062306a36Sopenharmony_ci .rates = ADAV80X_PLAYBACK_RATES, 77162306a36Sopenharmony_ci .formats = ADAV80X_FORMATS, 77262306a36Sopenharmony_ci }, 77362306a36Sopenharmony_ci .capture = { 77462306a36Sopenharmony_ci .stream_name = "HiFi Capture", 77562306a36Sopenharmony_ci .channels_min = 2, 77662306a36Sopenharmony_ci .channels_max = 2, 77762306a36Sopenharmony_ci .rates = ADAV80X_CAPTURE_RATES, 77862306a36Sopenharmony_ci .formats = ADAV80X_FORMATS, 77962306a36Sopenharmony_ci }, 78062306a36Sopenharmony_ci .ops = &adav80x_dai_ops, 78162306a36Sopenharmony_ci }, 78262306a36Sopenharmony_ci { 78362306a36Sopenharmony_ci .name = "adav80x-aux", 78462306a36Sopenharmony_ci .id = 1, 78562306a36Sopenharmony_ci .playback = { 78662306a36Sopenharmony_ci .stream_name = "Aux Playback", 78762306a36Sopenharmony_ci .channels_min = 2, 78862306a36Sopenharmony_ci .channels_max = 2, 78962306a36Sopenharmony_ci .rates = ADAV80X_PLAYBACK_RATES, 79062306a36Sopenharmony_ci .formats = ADAV80X_FORMATS, 79162306a36Sopenharmony_ci }, 79262306a36Sopenharmony_ci .capture = { 79362306a36Sopenharmony_ci .stream_name = "Aux Capture", 79462306a36Sopenharmony_ci .channels_min = 2, 79562306a36Sopenharmony_ci .channels_max = 2, 79662306a36Sopenharmony_ci .rates = ADAV80X_CAPTURE_RATES, 79762306a36Sopenharmony_ci .formats = ADAV80X_FORMATS, 79862306a36Sopenharmony_ci }, 79962306a36Sopenharmony_ci .ops = &adav80x_dai_ops, 80062306a36Sopenharmony_ci }, 80162306a36Sopenharmony_ci}; 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_cistatic int adav80x_probe(struct snd_soc_component *component) 80462306a36Sopenharmony_ci{ 80562306a36Sopenharmony_ci struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 80662306a36Sopenharmony_ci struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci /* Force PLLs on for SYSCLK output */ 80962306a36Sopenharmony_ci snd_soc_dapm_force_enable_pin(dapm, "PLL1"); 81062306a36Sopenharmony_ci snd_soc_dapm_force_enable_pin(dapm, "PLL2"); 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci /* Power down S/PDIF receiver, since it is currently not supported */ 81362306a36Sopenharmony_ci regmap_write(adav80x->regmap, ADAV80X_PLL_OUTE, 0x20); 81462306a36Sopenharmony_ci /* Disable DAC zero flag */ 81562306a36Sopenharmony_ci regmap_write(adav80x->regmap, ADAV80X_DAC_CTRL3, 0x6); 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci return 0; 81862306a36Sopenharmony_ci} 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_cistatic int adav80x_resume(struct snd_soc_component *component) 82162306a36Sopenharmony_ci{ 82262306a36Sopenharmony_ci struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci regcache_sync(adav80x->regmap); 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci return 0; 82762306a36Sopenharmony_ci} 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_cistatic const struct snd_soc_component_driver adav80x_component_driver = { 83062306a36Sopenharmony_ci .probe = adav80x_probe, 83162306a36Sopenharmony_ci .resume = adav80x_resume, 83262306a36Sopenharmony_ci .set_bias_level = adav80x_set_bias_level, 83362306a36Sopenharmony_ci .set_pll = adav80x_set_pll, 83462306a36Sopenharmony_ci .set_sysclk = adav80x_set_sysclk, 83562306a36Sopenharmony_ci .controls = adav80x_controls, 83662306a36Sopenharmony_ci .num_controls = ARRAY_SIZE(adav80x_controls), 83762306a36Sopenharmony_ci .dapm_widgets = adav80x_dapm_widgets, 83862306a36Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(adav80x_dapm_widgets), 83962306a36Sopenharmony_ci .dapm_routes = adav80x_dapm_routes, 84062306a36Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes), 84162306a36Sopenharmony_ci .suspend_bias_off = 1, 84262306a36Sopenharmony_ci .idle_bias_on = 1, 84362306a36Sopenharmony_ci .use_pmdown_time = 1, 84462306a36Sopenharmony_ci .endianness = 1, 84562306a36Sopenharmony_ci}; 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ciint adav80x_bus_probe(struct device *dev, struct regmap *regmap) 84862306a36Sopenharmony_ci{ 84962306a36Sopenharmony_ci struct adav80x *adav80x; 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci if (IS_ERR(regmap)) 85262306a36Sopenharmony_ci return PTR_ERR(regmap); 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci adav80x = devm_kzalloc(dev, sizeof(*adav80x), GFP_KERNEL); 85562306a36Sopenharmony_ci if (!adav80x) 85662306a36Sopenharmony_ci return -ENOMEM; 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_ci dev_set_drvdata(dev, adav80x); 85962306a36Sopenharmony_ci adav80x->regmap = regmap; 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci return devm_snd_soc_register_component(dev, &adav80x_component_driver, 86262306a36Sopenharmony_ci adav80x_dais, ARRAY_SIZE(adav80x_dais)); 86362306a36Sopenharmony_ci} 86462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(adav80x_bus_probe); 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ciconst struct regmap_config adav80x_regmap_config = { 86762306a36Sopenharmony_ci .val_bits = 8, 86862306a36Sopenharmony_ci .pad_bits = 1, 86962306a36Sopenharmony_ci .reg_bits = 7, 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci .max_register = ADAV80X_PLL_OUTE, 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci .cache_type = REGCACHE_MAPLE, 87462306a36Sopenharmony_ci .reg_defaults = adav80x_reg_defaults, 87562306a36Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults), 87662306a36Sopenharmony_ci}; 87762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(adav80x_regmap_config); 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ciMODULE_DESCRIPTION("ASoC ADAV80x driver"); 88062306a36Sopenharmony_ciMODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 88162306a36Sopenharmony_ciMODULE_AUTHOR("Yi Li <yi.li@analog.com>>"); 88262306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 883