180503b23SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2cc52688aSLars-Peter Clausen /* 3cc52688aSLars-Peter Clausen * ADAV80X Audio Codec driver supporting ADAV801, ADAV803 4cc52688aSLars-Peter Clausen * 5cc52688aSLars-Peter Clausen * Copyright 2011 Analog Devices Inc. 6cc52688aSLars-Peter Clausen * Author: Yi Li <yi.li@analog.com> 7cc52688aSLars-Peter Clausen * Author: Lars-Peter Clausen <lars@metafoo.de> 8cc52688aSLars-Peter Clausen */ 9cc52688aSLars-Peter Clausen 10cc52688aSLars-Peter Clausen #include <linux/module.h> 11cc52688aSLars-Peter Clausen #include <linux/kernel.h> 120c2d6964SLars-Peter Clausen #include <linux/regmap.h> 13cc52688aSLars-Peter Clausen #include <linux/slab.h> 140c2d6964SLars-Peter Clausen 15cc52688aSLars-Peter Clausen #include <sound/pcm.h> 16cc52688aSLars-Peter Clausen #include <sound/pcm_params.h> 17cc52688aSLars-Peter Clausen #include <sound/soc.h> 180c2d6964SLars-Peter Clausen #include <sound/tlv.h> 19cc52688aSLars-Peter Clausen 20cc52688aSLars-Peter Clausen #include "adav80x.h" 21cc52688aSLars-Peter Clausen 22cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_CTRL 0x04 23cc52688aSLars-Peter Clausen #define ADAV80X_AUX_IN_CTRL 0x05 24cc52688aSLars-Peter Clausen #define ADAV80X_REC_CTRL 0x06 25cc52688aSLars-Peter Clausen #define ADAV80X_AUX_OUT_CTRL 0x07 26cc52688aSLars-Peter Clausen #define ADAV80X_DPATH_CTRL1 0x62 27cc52688aSLars-Peter Clausen #define ADAV80X_DPATH_CTRL2 0x63 28cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL1 0x64 29cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2 0x65 30cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL3 0x66 31cc52688aSLars-Peter Clausen #define ADAV80X_DAC_L_VOL 0x68 32cc52688aSLars-Peter Clausen #define ADAV80X_DAC_R_VOL 0x69 33cc52688aSLars-Peter Clausen #define ADAV80X_PGA_L_VOL 0x6c 34cc52688aSLars-Peter Clausen #define ADAV80X_PGA_R_VOL 0x6d 35cc52688aSLars-Peter Clausen #define ADAV80X_ADC_CTRL1 0x6e 36cc52688aSLars-Peter Clausen #define ADAV80X_ADC_CTRL2 0x6f 37cc52688aSLars-Peter Clausen #define ADAV80X_ADC_L_VOL 0x70 38cc52688aSLars-Peter Clausen #define ADAV80X_ADC_R_VOL 0x71 39cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL1 0x74 40cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL2 0x75 41cc52688aSLars-Peter Clausen #define ADAV80X_ICLK_CTRL1 0x76 42cc52688aSLars-Peter Clausen #define ADAV80X_ICLK_CTRL2 0x77 43cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CLK_SRC 0x78 44cc52688aSLars-Peter Clausen #define ADAV80X_PLL_OUTE 0x7a 45cc52688aSLars-Peter Clausen 46cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CLK_SRC_PLL_XIN(pll) 0x00 47cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CLK_SRC_PLL_MCLKI(pll) (0x40 << (pll)) 48cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CLK_SRC_PLL_MASK(pll) (0x40 << (pll)) 49cc52688aSLars-Peter Clausen 50cc52688aSLars-Peter Clausen #define ADAV80X_ICLK_CTRL1_DAC_SRC(src) ((src) << 5) 51cc52688aSLars-Peter Clausen #define ADAV80X_ICLK_CTRL1_ADC_SRC(src) ((src) << 2) 52cc52688aSLars-Peter Clausen #define ADAV80X_ICLK_CTRL1_ICLK2_SRC(src) (src) 53cc52688aSLars-Peter Clausen #define ADAV80X_ICLK_CTRL2_ICLK1_SRC(src) ((src) << 3) 54cc52688aSLars-Peter Clausen 55cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL1_PLLDIV 0x10 56cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL1_PLLPD(pll) (0x04 << (pll)) 57cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL1_XTLPD 0x02 58cc52688aSLars-Peter Clausen 59cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL2_FIELD(pll, x) ((x) << ((pll) * 4)) 60cc52688aSLars-Peter Clausen 61cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL2_FS_48(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x00) 62cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL2_FS_32(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x08) 63cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL2_FS_44(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x0c) 64cc52688aSLars-Peter Clausen 65cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL2_SEL(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x02) 66cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL2_DOUB(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x01) 67cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL2_PLL_MASK(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x0f) 68cc52688aSLars-Peter Clausen 69cc52688aSLars-Peter Clausen #define ADAV80X_ADC_CTRL1_MODULATOR_MASK 0x80 70cc52688aSLars-Peter Clausen #define ADAV80X_ADC_CTRL1_MODULATOR_128FS 0x00 71cc52688aSLars-Peter Clausen #define ADAV80X_ADC_CTRL1_MODULATOR_64FS 0x80 72cc52688aSLars-Peter Clausen 73cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL1_PD 0x80 74cc52688aSLars-Peter Clausen 75cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DIV1 0x00 76cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DIV1_5 0x10 77cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DIV2 0x20 78cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DIV3 0x30 79cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DIV_MASK 0x30 80cc52688aSLars-Peter Clausen 81cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_INTERPOL_256FS 0x00 82cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_INTERPOL_128FS 0x40 83cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_INTERPOL_64FS 0x80 84cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_INTERPOL_MASK 0xc0 85cc52688aSLars-Peter Clausen 86cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DEEMPH_NONE 0x00 87cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DEEMPH_44 0x01 88cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DEEMPH_32 0x02 89cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DEEMPH_48 0x03 90cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DEEMPH_MASK 0x01 91cc52688aSLars-Peter Clausen 92cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_MODE_MASTER 0x20 93cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_WORD_LEN24 0x00 94cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_WORD_LEN20 0x04 95cc52688aSLars-Peter Clausen #define ADAV80X_CAPTRUE_WORD_LEN18 0x08 96cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_WORD_LEN16 0x0c 97cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_WORD_LEN_MASK 0x0c 98cc52688aSLars-Peter Clausen 99cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_MODE_LEFT_J 0x00 100cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_MODE_I2S 0x01 101cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_MODE_RIGHT_J 0x03 102cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_MODE_MASK 0x03 103cc52688aSLars-Peter Clausen 104cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_MODE_MASTER 0x10 105cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_MODE_LEFT_J 0x00 106cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_MODE_I2S 0x01 107cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_MODE_RIGHT_J_24 0x04 108cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_MODE_RIGHT_J_20 0x05 109cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_MODE_RIGHT_J_18 0x06 110cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_MODE_RIGHT_J_16 0x07 111cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_MODE_MASK 0x07 112cc52688aSLars-Peter Clausen 113cc52688aSLars-Peter Clausen #define ADAV80X_PLL_OUTE_SYSCLKPD(x) BIT(2 - (x)) 114cc52688aSLars-Peter Clausen 115c418a84aSAxel Lin static const struct reg_default adav80x_reg_defaults[] = { 1162560b3d1SLars-Peter Clausen { ADAV80X_PLAYBACK_CTRL, 0x01 }, 1172560b3d1SLars-Peter Clausen { ADAV80X_AUX_IN_CTRL, 0x01 }, 1182560b3d1SLars-Peter Clausen { ADAV80X_REC_CTRL, 0x02 }, 1192560b3d1SLars-Peter Clausen { ADAV80X_AUX_OUT_CTRL, 0x01 }, 1202560b3d1SLars-Peter Clausen { ADAV80X_DPATH_CTRL1, 0xc0 }, 1212560b3d1SLars-Peter Clausen { ADAV80X_DPATH_CTRL2, 0x11 }, 1222560b3d1SLars-Peter Clausen { ADAV80X_DAC_CTRL1, 0x00 }, 1232560b3d1SLars-Peter Clausen { ADAV80X_DAC_CTRL2, 0x00 }, 1242560b3d1SLars-Peter Clausen { ADAV80X_DAC_CTRL3, 0x00 }, 1252560b3d1SLars-Peter Clausen { ADAV80X_DAC_L_VOL, 0xff }, 1262560b3d1SLars-Peter Clausen { ADAV80X_DAC_R_VOL, 0xff }, 1272560b3d1SLars-Peter Clausen { ADAV80X_PGA_L_VOL, 0x00 }, 1282560b3d1SLars-Peter Clausen { ADAV80X_PGA_R_VOL, 0x00 }, 1292560b3d1SLars-Peter Clausen { ADAV80X_ADC_CTRL1, 0x00 }, 1302560b3d1SLars-Peter Clausen { ADAV80X_ADC_CTRL2, 0x00 }, 1312560b3d1SLars-Peter Clausen { ADAV80X_ADC_L_VOL, 0xff }, 1322560b3d1SLars-Peter Clausen { ADAV80X_ADC_R_VOL, 0xff }, 1332560b3d1SLars-Peter Clausen { ADAV80X_PLL_CTRL1, 0x00 }, 1342560b3d1SLars-Peter Clausen { ADAV80X_PLL_CTRL2, 0x00 }, 1352560b3d1SLars-Peter Clausen { ADAV80X_ICLK_CTRL1, 0x00 }, 1362560b3d1SLars-Peter Clausen { ADAV80X_ICLK_CTRL2, 0x00 }, 1372560b3d1SLars-Peter Clausen { ADAV80X_PLL_CLK_SRC, 0x00 }, 1382560b3d1SLars-Peter Clausen { ADAV80X_PLL_OUTE, 0x00 }, 139cc52688aSLars-Peter Clausen }; 140cc52688aSLars-Peter Clausen 141cc52688aSLars-Peter Clausen struct adav80x { 1422560b3d1SLars-Peter Clausen struct regmap *regmap; 143cc52688aSLars-Peter Clausen 144cc52688aSLars-Peter Clausen enum adav80x_clk_src clk_src; 145cc52688aSLars-Peter Clausen unsigned int sysclk; 146cc52688aSLars-Peter Clausen enum adav80x_pll_src pll_src; 147cc52688aSLars-Peter Clausen 148cc52688aSLars-Peter Clausen unsigned int dai_fmt[2]; 149cc52688aSLars-Peter Clausen unsigned int rate; 150cc52688aSLars-Peter Clausen bool deemph; 151cc52688aSLars-Peter Clausen bool sysclk_pd[3]; 152cc52688aSLars-Peter Clausen }; 153cc52688aSLars-Peter Clausen 154cc52688aSLars-Peter Clausen static const char *adav80x_mux_text[] = { 155cc52688aSLars-Peter Clausen "ADC", 156cc52688aSLars-Peter Clausen "Playback", 157cc52688aSLars-Peter Clausen "Aux Playback", 158cc52688aSLars-Peter Clausen }; 159cc52688aSLars-Peter Clausen 160cc52688aSLars-Peter Clausen static const unsigned int adav80x_mux_values[] = { 161cc52688aSLars-Peter Clausen 0, 2, 3, 162cc52688aSLars-Peter Clausen }; 163cc52688aSLars-Peter Clausen 164cc52688aSLars-Peter Clausen #define ADAV80X_MUX_ENUM_DECL(name, reg, shift) \ 165cc52688aSLars-Peter Clausen SOC_VALUE_ENUM_DOUBLE_DECL(name, reg, shift, 7, \ 166cc52688aSLars-Peter Clausen ARRAY_SIZE(adav80x_mux_text), adav80x_mux_text, \ 167cc52688aSLars-Peter Clausen adav80x_mux_values) 168cc52688aSLars-Peter Clausen 169cc52688aSLars-Peter Clausen static ADAV80X_MUX_ENUM_DECL(adav80x_aux_capture_enum, ADAV80X_DPATH_CTRL1, 0); 170cc52688aSLars-Peter Clausen static ADAV80X_MUX_ENUM_DECL(adav80x_capture_enum, ADAV80X_DPATH_CTRL1, 3); 171cc52688aSLars-Peter Clausen static ADAV80X_MUX_ENUM_DECL(adav80x_dac_enum, ADAV80X_DPATH_CTRL2, 3); 172cc52688aSLars-Peter Clausen 173cc52688aSLars-Peter Clausen static const struct snd_kcontrol_new adav80x_aux_capture_mux_ctrl = 17448fa3636SLars-Peter Clausen SOC_DAPM_ENUM("Route", adav80x_aux_capture_enum); 175cc52688aSLars-Peter Clausen static const struct snd_kcontrol_new adav80x_capture_mux_ctrl = 17648fa3636SLars-Peter Clausen SOC_DAPM_ENUM("Route", adav80x_capture_enum); 177cc52688aSLars-Peter Clausen static const struct snd_kcontrol_new adav80x_dac_mux_ctrl = 17848fa3636SLars-Peter Clausen SOC_DAPM_ENUM("Route", adav80x_dac_enum); 179cc52688aSLars-Peter Clausen 180cc52688aSLars-Peter Clausen #define ADAV80X_MUX(name, ctrl) \ 18148fa3636SLars-Peter Clausen SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, 0, 0, ctrl) 182cc52688aSLars-Peter Clausen 183cc52688aSLars-Peter Clausen static const struct snd_soc_dapm_widget adav80x_dapm_widgets[] = { 184cc52688aSLars-Peter Clausen SND_SOC_DAPM_DAC("DAC", NULL, ADAV80X_DAC_CTRL1, 7, 1), 185cc52688aSLars-Peter Clausen SND_SOC_DAPM_ADC("ADC", NULL, ADAV80X_ADC_CTRL1, 5, 1), 186cc52688aSLars-Peter Clausen 187cc52688aSLars-Peter Clausen SND_SOC_DAPM_PGA("Right PGA", ADAV80X_ADC_CTRL1, 0, 1, NULL, 0), 188cc52688aSLars-Peter Clausen SND_SOC_DAPM_PGA("Left PGA", ADAV80X_ADC_CTRL1, 1, 1, NULL, 0), 189cc52688aSLars-Peter Clausen 190cc52688aSLars-Peter Clausen SND_SOC_DAPM_AIF_OUT("AIFOUT", "HiFi Capture", 0, SND_SOC_NOPM, 0, 0), 191cc52688aSLars-Peter Clausen SND_SOC_DAPM_AIF_IN("AIFIN", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0), 192cc52688aSLars-Peter Clausen 193cc52688aSLars-Peter Clausen SND_SOC_DAPM_AIF_OUT("AIFAUXOUT", "Aux Capture", 0, SND_SOC_NOPM, 0, 0), 194cc52688aSLars-Peter Clausen SND_SOC_DAPM_AIF_IN("AIFAUXIN", "Aux Playback", 0, SND_SOC_NOPM, 0, 0), 195cc52688aSLars-Peter Clausen 196cc52688aSLars-Peter Clausen ADAV80X_MUX("Aux Capture Select", &adav80x_aux_capture_mux_ctrl), 197cc52688aSLars-Peter Clausen ADAV80X_MUX("Capture Select", &adav80x_capture_mux_ctrl), 198cc52688aSLars-Peter Clausen ADAV80X_MUX("DAC Select", &adav80x_dac_mux_ctrl), 199cc52688aSLars-Peter Clausen 200cc52688aSLars-Peter Clausen SND_SOC_DAPM_INPUT("VINR"), 201cc52688aSLars-Peter Clausen SND_SOC_DAPM_INPUT("VINL"), 202cc52688aSLars-Peter Clausen SND_SOC_DAPM_OUTPUT("VOUTR"), 203cc52688aSLars-Peter Clausen SND_SOC_DAPM_OUTPUT("VOUTL"), 204cc52688aSLars-Peter Clausen 205cc52688aSLars-Peter Clausen SND_SOC_DAPM_SUPPLY("SYSCLK", SND_SOC_NOPM, 0, 0, NULL, 0), 206cc52688aSLars-Peter Clausen SND_SOC_DAPM_SUPPLY("PLL1", ADAV80X_PLL_CTRL1, 2, 1, NULL, 0), 207cc52688aSLars-Peter Clausen SND_SOC_DAPM_SUPPLY("PLL2", ADAV80X_PLL_CTRL1, 3, 1, NULL, 0), 208cc52688aSLars-Peter Clausen SND_SOC_DAPM_SUPPLY("OSC", ADAV80X_PLL_CTRL1, 1, 1, NULL, 0), 209cc52688aSLars-Peter Clausen }; 210cc52688aSLars-Peter Clausen 211cc52688aSLars-Peter Clausen static int adav80x_dapm_sysclk_check(struct snd_soc_dapm_widget *source, 212cc52688aSLars-Peter Clausen struct snd_soc_dapm_widget *sink) 213cc52688aSLars-Peter Clausen { 214a0565587SKuninori Morimoto struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); 215a0565587SKuninori Morimoto struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 216cc52688aSLars-Peter Clausen const char *clk; 217cc52688aSLars-Peter Clausen 218cc52688aSLars-Peter Clausen switch (adav80x->clk_src) { 219cc52688aSLars-Peter Clausen case ADAV80X_CLK_PLL1: 220cc52688aSLars-Peter Clausen clk = "PLL1"; 221cc52688aSLars-Peter Clausen break; 222cc52688aSLars-Peter Clausen case ADAV80X_CLK_PLL2: 223cc52688aSLars-Peter Clausen clk = "PLL2"; 224cc52688aSLars-Peter Clausen break; 225cc52688aSLars-Peter Clausen case ADAV80X_CLK_XTAL: 226cc52688aSLars-Peter Clausen clk = "OSC"; 227cc52688aSLars-Peter Clausen break; 228cc52688aSLars-Peter Clausen default: 229cc52688aSLars-Peter Clausen return 0; 230cc52688aSLars-Peter Clausen } 231cc52688aSLars-Peter Clausen 232cc52688aSLars-Peter Clausen return strcmp(source->name, clk) == 0; 233cc52688aSLars-Peter Clausen } 234cc52688aSLars-Peter Clausen 235cc52688aSLars-Peter Clausen static int adav80x_dapm_pll_check(struct snd_soc_dapm_widget *source, 236cc52688aSLars-Peter Clausen struct snd_soc_dapm_widget *sink) 237cc52688aSLars-Peter Clausen { 238a0565587SKuninori Morimoto struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); 239a0565587SKuninori Morimoto struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 240cc52688aSLars-Peter Clausen 241cc52688aSLars-Peter Clausen return adav80x->pll_src == ADAV80X_PLL_SRC_XTAL; 242cc52688aSLars-Peter Clausen } 243cc52688aSLars-Peter Clausen 244cc52688aSLars-Peter Clausen 245cc52688aSLars-Peter Clausen static const struct snd_soc_dapm_route adav80x_dapm_routes[] = { 246cc52688aSLars-Peter Clausen { "DAC Select", "ADC", "ADC" }, 247cc52688aSLars-Peter Clausen { "DAC Select", "Playback", "AIFIN" }, 248cc52688aSLars-Peter Clausen { "DAC Select", "Aux Playback", "AIFAUXIN" }, 249cc52688aSLars-Peter Clausen { "DAC", NULL, "DAC Select" }, 250cc52688aSLars-Peter Clausen 251cc52688aSLars-Peter Clausen { "Capture Select", "ADC", "ADC" }, 252cc52688aSLars-Peter Clausen { "Capture Select", "Playback", "AIFIN" }, 253cc52688aSLars-Peter Clausen { "Capture Select", "Aux Playback", "AIFAUXIN" }, 254cc52688aSLars-Peter Clausen { "AIFOUT", NULL, "Capture Select" }, 255cc52688aSLars-Peter Clausen 256cc52688aSLars-Peter Clausen { "Aux Capture Select", "ADC", "ADC" }, 257cc52688aSLars-Peter Clausen { "Aux Capture Select", "Playback", "AIFIN" }, 258cc52688aSLars-Peter Clausen { "Aux Capture Select", "Aux Playback", "AIFAUXIN" }, 259cc52688aSLars-Peter Clausen { "AIFAUXOUT", NULL, "Aux Capture Select" }, 260cc52688aSLars-Peter Clausen 261cc52688aSLars-Peter Clausen { "VOUTR", NULL, "DAC" }, 262cc52688aSLars-Peter Clausen { "VOUTL", NULL, "DAC" }, 263cc52688aSLars-Peter Clausen 264cc52688aSLars-Peter Clausen { "Left PGA", NULL, "VINL" }, 265cc52688aSLars-Peter Clausen { "Right PGA", NULL, "VINR" }, 266cc52688aSLars-Peter Clausen { "ADC", NULL, "Left PGA" }, 267cc52688aSLars-Peter Clausen { "ADC", NULL, "Right PGA" }, 268cc52688aSLars-Peter Clausen 269cc52688aSLars-Peter Clausen { "SYSCLK", NULL, "PLL1", adav80x_dapm_sysclk_check }, 270cc52688aSLars-Peter Clausen { "SYSCLK", NULL, "PLL2", adav80x_dapm_sysclk_check }, 271cc52688aSLars-Peter Clausen { "SYSCLK", NULL, "OSC", adav80x_dapm_sysclk_check }, 272cc52688aSLars-Peter Clausen { "PLL1", NULL, "OSC", adav80x_dapm_pll_check }, 273cc52688aSLars-Peter Clausen { "PLL2", NULL, "OSC", adav80x_dapm_pll_check }, 274cc52688aSLars-Peter Clausen 275cc52688aSLars-Peter Clausen { "ADC", NULL, "SYSCLK" }, 276cc52688aSLars-Peter Clausen { "DAC", NULL, "SYSCLK" }, 277cc52688aSLars-Peter Clausen { "AIFOUT", NULL, "SYSCLK" }, 278cc52688aSLars-Peter Clausen { "AIFAUXOUT", NULL, "SYSCLK" }, 279cc52688aSLars-Peter Clausen { "AIFIN", NULL, "SYSCLK" }, 280cc52688aSLars-Peter Clausen { "AIFAUXIN", NULL, "SYSCLK" }, 281cc52688aSLars-Peter Clausen }; 282cc52688aSLars-Peter Clausen 283a0565587SKuninori Morimoto static int adav80x_set_deemph(struct snd_soc_component *component) 284cc52688aSLars-Peter Clausen { 285a0565587SKuninori Morimoto struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 286cc52688aSLars-Peter Clausen unsigned int val; 287cc52688aSLars-Peter Clausen 288cc52688aSLars-Peter Clausen if (adav80x->deemph) { 289cc52688aSLars-Peter Clausen switch (adav80x->rate) { 290cc52688aSLars-Peter Clausen case 32000: 291cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DEEMPH_32; 292cc52688aSLars-Peter Clausen break; 293cc52688aSLars-Peter Clausen case 44100: 294cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DEEMPH_44; 295cc52688aSLars-Peter Clausen break; 296cc52688aSLars-Peter Clausen case 48000: 297cc52688aSLars-Peter Clausen case 64000: 298cc52688aSLars-Peter Clausen case 88200: 299cc52688aSLars-Peter Clausen case 96000: 300cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DEEMPH_48; 301cc52688aSLars-Peter Clausen break; 302cc52688aSLars-Peter Clausen default: 303cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DEEMPH_NONE; 304cc52688aSLars-Peter Clausen break; 305cc52688aSLars-Peter Clausen } 306cc52688aSLars-Peter Clausen } else { 307cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DEEMPH_NONE; 308cc52688aSLars-Peter Clausen } 309cc52688aSLars-Peter Clausen 3102560b3d1SLars-Peter Clausen return regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL2, 311cc52688aSLars-Peter Clausen ADAV80X_DAC_CTRL2_DEEMPH_MASK, val); 312cc52688aSLars-Peter Clausen } 313cc52688aSLars-Peter Clausen 314cc52688aSLars-Peter Clausen static int adav80x_put_deemph(struct snd_kcontrol *kcontrol, 315cc52688aSLars-Peter Clausen struct snd_ctl_elem_value *ucontrol) 316cc52688aSLars-Peter Clausen { 317a0565587SKuninori Morimoto struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 318a0565587SKuninori Morimoto struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 3192bf4c1d4STakashi Iwai unsigned int deemph = ucontrol->value.integer.value[0]; 320cc52688aSLars-Peter Clausen 321cc52688aSLars-Peter Clausen if (deemph > 1) 322cc52688aSLars-Peter Clausen return -EINVAL; 323cc52688aSLars-Peter Clausen 324cc52688aSLars-Peter Clausen adav80x->deemph = deemph; 325cc52688aSLars-Peter Clausen 326a0565587SKuninori Morimoto return adav80x_set_deemph(component); 327cc52688aSLars-Peter Clausen } 328cc52688aSLars-Peter Clausen 329cc52688aSLars-Peter Clausen static int adav80x_get_deemph(struct snd_kcontrol *kcontrol, 330cc52688aSLars-Peter Clausen struct snd_ctl_elem_value *ucontrol) 331cc52688aSLars-Peter Clausen { 332a0565587SKuninori Morimoto struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 333a0565587SKuninori Morimoto struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 334cc52688aSLars-Peter Clausen 3352bf4c1d4STakashi Iwai ucontrol->value.integer.value[0] = adav80x->deemph; 336cc52688aSLars-Peter Clausen return 0; 337cc52688aSLars-Peter Clausen }; 338cc52688aSLars-Peter Clausen 339cc52688aSLars-Peter Clausen static const DECLARE_TLV_DB_SCALE(adav80x_inpga_tlv, 0, 50, 0); 340cc52688aSLars-Peter Clausen static const DECLARE_TLV_DB_MINMAX(adav80x_digital_tlv, -9563, 0); 341cc52688aSLars-Peter Clausen 342cc52688aSLars-Peter Clausen static const struct snd_kcontrol_new adav80x_controls[] = { 343cc52688aSLars-Peter Clausen SOC_DOUBLE_R_TLV("Master Playback Volume", ADAV80X_DAC_L_VOL, 344cc52688aSLars-Peter Clausen ADAV80X_DAC_R_VOL, 0, 0xff, 0, adav80x_digital_tlv), 345cc52688aSLars-Peter Clausen SOC_DOUBLE_R_TLV("Master Capture Volume", ADAV80X_ADC_L_VOL, 346cc52688aSLars-Peter Clausen ADAV80X_ADC_R_VOL, 0, 0xff, 0, adav80x_digital_tlv), 347cc52688aSLars-Peter Clausen 348cc52688aSLars-Peter Clausen SOC_DOUBLE_R_TLV("PGA Capture Volume", ADAV80X_PGA_L_VOL, 349cc52688aSLars-Peter Clausen ADAV80X_PGA_R_VOL, 0, 0x30, 0, adav80x_inpga_tlv), 350cc52688aSLars-Peter Clausen 351cc52688aSLars-Peter Clausen SOC_DOUBLE("Master Playback Switch", ADAV80X_DAC_CTRL1, 0, 1, 1, 0), 352cc52688aSLars-Peter Clausen SOC_DOUBLE("Master Capture Switch", ADAV80X_ADC_CTRL1, 2, 3, 1, 1), 353cc52688aSLars-Peter Clausen 354cc52688aSLars-Peter Clausen SOC_SINGLE("ADC High Pass Filter Switch", ADAV80X_ADC_CTRL1, 6, 1, 0), 355cc52688aSLars-Peter Clausen 356cc52688aSLars-Peter Clausen SOC_SINGLE_BOOL_EXT("Playback De-emphasis Switch", 0, 357cc52688aSLars-Peter Clausen adav80x_get_deemph, adav80x_put_deemph), 358cc52688aSLars-Peter Clausen }; 359cc52688aSLars-Peter Clausen 360cc52688aSLars-Peter Clausen static unsigned int adav80x_port_ctrl_regs[2][2] = { 361cc52688aSLars-Peter Clausen { ADAV80X_REC_CTRL, ADAV80X_PLAYBACK_CTRL, }, 362cc52688aSLars-Peter Clausen { ADAV80X_AUX_OUT_CTRL, ADAV80X_AUX_IN_CTRL }, 363cc52688aSLars-Peter Clausen }; 364cc52688aSLars-Peter Clausen 365cc52688aSLars-Peter Clausen static int adav80x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 366cc52688aSLars-Peter Clausen { 367a0565587SKuninori Morimoto struct snd_soc_component *component = dai->component; 368a0565587SKuninori Morimoto struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 369cc52688aSLars-Peter Clausen unsigned int capture = 0x00; 370cc52688aSLars-Peter Clausen unsigned int playback = 0x00; 371cc52688aSLars-Peter Clausen 372cc52688aSLars-Peter Clausen switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 373cc52688aSLars-Peter Clausen case SND_SOC_DAIFMT_CBM_CFM: 374cc52688aSLars-Peter Clausen capture |= ADAV80X_CAPTURE_MODE_MASTER; 375cc52688aSLars-Peter Clausen playback |= ADAV80X_PLAYBACK_MODE_MASTER; 376cc52688aSLars-Peter Clausen case SND_SOC_DAIFMT_CBS_CFS: 377cc52688aSLars-Peter Clausen break; 378cc52688aSLars-Peter Clausen default: 379cc52688aSLars-Peter Clausen return -EINVAL; 380cc52688aSLars-Peter Clausen } 381cc52688aSLars-Peter Clausen 382cc52688aSLars-Peter Clausen switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 383cc52688aSLars-Peter Clausen case SND_SOC_DAIFMT_I2S: 384cc52688aSLars-Peter Clausen capture |= ADAV80X_CAPTURE_MODE_I2S; 385cc52688aSLars-Peter Clausen playback |= ADAV80X_PLAYBACK_MODE_I2S; 386cc52688aSLars-Peter Clausen break; 387cc52688aSLars-Peter Clausen case SND_SOC_DAIFMT_LEFT_J: 388cc52688aSLars-Peter Clausen capture |= ADAV80X_CAPTURE_MODE_LEFT_J; 389cc52688aSLars-Peter Clausen playback |= ADAV80X_PLAYBACK_MODE_LEFT_J; 390cc52688aSLars-Peter Clausen break; 391cc52688aSLars-Peter Clausen case SND_SOC_DAIFMT_RIGHT_J: 392cc52688aSLars-Peter Clausen capture |= ADAV80X_CAPTURE_MODE_RIGHT_J; 393cc52688aSLars-Peter Clausen playback |= ADAV80X_PLAYBACK_MODE_RIGHT_J_24; 394cc52688aSLars-Peter Clausen break; 395cc52688aSLars-Peter Clausen default: 396cc52688aSLars-Peter Clausen return -EINVAL; 397cc52688aSLars-Peter Clausen } 398cc52688aSLars-Peter Clausen 399cc52688aSLars-Peter Clausen switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 400cc52688aSLars-Peter Clausen case SND_SOC_DAIFMT_NB_NF: 401cc52688aSLars-Peter Clausen break; 402cc52688aSLars-Peter Clausen default: 403cc52688aSLars-Peter Clausen return -EINVAL; 404cc52688aSLars-Peter Clausen } 405cc52688aSLars-Peter Clausen 4062560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][0], 407cc52688aSLars-Peter Clausen ADAV80X_CAPTURE_MODE_MASK | ADAV80X_CAPTURE_MODE_MASTER, 408cc52688aSLars-Peter Clausen capture); 4092560b3d1SLars-Peter Clausen regmap_write(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][1], 4102560b3d1SLars-Peter Clausen playback); 411cc52688aSLars-Peter Clausen 412cc52688aSLars-Peter Clausen adav80x->dai_fmt[dai->id] = fmt & SND_SOC_DAIFMT_FORMAT_MASK; 413cc52688aSLars-Peter Clausen 414cc52688aSLars-Peter Clausen return 0; 415cc52688aSLars-Peter Clausen } 416cc52688aSLars-Peter Clausen 417a0565587SKuninori Morimoto static int adav80x_set_adc_clock(struct snd_soc_component *component, 418cc52688aSLars-Peter Clausen unsigned int sample_rate) 419cc52688aSLars-Peter Clausen { 420a0565587SKuninori Morimoto struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 421cc52688aSLars-Peter Clausen unsigned int val; 422cc52688aSLars-Peter Clausen 423cc52688aSLars-Peter Clausen if (sample_rate <= 48000) 424cc52688aSLars-Peter Clausen val = ADAV80X_ADC_CTRL1_MODULATOR_128FS; 425cc52688aSLars-Peter Clausen else 426cc52688aSLars-Peter Clausen val = ADAV80X_ADC_CTRL1_MODULATOR_64FS; 427cc52688aSLars-Peter Clausen 4282560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, ADAV80X_ADC_CTRL1, 429cc52688aSLars-Peter Clausen ADAV80X_ADC_CTRL1_MODULATOR_MASK, val); 430cc52688aSLars-Peter Clausen 431cc52688aSLars-Peter Clausen return 0; 432cc52688aSLars-Peter Clausen } 433cc52688aSLars-Peter Clausen 434a0565587SKuninori Morimoto static int adav80x_set_dac_clock(struct snd_soc_component *component, 435cc52688aSLars-Peter Clausen unsigned int sample_rate) 436cc52688aSLars-Peter Clausen { 437a0565587SKuninori Morimoto struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 438cc52688aSLars-Peter Clausen unsigned int val; 439cc52688aSLars-Peter Clausen 440cc52688aSLars-Peter Clausen if (sample_rate <= 48000) 441cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DIV1 | ADAV80X_DAC_CTRL2_INTERPOL_256FS; 442cc52688aSLars-Peter Clausen else 443cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DIV2 | ADAV80X_DAC_CTRL2_INTERPOL_128FS; 444cc52688aSLars-Peter Clausen 4452560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL2, 446cc52688aSLars-Peter Clausen ADAV80X_DAC_CTRL2_DIV_MASK | ADAV80X_DAC_CTRL2_INTERPOL_MASK, 447cc52688aSLars-Peter Clausen val); 448cc52688aSLars-Peter Clausen 449cc52688aSLars-Peter Clausen return 0; 450cc52688aSLars-Peter Clausen } 451cc52688aSLars-Peter Clausen 452a0565587SKuninori Morimoto static int adav80x_set_capture_pcm_format(struct snd_soc_component *component, 453cf7d8b27SMark Brown struct snd_soc_dai *dai, struct snd_pcm_hw_params *params) 454cc52688aSLars-Peter Clausen { 455a0565587SKuninori Morimoto struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 456cc52688aSLars-Peter Clausen unsigned int val; 457cc52688aSLars-Peter Clausen 458cf7d8b27SMark Brown switch (params_width(params)) { 459cf7d8b27SMark Brown case 16: 460cc52688aSLars-Peter Clausen val = ADAV80X_CAPTURE_WORD_LEN16; 461cc52688aSLars-Peter Clausen break; 462cf7d8b27SMark Brown case 18: 463cc52688aSLars-Peter Clausen val = ADAV80X_CAPTRUE_WORD_LEN18; 464cc52688aSLars-Peter Clausen break; 465cf7d8b27SMark Brown case 20: 466cc52688aSLars-Peter Clausen val = ADAV80X_CAPTURE_WORD_LEN20; 467cc52688aSLars-Peter Clausen break; 468cf7d8b27SMark Brown case 24: 469cc52688aSLars-Peter Clausen val = ADAV80X_CAPTURE_WORD_LEN24; 470cc52688aSLars-Peter Clausen break; 471cc52688aSLars-Peter Clausen default: 472ca1004baSMark Brown return -EINVAL; 473cc52688aSLars-Peter Clausen } 474cc52688aSLars-Peter Clausen 4752560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][0], 476cc52688aSLars-Peter Clausen ADAV80X_CAPTURE_WORD_LEN_MASK, val); 477cc52688aSLars-Peter Clausen 478cc52688aSLars-Peter Clausen return 0; 479cc52688aSLars-Peter Clausen } 480cc52688aSLars-Peter Clausen 481a0565587SKuninori Morimoto static int adav80x_set_playback_pcm_format(struct snd_soc_component *component, 482cf7d8b27SMark Brown struct snd_soc_dai *dai, struct snd_pcm_hw_params *params) 483cc52688aSLars-Peter Clausen { 484a0565587SKuninori Morimoto struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 485cc52688aSLars-Peter Clausen unsigned int val; 486cc52688aSLars-Peter Clausen 487cc52688aSLars-Peter Clausen if (adav80x->dai_fmt[dai->id] != SND_SOC_DAIFMT_RIGHT_J) 488cc52688aSLars-Peter Clausen return 0; 489cc52688aSLars-Peter Clausen 490cf7d8b27SMark Brown switch (params_width(params)) { 491cf7d8b27SMark Brown case 16: 492cc52688aSLars-Peter Clausen val = ADAV80X_PLAYBACK_MODE_RIGHT_J_16; 493cc52688aSLars-Peter Clausen break; 494cf7d8b27SMark Brown case 18: 495cc52688aSLars-Peter Clausen val = ADAV80X_PLAYBACK_MODE_RIGHT_J_18; 496cc52688aSLars-Peter Clausen break; 497cf7d8b27SMark Brown case 20: 498cc52688aSLars-Peter Clausen val = ADAV80X_PLAYBACK_MODE_RIGHT_J_20; 499cc52688aSLars-Peter Clausen break; 500cf7d8b27SMark Brown case 24: 501cc52688aSLars-Peter Clausen val = ADAV80X_PLAYBACK_MODE_RIGHT_J_24; 502cc52688aSLars-Peter Clausen break; 503cc52688aSLars-Peter Clausen default: 504ca1004baSMark Brown return -EINVAL; 505cc52688aSLars-Peter Clausen } 506cc52688aSLars-Peter Clausen 5072560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][1], 508cc52688aSLars-Peter Clausen ADAV80X_PLAYBACK_MODE_MASK, val); 509cc52688aSLars-Peter Clausen 510cc52688aSLars-Peter Clausen return 0; 511cc52688aSLars-Peter Clausen } 512cc52688aSLars-Peter Clausen 513cc52688aSLars-Peter Clausen static int adav80x_hw_params(struct snd_pcm_substream *substream, 514cc52688aSLars-Peter Clausen struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 515cc52688aSLars-Peter Clausen { 516a0565587SKuninori Morimoto struct snd_soc_component *component = dai->component; 517a0565587SKuninori Morimoto struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 518cc52688aSLars-Peter Clausen unsigned int rate = params_rate(params); 519cc52688aSLars-Peter Clausen 520cc52688aSLars-Peter Clausen if (rate * 256 != adav80x->sysclk) 521cc52688aSLars-Peter Clausen return -EINVAL; 522cc52688aSLars-Peter Clausen 523cc52688aSLars-Peter Clausen if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 524a0565587SKuninori Morimoto adav80x_set_playback_pcm_format(component, dai, params); 525a0565587SKuninori Morimoto adav80x_set_dac_clock(component, rate); 526cc52688aSLars-Peter Clausen } else { 527a0565587SKuninori Morimoto adav80x_set_capture_pcm_format(component, dai, params); 528a0565587SKuninori Morimoto adav80x_set_adc_clock(component, rate); 529cc52688aSLars-Peter Clausen } 530cc52688aSLars-Peter Clausen adav80x->rate = rate; 531a0565587SKuninori Morimoto adav80x_set_deemph(component); 532cc52688aSLars-Peter Clausen 533cc52688aSLars-Peter Clausen return 0; 534cc52688aSLars-Peter Clausen } 535cc52688aSLars-Peter Clausen 536a0565587SKuninori Morimoto static int adav80x_set_sysclk(struct snd_soc_component *component, 537da1c6ea6SMark Brown int clk_id, int source, 538da1c6ea6SMark Brown unsigned int freq, int dir) 539cc52688aSLars-Peter Clausen { 540a0565587SKuninori Morimoto struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 541a0565587SKuninori Morimoto struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 542cc52688aSLars-Peter Clausen 543cc52688aSLars-Peter Clausen if (dir == SND_SOC_CLOCK_IN) { 544cc52688aSLars-Peter Clausen switch (clk_id) { 545cc52688aSLars-Peter Clausen case ADAV80X_CLK_XIN: 546cc52688aSLars-Peter Clausen case ADAV80X_CLK_XTAL: 547cc52688aSLars-Peter Clausen case ADAV80X_CLK_MCLKI: 548cc52688aSLars-Peter Clausen case ADAV80X_CLK_PLL1: 549cc52688aSLars-Peter Clausen case ADAV80X_CLK_PLL2: 550cc52688aSLars-Peter Clausen break; 551cc52688aSLars-Peter Clausen default: 552cc52688aSLars-Peter Clausen return -EINVAL; 553cc52688aSLars-Peter Clausen } 554cc52688aSLars-Peter Clausen 555cc52688aSLars-Peter Clausen adav80x->sysclk = freq; 556cc52688aSLars-Peter Clausen 557cc52688aSLars-Peter Clausen if (adav80x->clk_src != clk_id) { 558cc52688aSLars-Peter Clausen unsigned int iclk_ctrl1, iclk_ctrl2; 559cc52688aSLars-Peter Clausen 560cc52688aSLars-Peter Clausen adav80x->clk_src = clk_id; 561cc52688aSLars-Peter Clausen if (clk_id == ADAV80X_CLK_XTAL) 562cc52688aSLars-Peter Clausen clk_id = ADAV80X_CLK_XIN; 563cc52688aSLars-Peter Clausen 564cc52688aSLars-Peter Clausen iclk_ctrl1 = ADAV80X_ICLK_CTRL1_DAC_SRC(clk_id) | 565cc52688aSLars-Peter Clausen ADAV80X_ICLK_CTRL1_ADC_SRC(clk_id) | 566cc52688aSLars-Peter Clausen ADAV80X_ICLK_CTRL1_ICLK2_SRC(clk_id); 567cc52688aSLars-Peter Clausen iclk_ctrl2 = ADAV80X_ICLK_CTRL2_ICLK1_SRC(clk_id); 568cc52688aSLars-Peter Clausen 5692560b3d1SLars-Peter Clausen regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL1, 5702560b3d1SLars-Peter Clausen iclk_ctrl1); 5712560b3d1SLars-Peter Clausen regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL2, 5722560b3d1SLars-Peter Clausen iclk_ctrl2); 573cc52688aSLars-Peter Clausen 5741bf1b8cfSCharles Keepax snd_soc_dapm_sync(dapm); 575cc52688aSLars-Peter Clausen } 576cc52688aSLars-Peter Clausen } else { 577cc52688aSLars-Peter Clausen unsigned int mask; 578cc52688aSLars-Peter Clausen 579cc52688aSLars-Peter Clausen switch (clk_id) { 580cc52688aSLars-Peter Clausen case ADAV80X_CLK_SYSCLK1: 581cc52688aSLars-Peter Clausen case ADAV80X_CLK_SYSCLK2: 582cc52688aSLars-Peter Clausen case ADAV80X_CLK_SYSCLK3: 583cc52688aSLars-Peter Clausen break; 584cc52688aSLars-Peter Clausen default: 585cc52688aSLars-Peter Clausen return -EINVAL; 586cc52688aSLars-Peter Clausen } 587cc52688aSLars-Peter Clausen 588cc52688aSLars-Peter Clausen clk_id -= ADAV80X_CLK_SYSCLK1; 589cc52688aSLars-Peter Clausen mask = ADAV80X_PLL_OUTE_SYSCLKPD(clk_id); 590cc52688aSLars-Peter Clausen 591cc52688aSLars-Peter Clausen if (freq == 0) { 5922560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, ADAV80X_PLL_OUTE, 5932560b3d1SLars-Peter Clausen mask, mask); 594cc52688aSLars-Peter Clausen adav80x->sysclk_pd[clk_id] = true; 595cc52688aSLars-Peter Clausen } else { 5962560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, ADAV80X_PLL_OUTE, 5972560b3d1SLars-Peter Clausen mask, 0); 598cc52688aSLars-Peter Clausen adav80x->sysclk_pd[clk_id] = false; 599cc52688aSLars-Peter Clausen } 600cc52688aSLars-Peter Clausen 6011bf1b8cfSCharles Keepax snd_soc_dapm_mutex_lock(dapm); 6021bf1b8cfSCharles Keepax 603cc52688aSLars-Peter Clausen if (adav80x->sysclk_pd[0]) 6041bf1b8cfSCharles Keepax snd_soc_dapm_disable_pin_unlocked(dapm, "PLL1"); 605cc52688aSLars-Peter Clausen else 6061bf1b8cfSCharles Keepax snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL1"); 607cc52688aSLars-Peter Clausen 608cc52688aSLars-Peter Clausen if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2]) 6091bf1b8cfSCharles Keepax snd_soc_dapm_disable_pin_unlocked(dapm, "PLL2"); 610cc52688aSLars-Peter Clausen else 6111bf1b8cfSCharles Keepax snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL2"); 612cc52688aSLars-Peter Clausen 6131bf1b8cfSCharles Keepax snd_soc_dapm_sync_unlocked(dapm); 6141bf1b8cfSCharles Keepax 6151bf1b8cfSCharles Keepax snd_soc_dapm_mutex_unlock(dapm); 616cc52688aSLars-Peter Clausen } 617cc52688aSLars-Peter Clausen 618cc52688aSLars-Peter Clausen return 0; 619cc52688aSLars-Peter Clausen } 620cc52688aSLars-Peter Clausen 621a0565587SKuninori Morimoto static int adav80x_set_pll(struct snd_soc_component *component, int pll_id, 622cc52688aSLars-Peter Clausen int source, unsigned int freq_in, unsigned int freq_out) 623cc52688aSLars-Peter Clausen { 624a0565587SKuninori Morimoto struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 625a0565587SKuninori Morimoto struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 626cc52688aSLars-Peter Clausen unsigned int pll_ctrl1 = 0; 627cc52688aSLars-Peter Clausen unsigned int pll_ctrl2 = 0; 628cc52688aSLars-Peter Clausen unsigned int pll_src; 629cc52688aSLars-Peter Clausen 630cc52688aSLars-Peter Clausen switch (source) { 631cc52688aSLars-Peter Clausen case ADAV80X_PLL_SRC_XTAL: 632cc52688aSLars-Peter Clausen case ADAV80X_PLL_SRC_XIN: 633cc52688aSLars-Peter Clausen case ADAV80X_PLL_SRC_MCLKI: 634cc52688aSLars-Peter Clausen break; 635cc52688aSLars-Peter Clausen default: 636cc52688aSLars-Peter Clausen return -EINVAL; 637cc52688aSLars-Peter Clausen } 638cc52688aSLars-Peter Clausen 639cc52688aSLars-Peter Clausen if (!freq_out) 640cc52688aSLars-Peter Clausen return 0; 641cc52688aSLars-Peter Clausen 642cc52688aSLars-Peter Clausen switch (freq_in) { 643cc52688aSLars-Peter Clausen case 27000000: 644cc52688aSLars-Peter Clausen break; 645cc52688aSLars-Peter Clausen case 54000000: 646cc52688aSLars-Peter Clausen if (source == ADAV80X_PLL_SRC_XIN) { 647cc52688aSLars-Peter Clausen pll_ctrl1 |= ADAV80X_PLL_CTRL1_PLLDIV; 648cc52688aSLars-Peter Clausen break; 649cc52688aSLars-Peter Clausen } 650f2cf0ef7SGustavo A. R. Silva /* fall through */ 651cc52688aSLars-Peter Clausen default: 652cc52688aSLars-Peter Clausen return -EINVAL; 653cc52688aSLars-Peter Clausen } 654cc52688aSLars-Peter Clausen 655cc52688aSLars-Peter Clausen if (freq_out > 12288000) { 656cc52688aSLars-Peter Clausen pll_ctrl2 |= ADAV80X_PLL_CTRL2_DOUB(pll_id); 657cc52688aSLars-Peter Clausen freq_out /= 2; 658cc52688aSLars-Peter Clausen } 659cc52688aSLars-Peter Clausen 660cc52688aSLars-Peter Clausen /* freq_out = sample_rate * 256 */ 661cc52688aSLars-Peter Clausen switch (freq_out) { 662cc52688aSLars-Peter Clausen case 8192000: 663cc52688aSLars-Peter Clausen pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_32(pll_id); 664cc52688aSLars-Peter Clausen break; 665cc52688aSLars-Peter Clausen case 11289600: 666cc52688aSLars-Peter Clausen pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_44(pll_id); 667cc52688aSLars-Peter Clausen break; 668cc52688aSLars-Peter Clausen case 12288000: 669cc52688aSLars-Peter Clausen pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_48(pll_id); 670cc52688aSLars-Peter Clausen break; 671cc52688aSLars-Peter Clausen default: 672cc52688aSLars-Peter Clausen return -EINVAL; 673cc52688aSLars-Peter Clausen } 674cc52688aSLars-Peter Clausen 6752560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, ADAV80X_PLL_CTRL1, 6762560b3d1SLars-Peter Clausen ADAV80X_PLL_CTRL1_PLLDIV, pll_ctrl1); 6772560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, ADAV80X_PLL_CTRL2, 678cc52688aSLars-Peter Clausen ADAV80X_PLL_CTRL2_PLL_MASK(pll_id), pll_ctrl2); 679cc52688aSLars-Peter Clausen 680cc52688aSLars-Peter Clausen if (source != adav80x->pll_src) { 681cc52688aSLars-Peter Clausen if (source == ADAV80X_PLL_SRC_MCLKI) 682cc52688aSLars-Peter Clausen pll_src = ADAV80X_PLL_CLK_SRC_PLL_MCLKI(pll_id); 683cc52688aSLars-Peter Clausen else 684cc52688aSLars-Peter Clausen pll_src = ADAV80X_PLL_CLK_SRC_PLL_XIN(pll_id); 685cc52688aSLars-Peter Clausen 6862560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, ADAV80X_PLL_CLK_SRC, 687cc52688aSLars-Peter Clausen ADAV80X_PLL_CLK_SRC_PLL_MASK(pll_id), pll_src); 688cc52688aSLars-Peter Clausen 689cc52688aSLars-Peter Clausen adav80x->pll_src = source; 690cc52688aSLars-Peter Clausen 691a34c31a9SLars-Peter Clausen snd_soc_dapm_sync(dapm); 692cc52688aSLars-Peter Clausen } 693cc52688aSLars-Peter Clausen 694cc52688aSLars-Peter Clausen return 0; 695cc52688aSLars-Peter Clausen } 696cc52688aSLars-Peter Clausen 697a0565587SKuninori Morimoto static int adav80x_set_bias_level(struct snd_soc_component *component, 698cc52688aSLars-Peter Clausen enum snd_soc_bias_level level) 699cc52688aSLars-Peter Clausen { 700a0565587SKuninori Morimoto struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 701cc52688aSLars-Peter Clausen unsigned int mask = ADAV80X_DAC_CTRL1_PD; 702cc52688aSLars-Peter Clausen 703cc52688aSLars-Peter Clausen switch (level) { 704cc52688aSLars-Peter Clausen case SND_SOC_BIAS_ON: 705cc52688aSLars-Peter Clausen break; 706cc52688aSLars-Peter Clausen case SND_SOC_BIAS_PREPARE: 707cc52688aSLars-Peter Clausen break; 708cc52688aSLars-Peter Clausen case SND_SOC_BIAS_STANDBY: 7092560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL1, mask, 7102560b3d1SLars-Peter Clausen 0x00); 711cc52688aSLars-Peter Clausen break; 712cc52688aSLars-Peter Clausen case SND_SOC_BIAS_OFF: 7132560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL1, mask, 7142560b3d1SLars-Peter Clausen mask); 715cc52688aSLars-Peter Clausen break; 716cc52688aSLars-Peter Clausen } 717cc52688aSLars-Peter Clausen 718cc52688aSLars-Peter Clausen return 0; 719cc52688aSLars-Peter Clausen } 720cc52688aSLars-Peter Clausen 721cc52688aSLars-Peter Clausen /* Enforce the same sample rate on all audio interfaces */ 722cc52688aSLars-Peter Clausen static int adav80x_dai_startup(struct snd_pcm_substream *substream, 723cc52688aSLars-Peter Clausen struct snd_soc_dai *dai) 724cc52688aSLars-Peter Clausen { 725a0565587SKuninori Morimoto struct snd_soc_component *component = dai->component; 726a0565587SKuninori Morimoto struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 727cc52688aSLars-Peter Clausen 7285e518eddSKuninori Morimoto if (!snd_soc_component_active(component) || !adav80x->rate) 729cc52688aSLars-Peter Clausen return 0; 730cc52688aSLars-Peter Clausen 731153e2f5cSLars-Peter Clausen return snd_pcm_hw_constraint_single(substream->runtime, 732153e2f5cSLars-Peter Clausen SNDRV_PCM_HW_PARAM_RATE, adav80x->rate); 733cc52688aSLars-Peter Clausen } 734cc52688aSLars-Peter Clausen 735cc52688aSLars-Peter Clausen static void adav80x_dai_shutdown(struct snd_pcm_substream *substream, 736cc52688aSLars-Peter Clausen struct snd_soc_dai *dai) 737cc52688aSLars-Peter Clausen { 738a0565587SKuninori Morimoto struct snd_soc_component *component = dai->component; 739a0565587SKuninori Morimoto struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 740cc52688aSLars-Peter Clausen 7415e518eddSKuninori Morimoto if (!snd_soc_component_active(component)) 742cc52688aSLars-Peter Clausen adav80x->rate = 0; 743cc52688aSLars-Peter Clausen } 744cc52688aSLars-Peter Clausen 745890754a8SLars-Peter Clausen static const struct snd_soc_dai_ops adav80x_dai_ops = { 746cc52688aSLars-Peter Clausen .set_fmt = adav80x_set_dai_fmt, 747cc52688aSLars-Peter Clausen .hw_params = adav80x_hw_params, 748cc52688aSLars-Peter Clausen .startup = adav80x_dai_startup, 749cc52688aSLars-Peter Clausen .shutdown = adav80x_dai_shutdown, 750cc52688aSLars-Peter Clausen }; 751cc52688aSLars-Peter Clausen 752cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ 753cc52688aSLars-Peter Clausen SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | \ 754cc52688aSLars-Peter Clausen SNDRV_PCM_RATE_96000) 755cc52688aSLars-Peter Clausen 756cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) 757cc52688aSLars-Peter Clausen 758cc52688aSLars-Peter Clausen #define ADAV80X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \ 759cc52688aSLars-Peter Clausen SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) 760cc52688aSLars-Peter Clausen 761cc52688aSLars-Peter Clausen static struct snd_soc_dai_driver adav80x_dais[] = { 762cc52688aSLars-Peter Clausen { 763cc52688aSLars-Peter Clausen .name = "adav80x-hifi", 764cc52688aSLars-Peter Clausen .id = 0, 765cc52688aSLars-Peter Clausen .playback = { 766cc52688aSLars-Peter Clausen .stream_name = "HiFi Playback", 767cc52688aSLars-Peter Clausen .channels_min = 2, 768cc52688aSLars-Peter Clausen .channels_max = 2, 769cc52688aSLars-Peter Clausen .rates = ADAV80X_PLAYBACK_RATES, 770cc52688aSLars-Peter Clausen .formats = ADAV80X_FORMATS, 771cc52688aSLars-Peter Clausen }, 772cc52688aSLars-Peter Clausen .capture = { 773cc52688aSLars-Peter Clausen .stream_name = "HiFi Capture", 774cc52688aSLars-Peter Clausen .channels_min = 2, 775cc52688aSLars-Peter Clausen .channels_max = 2, 776cc52688aSLars-Peter Clausen .rates = ADAV80X_CAPTURE_RATES, 777cc52688aSLars-Peter Clausen .formats = ADAV80X_FORMATS, 778cc52688aSLars-Peter Clausen }, 779cc52688aSLars-Peter Clausen .ops = &adav80x_dai_ops, 780cc52688aSLars-Peter Clausen }, 781cc52688aSLars-Peter Clausen { 782cc52688aSLars-Peter Clausen .name = "adav80x-aux", 783cc52688aSLars-Peter Clausen .id = 1, 784cc52688aSLars-Peter Clausen .playback = { 785cc52688aSLars-Peter Clausen .stream_name = "Aux Playback", 786cc52688aSLars-Peter Clausen .channels_min = 2, 787cc52688aSLars-Peter Clausen .channels_max = 2, 788cc52688aSLars-Peter Clausen .rates = ADAV80X_PLAYBACK_RATES, 789cc52688aSLars-Peter Clausen .formats = ADAV80X_FORMATS, 790cc52688aSLars-Peter Clausen }, 791cc52688aSLars-Peter Clausen .capture = { 792cc52688aSLars-Peter Clausen .stream_name = "Aux Capture", 793cc52688aSLars-Peter Clausen .channels_min = 2, 794cc52688aSLars-Peter Clausen .channels_max = 2, 795cc52688aSLars-Peter Clausen .rates = ADAV80X_CAPTURE_RATES, 796cc52688aSLars-Peter Clausen .formats = ADAV80X_FORMATS, 797cc52688aSLars-Peter Clausen }, 798cc52688aSLars-Peter Clausen .ops = &adav80x_dai_ops, 799cc52688aSLars-Peter Clausen }, 800cc52688aSLars-Peter Clausen }; 801cc52688aSLars-Peter Clausen 802a0565587SKuninori Morimoto static int adav80x_probe(struct snd_soc_component *component) 803cc52688aSLars-Peter Clausen { 804a0565587SKuninori Morimoto struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 805a0565587SKuninori Morimoto struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 806cc52688aSLars-Peter Clausen 807cc52688aSLars-Peter Clausen /* Force PLLs on for SYSCLK output */ 808a34c31a9SLars-Peter Clausen snd_soc_dapm_force_enable_pin(dapm, "PLL1"); 809a34c31a9SLars-Peter Clausen snd_soc_dapm_force_enable_pin(dapm, "PLL2"); 810cc52688aSLars-Peter Clausen 811cc52688aSLars-Peter Clausen /* Power down S/PDIF receiver, since it is currently not supported */ 8122560b3d1SLars-Peter Clausen regmap_write(adav80x->regmap, ADAV80X_PLL_OUTE, 0x20); 813cc52688aSLars-Peter Clausen /* Disable DAC zero flag */ 8142560b3d1SLars-Peter Clausen regmap_write(adav80x->regmap, ADAV80X_DAC_CTRL3, 0x6); 815cc52688aSLars-Peter Clausen 816cd5d3a15SLars-Peter Clausen return 0; 817cc52688aSLars-Peter Clausen } 818cc52688aSLars-Peter Clausen 819a0565587SKuninori Morimoto static int adav80x_resume(struct snd_soc_component *component) 820cc52688aSLars-Peter Clausen { 821a0565587SKuninori Morimoto struct adav80x *adav80x = snd_soc_component_get_drvdata(component); 8222560b3d1SLars-Peter Clausen 8232560b3d1SLars-Peter Clausen regcache_sync(adav80x->regmap); 824cc52688aSLars-Peter Clausen 825cc52688aSLars-Peter Clausen return 0; 826cc52688aSLars-Peter Clausen } 827cc52688aSLars-Peter Clausen 828a0565587SKuninori Morimoto static const struct snd_soc_component_driver adav80x_component_driver = { 829cc52688aSLars-Peter Clausen .probe = adav80x_probe, 830cc52688aSLars-Peter Clausen .resume = adav80x_resume, 831cc52688aSLars-Peter Clausen .set_bias_level = adav80x_set_bias_level, 832cc52688aSLars-Peter Clausen .set_pll = adav80x_set_pll, 833cc52688aSLars-Peter Clausen .set_sysclk = adav80x_set_sysclk, 834cc52688aSLars-Peter Clausen .controls = adav80x_controls, 835cc52688aSLars-Peter Clausen .num_controls = ARRAY_SIZE(adav80x_controls), 836cc52688aSLars-Peter Clausen .dapm_widgets = adav80x_dapm_widgets, 837cc52688aSLars-Peter Clausen .num_dapm_widgets = ARRAY_SIZE(adav80x_dapm_widgets), 838cc52688aSLars-Peter Clausen .dapm_routes = adav80x_dapm_routes, 839cc52688aSLars-Peter Clausen .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes), 840a0565587SKuninori Morimoto .suspend_bias_off = 1, 841a0565587SKuninori Morimoto .idle_bias_on = 1, 842a0565587SKuninori Morimoto .use_pmdown_time = 1, 843a0565587SKuninori Morimoto .endianness = 1, 844a0565587SKuninori Morimoto .non_legacy_dai_naming = 1, 845cc52688aSLars-Peter Clausen }; 846cc52688aSLars-Peter Clausen 8470c2d6964SLars-Peter Clausen int adav80x_bus_probe(struct device *dev, struct regmap *regmap) 848cc52688aSLars-Peter Clausen { 849cc52688aSLars-Peter Clausen struct adav80x *adav80x; 850cc52688aSLars-Peter Clausen 8512560b3d1SLars-Peter Clausen if (IS_ERR(regmap)) 8522560b3d1SLars-Peter Clausen return PTR_ERR(regmap); 8532560b3d1SLars-Peter Clausen 854f96a5d3fSLars-Peter Clausen adav80x = devm_kzalloc(dev, sizeof(*adav80x), GFP_KERNEL); 855cc52688aSLars-Peter Clausen if (!adav80x) 856cc52688aSLars-Peter Clausen return -ENOMEM; 857cc52688aSLars-Peter Clausen 858cc52688aSLars-Peter Clausen dev_set_drvdata(dev, adav80x); 8592560b3d1SLars-Peter Clausen adav80x->regmap = regmap; 860cc52688aSLars-Peter Clausen 861a0565587SKuninori Morimoto return devm_snd_soc_register_component(dev, &adav80x_component_driver, 862cc52688aSLars-Peter Clausen adav80x_dais, ARRAY_SIZE(adav80x_dais)); 863cc52688aSLars-Peter Clausen } 8640c2d6964SLars-Peter Clausen EXPORT_SYMBOL_GPL(adav80x_bus_probe); 865cc52688aSLars-Peter Clausen 8660c2d6964SLars-Peter Clausen const struct regmap_config adav80x_regmap_config = { 8672560b3d1SLars-Peter Clausen .val_bits = 8, 8682560b3d1SLars-Peter Clausen .pad_bits = 1, 8692560b3d1SLars-Peter Clausen .reg_bits = 7, 8702560b3d1SLars-Peter Clausen 8712560b3d1SLars-Peter Clausen .max_register = ADAV80X_PLL_OUTE, 8722560b3d1SLars-Peter Clausen 8732560b3d1SLars-Peter Clausen .cache_type = REGCACHE_RBTREE, 8742560b3d1SLars-Peter Clausen .reg_defaults = adav80x_reg_defaults, 8752560b3d1SLars-Peter Clausen .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults), 8762560b3d1SLars-Peter Clausen }; 8770c2d6964SLars-Peter Clausen EXPORT_SYMBOL_GPL(adav80x_regmap_config); 878cc52688aSLars-Peter Clausen 879cc52688aSLars-Peter Clausen MODULE_DESCRIPTION("ASoC ADAV80x driver"); 880cc52688aSLars-Peter Clausen MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 881cc52688aSLars-Peter Clausen MODULE_AUTHOR("Yi Li <yi.li@analog.com>>"); 882cc52688aSLars-Peter Clausen MODULE_LICENSE("GPL"); 883