1cc52688aSLars-Peter Clausen /* 2cc52688aSLars-Peter Clausen * ADAV80X Audio Codec driver supporting ADAV801, ADAV803 3cc52688aSLars-Peter Clausen * 4cc52688aSLars-Peter Clausen * Copyright 2011 Analog Devices Inc. 5cc52688aSLars-Peter Clausen * Author: Yi Li <yi.li@analog.com> 6cc52688aSLars-Peter Clausen * Author: Lars-Peter Clausen <lars@metafoo.de> 7cc52688aSLars-Peter Clausen * 8cc52688aSLars-Peter Clausen * Licensed under the GPL-2 or later. 9cc52688aSLars-Peter Clausen */ 10cc52688aSLars-Peter Clausen 11cc52688aSLars-Peter Clausen #include <linux/init.h> 12cc52688aSLars-Peter Clausen #include <linux/module.h> 13cc52688aSLars-Peter Clausen #include <linux/kernel.h> 14cc52688aSLars-Peter Clausen #include <linux/i2c.h> 15cc52688aSLars-Peter Clausen #include <linux/spi/spi.h> 16cc52688aSLars-Peter Clausen #include <linux/slab.h> 17cc52688aSLars-Peter Clausen #include <sound/core.h> 18cc52688aSLars-Peter Clausen #include <sound/pcm.h> 19cc52688aSLars-Peter Clausen #include <sound/pcm_params.h> 20cc52688aSLars-Peter Clausen #include <sound/tlv.h> 21cc52688aSLars-Peter Clausen #include <sound/soc.h> 22cc52688aSLars-Peter Clausen 23cc52688aSLars-Peter Clausen #include "adav80x.h" 24cc52688aSLars-Peter Clausen 25cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_CTRL 0x04 26cc52688aSLars-Peter Clausen #define ADAV80X_AUX_IN_CTRL 0x05 27cc52688aSLars-Peter Clausen #define ADAV80X_REC_CTRL 0x06 28cc52688aSLars-Peter Clausen #define ADAV80X_AUX_OUT_CTRL 0x07 29cc52688aSLars-Peter Clausen #define ADAV80X_DPATH_CTRL1 0x62 30cc52688aSLars-Peter Clausen #define ADAV80X_DPATH_CTRL2 0x63 31cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL1 0x64 32cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2 0x65 33cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL3 0x66 34cc52688aSLars-Peter Clausen #define ADAV80X_DAC_L_VOL 0x68 35cc52688aSLars-Peter Clausen #define ADAV80X_DAC_R_VOL 0x69 36cc52688aSLars-Peter Clausen #define ADAV80X_PGA_L_VOL 0x6c 37cc52688aSLars-Peter Clausen #define ADAV80X_PGA_R_VOL 0x6d 38cc52688aSLars-Peter Clausen #define ADAV80X_ADC_CTRL1 0x6e 39cc52688aSLars-Peter Clausen #define ADAV80X_ADC_CTRL2 0x6f 40cc52688aSLars-Peter Clausen #define ADAV80X_ADC_L_VOL 0x70 41cc52688aSLars-Peter Clausen #define ADAV80X_ADC_R_VOL 0x71 42cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL1 0x74 43cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL2 0x75 44cc52688aSLars-Peter Clausen #define ADAV80X_ICLK_CTRL1 0x76 45cc52688aSLars-Peter Clausen #define ADAV80X_ICLK_CTRL2 0x77 46cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CLK_SRC 0x78 47cc52688aSLars-Peter Clausen #define ADAV80X_PLL_OUTE 0x7a 48cc52688aSLars-Peter Clausen 49cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CLK_SRC_PLL_XIN(pll) 0x00 50cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CLK_SRC_PLL_MCLKI(pll) (0x40 << (pll)) 51cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CLK_SRC_PLL_MASK(pll) (0x40 << (pll)) 52cc52688aSLars-Peter Clausen 53cc52688aSLars-Peter Clausen #define ADAV80X_ICLK_CTRL1_DAC_SRC(src) ((src) << 5) 54cc52688aSLars-Peter Clausen #define ADAV80X_ICLK_CTRL1_ADC_SRC(src) ((src) << 2) 55cc52688aSLars-Peter Clausen #define ADAV80X_ICLK_CTRL1_ICLK2_SRC(src) (src) 56cc52688aSLars-Peter Clausen #define ADAV80X_ICLK_CTRL2_ICLK1_SRC(src) ((src) << 3) 57cc52688aSLars-Peter Clausen 58cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL1_PLLDIV 0x10 59cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL1_PLLPD(pll) (0x04 << (pll)) 60cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL1_XTLPD 0x02 61cc52688aSLars-Peter Clausen 62cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL2_FIELD(pll, x) ((x) << ((pll) * 4)) 63cc52688aSLars-Peter Clausen 64cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL2_FS_48(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x00) 65cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL2_FS_32(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x08) 66cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL2_FS_44(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x0c) 67cc52688aSLars-Peter Clausen 68cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL2_SEL(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x02) 69cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL2_DOUB(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x01) 70cc52688aSLars-Peter Clausen #define ADAV80X_PLL_CTRL2_PLL_MASK(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x0f) 71cc52688aSLars-Peter Clausen 72cc52688aSLars-Peter Clausen #define ADAV80X_ADC_CTRL1_MODULATOR_MASK 0x80 73cc52688aSLars-Peter Clausen #define ADAV80X_ADC_CTRL1_MODULATOR_128FS 0x00 74cc52688aSLars-Peter Clausen #define ADAV80X_ADC_CTRL1_MODULATOR_64FS 0x80 75cc52688aSLars-Peter Clausen 76cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL1_PD 0x80 77cc52688aSLars-Peter Clausen 78cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DIV1 0x00 79cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DIV1_5 0x10 80cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DIV2 0x20 81cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DIV3 0x30 82cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DIV_MASK 0x30 83cc52688aSLars-Peter Clausen 84cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_INTERPOL_256FS 0x00 85cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_INTERPOL_128FS 0x40 86cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_INTERPOL_64FS 0x80 87cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_INTERPOL_MASK 0xc0 88cc52688aSLars-Peter Clausen 89cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DEEMPH_NONE 0x00 90cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DEEMPH_44 0x01 91cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DEEMPH_32 0x02 92cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DEEMPH_48 0x03 93cc52688aSLars-Peter Clausen #define ADAV80X_DAC_CTRL2_DEEMPH_MASK 0x01 94cc52688aSLars-Peter Clausen 95cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_MODE_MASTER 0x20 96cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_WORD_LEN24 0x00 97cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_WORD_LEN20 0x04 98cc52688aSLars-Peter Clausen #define ADAV80X_CAPTRUE_WORD_LEN18 0x08 99cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_WORD_LEN16 0x0c 100cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_WORD_LEN_MASK 0x0c 101cc52688aSLars-Peter Clausen 102cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_MODE_LEFT_J 0x00 103cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_MODE_I2S 0x01 104cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_MODE_RIGHT_J 0x03 105cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_MODE_MASK 0x03 106cc52688aSLars-Peter Clausen 107cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_MODE_MASTER 0x10 108cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_MODE_LEFT_J 0x00 109cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_MODE_I2S 0x01 110cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_MODE_RIGHT_J_24 0x04 111cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_MODE_RIGHT_J_20 0x05 112cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_MODE_RIGHT_J_18 0x06 113cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_MODE_RIGHT_J_16 0x07 114cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_MODE_MASK 0x07 115cc52688aSLars-Peter Clausen 116cc52688aSLars-Peter Clausen #define ADAV80X_PLL_OUTE_SYSCLKPD(x) BIT(2 - (x)) 117cc52688aSLars-Peter Clausen 1182560b3d1SLars-Peter Clausen static struct reg_default adav80x_reg_defaults[] = { 1192560b3d1SLars-Peter Clausen { ADAV80X_PLAYBACK_CTRL, 0x01 }, 1202560b3d1SLars-Peter Clausen { ADAV80X_AUX_IN_CTRL, 0x01 }, 1212560b3d1SLars-Peter Clausen { ADAV80X_REC_CTRL, 0x02 }, 1222560b3d1SLars-Peter Clausen { ADAV80X_AUX_OUT_CTRL, 0x01 }, 1232560b3d1SLars-Peter Clausen { ADAV80X_DPATH_CTRL1, 0xc0 }, 1242560b3d1SLars-Peter Clausen { ADAV80X_DPATH_CTRL2, 0x11 }, 1252560b3d1SLars-Peter Clausen { ADAV80X_DAC_CTRL1, 0x00 }, 1262560b3d1SLars-Peter Clausen { ADAV80X_DAC_CTRL2, 0x00 }, 1272560b3d1SLars-Peter Clausen { ADAV80X_DAC_CTRL3, 0x00 }, 1282560b3d1SLars-Peter Clausen { ADAV80X_DAC_L_VOL, 0xff }, 1292560b3d1SLars-Peter Clausen { ADAV80X_DAC_R_VOL, 0xff }, 1302560b3d1SLars-Peter Clausen { ADAV80X_PGA_L_VOL, 0x00 }, 1312560b3d1SLars-Peter Clausen { ADAV80X_PGA_R_VOL, 0x00 }, 1322560b3d1SLars-Peter Clausen { ADAV80X_ADC_CTRL1, 0x00 }, 1332560b3d1SLars-Peter Clausen { ADAV80X_ADC_CTRL2, 0x00 }, 1342560b3d1SLars-Peter Clausen { ADAV80X_ADC_L_VOL, 0xff }, 1352560b3d1SLars-Peter Clausen { ADAV80X_ADC_R_VOL, 0xff }, 1362560b3d1SLars-Peter Clausen { ADAV80X_PLL_CTRL1, 0x00 }, 1372560b3d1SLars-Peter Clausen { ADAV80X_PLL_CTRL2, 0x00 }, 1382560b3d1SLars-Peter Clausen { ADAV80X_ICLK_CTRL1, 0x00 }, 1392560b3d1SLars-Peter Clausen { ADAV80X_ICLK_CTRL2, 0x00 }, 1402560b3d1SLars-Peter Clausen { ADAV80X_PLL_CLK_SRC, 0x00 }, 1412560b3d1SLars-Peter Clausen { ADAV80X_PLL_OUTE, 0x00 }, 142cc52688aSLars-Peter Clausen }; 143cc52688aSLars-Peter Clausen 144cc52688aSLars-Peter Clausen struct adav80x { 1452560b3d1SLars-Peter Clausen struct regmap *regmap; 146cc52688aSLars-Peter Clausen 147cc52688aSLars-Peter Clausen enum adav80x_clk_src clk_src; 148cc52688aSLars-Peter Clausen unsigned int sysclk; 149cc52688aSLars-Peter Clausen enum adav80x_pll_src pll_src; 150cc52688aSLars-Peter Clausen 151cc52688aSLars-Peter Clausen unsigned int dai_fmt[2]; 152cc52688aSLars-Peter Clausen unsigned int rate; 153cc52688aSLars-Peter Clausen bool deemph; 154cc52688aSLars-Peter Clausen bool sysclk_pd[3]; 155cc52688aSLars-Peter Clausen }; 156cc52688aSLars-Peter Clausen 157cc52688aSLars-Peter Clausen static const char *adav80x_mux_text[] = { 158cc52688aSLars-Peter Clausen "ADC", 159cc52688aSLars-Peter Clausen "Playback", 160cc52688aSLars-Peter Clausen "Aux Playback", 161cc52688aSLars-Peter Clausen }; 162cc52688aSLars-Peter Clausen 163cc52688aSLars-Peter Clausen static const unsigned int adav80x_mux_values[] = { 164cc52688aSLars-Peter Clausen 0, 2, 3, 165cc52688aSLars-Peter Clausen }; 166cc52688aSLars-Peter Clausen 167cc52688aSLars-Peter Clausen #define ADAV80X_MUX_ENUM_DECL(name, reg, shift) \ 168cc52688aSLars-Peter Clausen SOC_VALUE_ENUM_DOUBLE_DECL(name, reg, shift, 7, \ 169cc52688aSLars-Peter Clausen ARRAY_SIZE(adav80x_mux_text), adav80x_mux_text, \ 170cc52688aSLars-Peter Clausen adav80x_mux_values) 171cc52688aSLars-Peter Clausen 172cc52688aSLars-Peter Clausen static ADAV80X_MUX_ENUM_DECL(adav80x_aux_capture_enum, ADAV80X_DPATH_CTRL1, 0); 173cc52688aSLars-Peter Clausen static ADAV80X_MUX_ENUM_DECL(adav80x_capture_enum, ADAV80X_DPATH_CTRL1, 3); 174cc52688aSLars-Peter Clausen static ADAV80X_MUX_ENUM_DECL(adav80x_dac_enum, ADAV80X_DPATH_CTRL2, 3); 175cc52688aSLars-Peter Clausen 176cc52688aSLars-Peter Clausen static const struct snd_kcontrol_new adav80x_aux_capture_mux_ctrl = 177cc52688aSLars-Peter Clausen SOC_DAPM_VALUE_ENUM("Route", adav80x_aux_capture_enum); 178cc52688aSLars-Peter Clausen static const struct snd_kcontrol_new adav80x_capture_mux_ctrl = 179cc52688aSLars-Peter Clausen SOC_DAPM_VALUE_ENUM("Route", adav80x_capture_enum); 180cc52688aSLars-Peter Clausen static const struct snd_kcontrol_new adav80x_dac_mux_ctrl = 181cc52688aSLars-Peter Clausen SOC_DAPM_VALUE_ENUM("Route", adav80x_dac_enum); 182cc52688aSLars-Peter Clausen 183cc52688aSLars-Peter Clausen #define ADAV80X_MUX(name, ctrl) \ 184cc52688aSLars-Peter Clausen SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl) 185cc52688aSLars-Peter Clausen 186cc52688aSLars-Peter Clausen static const struct snd_soc_dapm_widget adav80x_dapm_widgets[] = { 187cc52688aSLars-Peter Clausen SND_SOC_DAPM_DAC("DAC", NULL, ADAV80X_DAC_CTRL1, 7, 1), 188cc52688aSLars-Peter Clausen SND_SOC_DAPM_ADC("ADC", NULL, ADAV80X_ADC_CTRL1, 5, 1), 189cc52688aSLars-Peter Clausen 190cc52688aSLars-Peter Clausen SND_SOC_DAPM_PGA("Right PGA", ADAV80X_ADC_CTRL1, 0, 1, NULL, 0), 191cc52688aSLars-Peter Clausen SND_SOC_DAPM_PGA("Left PGA", ADAV80X_ADC_CTRL1, 1, 1, NULL, 0), 192cc52688aSLars-Peter Clausen 193cc52688aSLars-Peter Clausen SND_SOC_DAPM_AIF_OUT("AIFOUT", "HiFi Capture", 0, SND_SOC_NOPM, 0, 0), 194cc52688aSLars-Peter Clausen SND_SOC_DAPM_AIF_IN("AIFIN", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0), 195cc52688aSLars-Peter Clausen 196cc52688aSLars-Peter Clausen SND_SOC_DAPM_AIF_OUT("AIFAUXOUT", "Aux Capture", 0, SND_SOC_NOPM, 0, 0), 197cc52688aSLars-Peter Clausen SND_SOC_DAPM_AIF_IN("AIFAUXIN", "Aux Playback", 0, SND_SOC_NOPM, 0, 0), 198cc52688aSLars-Peter Clausen 199cc52688aSLars-Peter Clausen ADAV80X_MUX("Aux Capture Select", &adav80x_aux_capture_mux_ctrl), 200cc52688aSLars-Peter Clausen ADAV80X_MUX("Capture Select", &adav80x_capture_mux_ctrl), 201cc52688aSLars-Peter Clausen ADAV80X_MUX("DAC Select", &adav80x_dac_mux_ctrl), 202cc52688aSLars-Peter Clausen 203cc52688aSLars-Peter Clausen SND_SOC_DAPM_INPUT("VINR"), 204cc52688aSLars-Peter Clausen SND_SOC_DAPM_INPUT("VINL"), 205cc52688aSLars-Peter Clausen SND_SOC_DAPM_OUTPUT("VOUTR"), 206cc52688aSLars-Peter Clausen SND_SOC_DAPM_OUTPUT("VOUTL"), 207cc52688aSLars-Peter Clausen 208cc52688aSLars-Peter Clausen SND_SOC_DAPM_SUPPLY("SYSCLK", SND_SOC_NOPM, 0, 0, NULL, 0), 209cc52688aSLars-Peter Clausen SND_SOC_DAPM_SUPPLY("PLL1", ADAV80X_PLL_CTRL1, 2, 1, NULL, 0), 210cc52688aSLars-Peter Clausen SND_SOC_DAPM_SUPPLY("PLL2", ADAV80X_PLL_CTRL1, 3, 1, NULL, 0), 211cc52688aSLars-Peter Clausen SND_SOC_DAPM_SUPPLY("OSC", ADAV80X_PLL_CTRL1, 1, 1, NULL, 0), 212cc52688aSLars-Peter Clausen }; 213cc52688aSLars-Peter Clausen 214cc52688aSLars-Peter Clausen static int adav80x_dapm_sysclk_check(struct snd_soc_dapm_widget *source, 215cc52688aSLars-Peter Clausen struct snd_soc_dapm_widget *sink) 216cc52688aSLars-Peter Clausen { 217cc52688aSLars-Peter Clausen struct snd_soc_codec *codec = source->codec; 218cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 219cc52688aSLars-Peter Clausen const char *clk; 220cc52688aSLars-Peter Clausen 221cc52688aSLars-Peter Clausen switch (adav80x->clk_src) { 222cc52688aSLars-Peter Clausen case ADAV80X_CLK_PLL1: 223cc52688aSLars-Peter Clausen clk = "PLL1"; 224cc52688aSLars-Peter Clausen break; 225cc52688aSLars-Peter Clausen case ADAV80X_CLK_PLL2: 226cc52688aSLars-Peter Clausen clk = "PLL2"; 227cc52688aSLars-Peter Clausen break; 228cc52688aSLars-Peter Clausen case ADAV80X_CLK_XTAL: 229cc52688aSLars-Peter Clausen clk = "OSC"; 230cc52688aSLars-Peter Clausen break; 231cc52688aSLars-Peter Clausen default: 232cc52688aSLars-Peter Clausen return 0; 233cc52688aSLars-Peter Clausen } 234cc52688aSLars-Peter Clausen 235cc52688aSLars-Peter Clausen return strcmp(source->name, clk) == 0; 236cc52688aSLars-Peter Clausen } 237cc52688aSLars-Peter Clausen 238cc52688aSLars-Peter Clausen static int adav80x_dapm_pll_check(struct snd_soc_dapm_widget *source, 239cc52688aSLars-Peter Clausen struct snd_soc_dapm_widget *sink) 240cc52688aSLars-Peter Clausen { 241cc52688aSLars-Peter Clausen struct snd_soc_codec *codec = source->codec; 242cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 243cc52688aSLars-Peter Clausen 244cc52688aSLars-Peter Clausen return adav80x->pll_src == ADAV80X_PLL_SRC_XTAL; 245cc52688aSLars-Peter Clausen } 246cc52688aSLars-Peter Clausen 247cc52688aSLars-Peter Clausen 248cc52688aSLars-Peter Clausen static const struct snd_soc_dapm_route adav80x_dapm_routes[] = { 249cc52688aSLars-Peter Clausen { "DAC Select", "ADC", "ADC" }, 250cc52688aSLars-Peter Clausen { "DAC Select", "Playback", "AIFIN" }, 251cc52688aSLars-Peter Clausen { "DAC Select", "Aux Playback", "AIFAUXIN" }, 252cc52688aSLars-Peter Clausen { "DAC", NULL, "DAC Select" }, 253cc52688aSLars-Peter Clausen 254cc52688aSLars-Peter Clausen { "Capture Select", "ADC", "ADC" }, 255cc52688aSLars-Peter Clausen { "Capture Select", "Playback", "AIFIN" }, 256cc52688aSLars-Peter Clausen { "Capture Select", "Aux Playback", "AIFAUXIN" }, 257cc52688aSLars-Peter Clausen { "AIFOUT", NULL, "Capture Select" }, 258cc52688aSLars-Peter Clausen 259cc52688aSLars-Peter Clausen { "Aux Capture Select", "ADC", "ADC" }, 260cc52688aSLars-Peter Clausen { "Aux Capture Select", "Playback", "AIFIN" }, 261cc52688aSLars-Peter Clausen { "Aux Capture Select", "Aux Playback", "AIFAUXIN" }, 262cc52688aSLars-Peter Clausen { "AIFAUXOUT", NULL, "Aux Capture Select" }, 263cc52688aSLars-Peter Clausen 264cc52688aSLars-Peter Clausen { "VOUTR", NULL, "DAC" }, 265cc52688aSLars-Peter Clausen { "VOUTL", NULL, "DAC" }, 266cc52688aSLars-Peter Clausen 267cc52688aSLars-Peter Clausen { "Left PGA", NULL, "VINL" }, 268cc52688aSLars-Peter Clausen { "Right PGA", NULL, "VINR" }, 269cc52688aSLars-Peter Clausen { "ADC", NULL, "Left PGA" }, 270cc52688aSLars-Peter Clausen { "ADC", NULL, "Right PGA" }, 271cc52688aSLars-Peter Clausen 272cc52688aSLars-Peter Clausen { "SYSCLK", NULL, "PLL1", adav80x_dapm_sysclk_check }, 273cc52688aSLars-Peter Clausen { "SYSCLK", NULL, "PLL2", adav80x_dapm_sysclk_check }, 274cc52688aSLars-Peter Clausen { "SYSCLK", NULL, "OSC", adav80x_dapm_sysclk_check }, 275cc52688aSLars-Peter Clausen { "PLL1", NULL, "OSC", adav80x_dapm_pll_check }, 276cc52688aSLars-Peter Clausen { "PLL2", NULL, "OSC", adav80x_dapm_pll_check }, 277cc52688aSLars-Peter Clausen 278cc52688aSLars-Peter Clausen { "ADC", NULL, "SYSCLK" }, 279cc52688aSLars-Peter Clausen { "DAC", NULL, "SYSCLK" }, 280cc52688aSLars-Peter Clausen { "AIFOUT", NULL, "SYSCLK" }, 281cc52688aSLars-Peter Clausen { "AIFAUXOUT", NULL, "SYSCLK" }, 282cc52688aSLars-Peter Clausen { "AIFIN", NULL, "SYSCLK" }, 283cc52688aSLars-Peter Clausen { "AIFAUXIN", NULL, "SYSCLK" }, 284cc52688aSLars-Peter Clausen }; 285cc52688aSLars-Peter Clausen 286cc52688aSLars-Peter Clausen static int adav80x_set_deemph(struct snd_soc_codec *codec) 287cc52688aSLars-Peter Clausen { 288cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 289cc52688aSLars-Peter Clausen unsigned int val; 290cc52688aSLars-Peter Clausen 291cc52688aSLars-Peter Clausen if (adav80x->deemph) { 292cc52688aSLars-Peter Clausen switch (adav80x->rate) { 293cc52688aSLars-Peter Clausen case 32000: 294cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DEEMPH_32; 295cc52688aSLars-Peter Clausen break; 296cc52688aSLars-Peter Clausen case 44100: 297cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DEEMPH_44; 298cc52688aSLars-Peter Clausen break; 299cc52688aSLars-Peter Clausen case 48000: 300cc52688aSLars-Peter Clausen case 64000: 301cc52688aSLars-Peter Clausen case 88200: 302cc52688aSLars-Peter Clausen case 96000: 303cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DEEMPH_48; 304cc52688aSLars-Peter Clausen break; 305cc52688aSLars-Peter Clausen default: 306cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DEEMPH_NONE; 307cc52688aSLars-Peter Clausen break; 308cc52688aSLars-Peter Clausen } 309cc52688aSLars-Peter Clausen } else { 310cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DEEMPH_NONE; 311cc52688aSLars-Peter Clausen } 312cc52688aSLars-Peter Clausen 3132560b3d1SLars-Peter Clausen return regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL2, 314cc52688aSLars-Peter Clausen ADAV80X_DAC_CTRL2_DEEMPH_MASK, val); 315cc52688aSLars-Peter Clausen } 316cc52688aSLars-Peter Clausen 317cc52688aSLars-Peter Clausen static int adav80x_put_deemph(struct snd_kcontrol *kcontrol, 318cc52688aSLars-Peter Clausen struct snd_ctl_elem_value *ucontrol) 319cc52688aSLars-Peter Clausen { 320cc52688aSLars-Peter Clausen struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 321cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 322cc52688aSLars-Peter Clausen unsigned int deemph = ucontrol->value.enumerated.item[0]; 323cc52688aSLars-Peter Clausen 324cc52688aSLars-Peter Clausen if (deemph > 1) 325cc52688aSLars-Peter Clausen return -EINVAL; 326cc52688aSLars-Peter Clausen 327cc52688aSLars-Peter Clausen adav80x->deemph = deemph; 328cc52688aSLars-Peter Clausen 329cc52688aSLars-Peter Clausen return adav80x_set_deemph(codec); 330cc52688aSLars-Peter Clausen } 331cc52688aSLars-Peter Clausen 332cc52688aSLars-Peter Clausen static int adav80x_get_deemph(struct snd_kcontrol *kcontrol, 333cc52688aSLars-Peter Clausen struct snd_ctl_elem_value *ucontrol) 334cc52688aSLars-Peter Clausen { 335cc52688aSLars-Peter Clausen struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 336cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 337cc52688aSLars-Peter Clausen 338cc52688aSLars-Peter Clausen ucontrol->value.enumerated.item[0] = adav80x->deemph; 339cc52688aSLars-Peter Clausen return 0; 340cc52688aSLars-Peter Clausen }; 341cc52688aSLars-Peter Clausen 342cc52688aSLars-Peter Clausen static const DECLARE_TLV_DB_SCALE(adav80x_inpga_tlv, 0, 50, 0); 343cc52688aSLars-Peter Clausen static const DECLARE_TLV_DB_MINMAX(adav80x_digital_tlv, -9563, 0); 344cc52688aSLars-Peter Clausen 345cc52688aSLars-Peter Clausen static const struct snd_kcontrol_new adav80x_controls[] = { 346cc52688aSLars-Peter Clausen SOC_DOUBLE_R_TLV("Master Playback Volume", ADAV80X_DAC_L_VOL, 347cc52688aSLars-Peter Clausen ADAV80X_DAC_R_VOL, 0, 0xff, 0, adav80x_digital_tlv), 348cc52688aSLars-Peter Clausen SOC_DOUBLE_R_TLV("Master Capture Volume", ADAV80X_ADC_L_VOL, 349cc52688aSLars-Peter Clausen ADAV80X_ADC_R_VOL, 0, 0xff, 0, adav80x_digital_tlv), 350cc52688aSLars-Peter Clausen 351cc52688aSLars-Peter Clausen SOC_DOUBLE_R_TLV("PGA Capture Volume", ADAV80X_PGA_L_VOL, 352cc52688aSLars-Peter Clausen ADAV80X_PGA_R_VOL, 0, 0x30, 0, adav80x_inpga_tlv), 353cc52688aSLars-Peter Clausen 354cc52688aSLars-Peter Clausen SOC_DOUBLE("Master Playback Switch", ADAV80X_DAC_CTRL1, 0, 1, 1, 0), 355cc52688aSLars-Peter Clausen SOC_DOUBLE("Master Capture Switch", ADAV80X_ADC_CTRL1, 2, 3, 1, 1), 356cc52688aSLars-Peter Clausen 357cc52688aSLars-Peter Clausen SOC_SINGLE("ADC High Pass Filter Switch", ADAV80X_ADC_CTRL1, 6, 1, 0), 358cc52688aSLars-Peter Clausen 359cc52688aSLars-Peter Clausen SOC_SINGLE_BOOL_EXT("Playback De-emphasis Switch", 0, 360cc52688aSLars-Peter Clausen adav80x_get_deemph, adav80x_put_deemph), 361cc52688aSLars-Peter Clausen }; 362cc52688aSLars-Peter Clausen 363cc52688aSLars-Peter Clausen static unsigned int adav80x_port_ctrl_regs[2][2] = { 364cc52688aSLars-Peter Clausen { ADAV80X_REC_CTRL, ADAV80X_PLAYBACK_CTRL, }, 365cc52688aSLars-Peter Clausen { ADAV80X_AUX_OUT_CTRL, ADAV80X_AUX_IN_CTRL }, 366cc52688aSLars-Peter Clausen }; 367cc52688aSLars-Peter Clausen 368cc52688aSLars-Peter Clausen static int adav80x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 369cc52688aSLars-Peter Clausen { 370cc52688aSLars-Peter Clausen struct snd_soc_codec *codec = dai->codec; 371cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 372cc52688aSLars-Peter Clausen unsigned int capture = 0x00; 373cc52688aSLars-Peter Clausen unsigned int playback = 0x00; 374cc52688aSLars-Peter Clausen 375cc52688aSLars-Peter Clausen switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 376cc52688aSLars-Peter Clausen case SND_SOC_DAIFMT_CBM_CFM: 377cc52688aSLars-Peter Clausen capture |= ADAV80X_CAPTURE_MODE_MASTER; 378cc52688aSLars-Peter Clausen playback |= ADAV80X_PLAYBACK_MODE_MASTER; 379cc52688aSLars-Peter Clausen case SND_SOC_DAIFMT_CBS_CFS: 380cc52688aSLars-Peter Clausen break; 381cc52688aSLars-Peter Clausen default: 382cc52688aSLars-Peter Clausen return -EINVAL; 383cc52688aSLars-Peter Clausen } 384cc52688aSLars-Peter Clausen 385cc52688aSLars-Peter Clausen switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 386cc52688aSLars-Peter Clausen case SND_SOC_DAIFMT_I2S: 387cc52688aSLars-Peter Clausen capture |= ADAV80X_CAPTURE_MODE_I2S; 388cc52688aSLars-Peter Clausen playback |= ADAV80X_PLAYBACK_MODE_I2S; 389cc52688aSLars-Peter Clausen break; 390cc52688aSLars-Peter Clausen case SND_SOC_DAIFMT_LEFT_J: 391cc52688aSLars-Peter Clausen capture |= ADAV80X_CAPTURE_MODE_LEFT_J; 392cc52688aSLars-Peter Clausen playback |= ADAV80X_PLAYBACK_MODE_LEFT_J; 393cc52688aSLars-Peter Clausen break; 394cc52688aSLars-Peter Clausen case SND_SOC_DAIFMT_RIGHT_J: 395cc52688aSLars-Peter Clausen capture |= ADAV80X_CAPTURE_MODE_RIGHT_J; 396cc52688aSLars-Peter Clausen playback |= ADAV80X_PLAYBACK_MODE_RIGHT_J_24; 397cc52688aSLars-Peter Clausen break; 398cc52688aSLars-Peter Clausen default: 399cc52688aSLars-Peter Clausen return -EINVAL; 400cc52688aSLars-Peter Clausen } 401cc52688aSLars-Peter Clausen 402cc52688aSLars-Peter Clausen switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 403cc52688aSLars-Peter Clausen case SND_SOC_DAIFMT_NB_NF: 404cc52688aSLars-Peter Clausen break; 405cc52688aSLars-Peter Clausen default: 406cc52688aSLars-Peter Clausen return -EINVAL; 407cc52688aSLars-Peter Clausen } 408cc52688aSLars-Peter Clausen 4092560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][0], 410cc52688aSLars-Peter Clausen ADAV80X_CAPTURE_MODE_MASK | ADAV80X_CAPTURE_MODE_MASTER, 411cc52688aSLars-Peter Clausen capture); 4122560b3d1SLars-Peter Clausen regmap_write(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][1], 4132560b3d1SLars-Peter Clausen playback); 414cc52688aSLars-Peter Clausen 415cc52688aSLars-Peter Clausen adav80x->dai_fmt[dai->id] = fmt & SND_SOC_DAIFMT_FORMAT_MASK; 416cc52688aSLars-Peter Clausen 417cc52688aSLars-Peter Clausen return 0; 418cc52688aSLars-Peter Clausen } 419cc52688aSLars-Peter Clausen 420cc52688aSLars-Peter Clausen static int adav80x_set_adc_clock(struct snd_soc_codec *codec, 421cc52688aSLars-Peter Clausen unsigned int sample_rate) 422cc52688aSLars-Peter Clausen { 4232560b3d1SLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 424cc52688aSLars-Peter Clausen unsigned int val; 425cc52688aSLars-Peter Clausen 426cc52688aSLars-Peter Clausen if (sample_rate <= 48000) 427cc52688aSLars-Peter Clausen val = ADAV80X_ADC_CTRL1_MODULATOR_128FS; 428cc52688aSLars-Peter Clausen else 429cc52688aSLars-Peter Clausen val = ADAV80X_ADC_CTRL1_MODULATOR_64FS; 430cc52688aSLars-Peter Clausen 4312560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, ADAV80X_ADC_CTRL1, 432cc52688aSLars-Peter Clausen ADAV80X_ADC_CTRL1_MODULATOR_MASK, val); 433cc52688aSLars-Peter Clausen 434cc52688aSLars-Peter Clausen return 0; 435cc52688aSLars-Peter Clausen } 436cc52688aSLars-Peter Clausen 437cc52688aSLars-Peter Clausen static int adav80x_set_dac_clock(struct snd_soc_codec *codec, 438cc52688aSLars-Peter Clausen unsigned int sample_rate) 439cc52688aSLars-Peter Clausen { 4402560b3d1SLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 441cc52688aSLars-Peter Clausen unsigned int val; 442cc52688aSLars-Peter Clausen 443cc52688aSLars-Peter Clausen if (sample_rate <= 48000) 444cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DIV1 | ADAV80X_DAC_CTRL2_INTERPOL_256FS; 445cc52688aSLars-Peter Clausen else 446cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DIV2 | ADAV80X_DAC_CTRL2_INTERPOL_128FS; 447cc52688aSLars-Peter Clausen 4482560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL2, 449cc52688aSLars-Peter Clausen ADAV80X_DAC_CTRL2_DIV_MASK | ADAV80X_DAC_CTRL2_INTERPOL_MASK, 450cc52688aSLars-Peter Clausen val); 451cc52688aSLars-Peter Clausen 452cc52688aSLars-Peter Clausen return 0; 453cc52688aSLars-Peter Clausen } 454cc52688aSLars-Peter Clausen 455cc52688aSLars-Peter Clausen static int adav80x_set_capture_pcm_format(struct snd_soc_codec *codec, 456cc52688aSLars-Peter Clausen struct snd_soc_dai *dai, snd_pcm_format_t format) 457cc52688aSLars-Peter Clausen { 4582560b3d1SLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 459cc52688aSLars-Peter Clausen unsigned int val; 460cc52688aSLars-Peter Clausen 461cc52688aSLars-Peter Clausen switch (format) { 462cc52688aSLars-Peter Clausen case SNDRV_PCM_FORMAT_S16_LE: 463cc52688aSLars-Peter Clausen val = ADAV80X_CAPTURE_WORD_LEN16; 464cc52688aSLars-Peter Clausen break; 465cc52688aSLars-Peter Clausen case SNDRV_PCM_FORMAT_S18_3LE: 466cc52688aSLars-Peter Clausen val = ADAV80X_CAPTRUE_WORD_LEN18; 467cc52688aSLars-Peter Clausen break; 468cc52688aSLars-Peter Clausen case SNDRV_PCM_FORMAT_S20_3LE: 469cc52688aSLars-Peter Clausen val = ADAV80X_CAPTURE_WORD_LEN20; 470cc52688aSLars-Peter Clausen break; 471cc52688aSLars-Peter Clausen case SNDRV_PCM_FORMAT_S24_LE: 472cc52688aSLars-Peter Clausen val = ADAV80X_CAPTURE_WORD_LEN24; 473cc52688aSLars-Peter Clausen break; 474cc52688aSLars-Peter Clausen default: 475ca1004baSMark Brown return -EINVAL; 476cc52688aSLars-Peter Clausen } 477cc52688aSLars-Peter Clausen 4782560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][0], 479cc52688aSLars-Peter Clausen ADAV80X_CAPTURE_WORD_LEN_MASK, val); 480cc52688aSLars-Peter Clausen 481cc52688aSLars-Peter Clausen return 0; 482cc52688aSLars-Peter Clausen } 483cc52688aSLars-Peter Clausen 484cc52688aSLars-Peter Clausen static int adav80x_set_playback_pcm_format(struct snd_soc_codec *codec, 485cc52688aSLars-Peter Clausen struct snd_soc_dai *dai, snd_pcm_format_t format) 486cc52688aSLars-Peter Clausen { 487cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 488cc52688aSLars-Peter Clausen unsigned int val; 489cc52688aSLars-Peter Clausen 490cc52688aSLars-Peter Clausen if (adav80x->dai_fmt[dai->id] != SND_SOC_DAIFMT_RIGHT_J) 491cc52688aSLars-Peter Clausen return 0; 492cc52688aSLars-Peter Clausen 493cc52688aSLars-Peter Clausen switch (format) { 494cc52688aSLars-Peter Clausen case SNDRV_PCM_FORMAT_S16_LE: 495cc52688aSLars-Peter Clausen val = ADAV80X_PLAYBACK_MODE_RIGHT_J_16; 496cc52688aSLars-Peter Clausen break; 497cc52688aSLars-Peter Clausen case SNDRV_PCM_FORMAT_S18_3LE: 498cc52688aSLars-Peter Clausen val = ADAV80X_PLAYBACK_MODE_RIGHT_J_18; 499cc52688aSLars-Peter Clausen break; 500cc52688aSLars-Peter Clausen case SNDRV_PCM_FORMAT_S20_3LE: 501cc52688aSLars-Peter Clausen val = ADAV80X_PLAYBACK_MODE_RIGHT_J_20; 502cc52688aSLars-Peter Clausen break; 503cc52688aSLars-Peter Clausen case SNDRV_PCM_FORMAT_S24_LE: 504cc52688aSLars-Peter Clausen val = ADAV80X_PLAYBACK_MODE_RIGHT_J_24; 505cc52688aSLars-Peter Clausen break; 506cc52688aSLars-Peter Clausen default: 507ca1004baSMark Brown return -EINVAL; 508cc52688aSLars-Peter Clausen } 509cc52688aSLars-Peter Clausen 5102560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][1], 511cc52688aSLars-Peter Clausen ADAV80X_PLAYBACK_MODE_MASK, val); 512cc52688aSLars-Peter Clausen 513cc52688aSLars-Peter Clausen return 0; 514cc52688aSLars-Peter Clausen } 515cc52688aSLars-Peter Clausen 516cc52688aSLars-Peter Clausen static int adav80x_hw_params(struct snd_pcm_substream *substream, 517cc52688aSLars-Peter Clausen struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 518cc52688aSLars-Peter Clausen { 519cc52688aSLars-Peter Clausen struct snd_soc_codec *codec = dai->codec; 520cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 521cc52688aSLars-Peter Clausen unsigned int rate = params_rate(params); 522cc52688aSLars-Peter Clausen 523cc52688aSLars-Peter Clausen if (rate * 256 != adav80x->sysclk) 524cc52688aSLars-Peter Clausen return -EINVAL; 525cc52688aSLars-Peter Clausen 526cc52688aSLars-Peter Clausen if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 527cc52688aSLars-Peter Clausen adav80x_set_playback_pcm_format(codec, dai, 528cc52688aSLars-Peter Clausen params_format(params)); 529cc52688aSLars-Peter Clausen adav80x_set_dac_clock(codec, rate); 530cc52688aSLars-Peter Clausen } else { 531cc52688aSLars-Peter Clausen adav80x_set_capture_pcm_format(codec, dai, 532cc52688aSLars-Peter Clausen params_format(params)); 533cc52688aSLars-Peter Clausen adav80x_set_adc_clock(codec, rate); 534cc52688aSLars-Peter Clausen } 535cc52688aSLars-Peter Clausen adav80x->rate = rate; 536cc52688aSLars-Peter Clausen adav80x_set_deemph(codec); 537cc52688aSLars-Peter Clausen 538cc52688aSLars-Peter Clausen return 0; 539cc52688aSLars-Peter Clausen } 540cc52688aSLars-Peter Clausen 541cc52688aSLars-Peter Clausen static int adav80x_set_sysclk(struct snd_soc_codec *codec, 542da1c6ea6SMark Brown int clk_id, int source, 543da1c6ea6SMark Brown unsigned int freq, int dir) 544cc52688aSLars-Peter Clausen { 545cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 546cc52688aSLars-Peter Clausen 547cc52688aSLars-Peter Clausen if (dir == SND_SOC_CLOCK_IN) { 548cc52688aSLars-Peter Clausen switch (clk_id) { 549cc52688aSLars-Peter Clausen case ADAV80X_CLK_XIN: 550cc52688aSLars-Peter Clausen case ADAV80X_CLK_XTAL: 551cc52688aSLars-Peter Clausen case ADAV80X_CLK_MCLKI: 552cc52688aSLars-Peter Clausen case ADAV80X_CLK_PLL1: 553cc52688aSLars-Peter Clausen case ADAV80X_CLK_PLL2: 554cc52688aSLars-Peter Clausen break; 555cc52688aSLars-Peter Clausen default: 556cc52688aSLars-Peter Clausen return -EINVAL; 557cc52688aSLars-Peter Clausen } 558cc52688aSLars-Peter Clausen 559cc52688aSLars-Peter Clausen adav80x->sysclk = freq; 560cc52688aSLars-Peter Clausen 561cc52688aSLars-Peter Clausen if (adav80x->clk_src != clk_id) { 562cc52688aSLars-Peter Clausen unsigned int iclk_ctrl1, iclk_ctrl2; 563cc52688aSLars-Peter Clausen 564cc52688aSLars-Peter Clausen adav80x->clk_src = clk_id; 565cc52688aSLars-Peter Clausen if (clk_id == ADAV80X_CLK_XTAL) 566cc52688aSLars-Peter Clausen clk_id = ADAV80X_CLK_XIN; 567cc52688aSLars-Peter Clausen 568cc52688aSLars-Peter Clausen iclk_ctrl1 = ADAV80X_ICLK_CTRL1_DAC_SRC(clk_id) | 569cc52688aSLars-Peter Clausen ADAV80X_ICLK_CTRL1_ADC_SRC(clk_id) | 570cc52688aSLars-Peter Clausen ADAV80X_ICLK_CTRL1_ICLK2_SRC(clk_id); 571cc52688aSLars-Peter Clausen iclk_ctrl2 = ADAV80X_ICLK_CTRL2_ICLK1_SRC(clk_id); 572cc52688aSLars-Peter Clausen 5732560b3d1SLars-Peter Clausen regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL1, 5742560b3d1SLars-Peter Clausen iclk_ctrl1); 5752560b3d1SLars-Peter Clausen regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL2, 5762560b3d1SLars-Peter Clausen iclk_ctrl2); 577cc52688aSLars-Peter Clausen 578cc52688aSLars-Peter Clausen snd_soc_dapm_sync(&codec->dapm); 579cc52688aSLars-Peter Clausen } 580cc52688aSLars-Peter Clausen } else { 581cc52688aSLars-Peter Clausen unsigned int mask; 582cc52688aSLars-Peter Clausen 583cc52688aSLars-Peter Clausen switch (clk_id) { 584cc52688aSLars-Peter Clausen case ADAV80X_CLK_SYSCLK1: 585cc52688aSLars-Peter Clausen case ADAV80X_CLK_SYSCLK2: 586cc52688aSLars-Peter Clausen case ADAV80X_CLK_SYSCLK3: 587cc52688aSLars-Peter Clausen break; 588cc52688aSLars-Peter Clausen default: 589cc52688aSLars-Peter Clausen return -EINVAL; 590cc52688aSLars-Peter Clausen } 591cc52688aSLars-Peter Clausen 592cc52688aSLars-Peter Clausen clk_id -= ADAV80X_CLK_SYSCLK1; 593cc52688aSLars-Peter Clausen mask = ADAV80X_PLL_OUTE_SYSCLKPD(clk_id); 594cc52688aSLars-Peter Clausen 595cc52688aSLars-Peter Clausen if (freq == 0) { 5962560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, ADAV80X_PLL_OUTE, 5972560b3d1SLars-Peter Clausen mask, mask); 598cc52688aSLars-Peter Clausen adav80x->sysclk_pd[clk_id] = true; 599cc52688aSLars-Peter Clausen } else { 6002560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, ADAV80X_PLL_OUTE, 6012560b3d1SLars-Peter Clausen mask, 0); 602cc52688aSLars-Peter Clausen adav80x->sysclk_pd[clk_id] = false; 603cc52688aSLars-Peter Clausen } 604cc52688aSLars-Peter Clausen 605cc52688aSLars-Peter Clausen if (adav80x->sysclk_pd[0]) 606cc52688aSLars-Peter Clausen snd_soc_dapm_disable_pin(&codec->dapm, "PLL1"); 607cc52688aSLars-Peter Clausen else 608cc52688aSLars-Peter Clausen snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); 609cc52688aSLars-Peter Clausen 610cc52688aSLars-Peter Clausen if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2]) 611cc52688aSLars-Peter Clausen snd_soc_dapm_disable_pin(&codec->dapm, "PLL2"); 612cc52688aSLars-Peter Clausen else 613cc52688aSLars-Peter Clausen snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); 614cc52688aSLars-Peter Clausen 615cc52688aSLars-Peter Clausen snd_soc_dapm_sync(&codec->dapm); 616cc52688aSLars-Peter Clausen } 617cc52688aSLars-Peter Clausen 618cc52688aSLars-Peter Clausen return 0; 619cc52688aSLars-Peter Clausen } 620cc52688aSLars-Peter Clausen 621cc52688aSLars-Peter Clausen static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id, 622cc52688aSLars-Peter Clausen int source, unsigned int freq_in, unsigned int freq_out) 623cc52688aSLars-Peter Clausen { 624cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 625cc52688aSLars-Peter Clausen unsigned int pll_ctrl1 = 0; 626cc52688aSLars-Peter Clausen unsigned int pll_ctrl2 = 0; 627cc52688aSLars-Peter Clausen unsigned int pll_src; 628cc52688aSLars-Peter Clausen 629cc52688aSLars-Peter Clausen switch (source) { 630cc52688aSLars-Peter Clausen case ADAV80X_PLL_SRC_XTAL: 631cc52688aSLars-Peter Clausen case ADAV80X_PLL_SRC_XIN: 632cc52688aSLars-Peter Clausen case ADAV80X_PLL_SRC_MCLKI: 633cc52688aSLars-Peter Clausen break; 634cc52688aSLars-Peter Clausen default: 635cc52688aSLars-Peter Clausen return -EINVAL; 636cc52688aSLars-Peter Clausen } 637cc52688aSLars-Peter Clausen 638cc52688aSLars-Peter Clausen if (!freq_out) 639cc52688aSLars-Peter Clausen return 0; 640cc52688aSLars-Peter Clausen 641cc52688aSLars-Peter Clausen switch (freq_in) { 642cc52688aSLars-Peter Clausen case 27000000: 643cc52688aSLars-Peter Clausen break; 644cc52688aSLars-Peter Clausen case 54000000: 645cc52688aSLars-Peter Clausen if (source == ADAV80X_PLL_SRC_XIN) { 646cc52688aSLars-Peter Clausen pll_ctrl1 |= ADAV80X_PLL_CTRL1_PLLDIV; 647cc52688aSLars-Peter Clausen break; 648cc52688aSLars-Peter Clausen } 649cc52688aSLars-Peter Clausen default: 650cc52688aSLars-Peter Clausen return -EINVAL; 651cc52688aSLars-Peter Clausen } 652cc52688aSLars-Peter Clausen 653cc52688aSLars-Peter Clausen if (freq_out > 12288000) { 654cc52688aSLars-Peter Clausen pll_ctrl2 |= ADAV80X_PLL_CTRL2_DOUB(pll_id); 655cc52688aSLars-Peter Clausen freq_out /= 2; 656cc52688aSLars-Peter Clausen } 657cc52688aSLars-Peter Clausen 658cc52688aSLars-Peter Clausen /* freq_out = sample_rate * 256 */ 659cc52688aSLars-Peter Clausen switch (freq_out) { 660cc52688aSLars-Peter Clausen case 8192000: 661cc52688aSLars-Peter Clausen pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_32(pll_id); 662cc52688aSLars-Peter Clausen break; 663cc52688aSLars-Peter Clausen case 11289600: 664cc52688aSLars-Peter Clausen pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_44(pll_id); 665cc52688aSLars-Peter Clausen break; 666cc52688aSLars-Peter Clausen case 12288000: 667cc52688aSLars-Peter Clausen pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_48(pll_id); 668cc52688aSLars-Peter Clausen break; 669cc52688aSLars-Peter Clausen default: 670cc52688aSLars-Peter Clausen return -EINVAL; 671cc52688aSLars-Peter Clausen } 672cc52688aSLars-Peter Clausen 6732560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, ADAV80X_PLL_CTRL1, 6742560b3d1SLars-Peter Clausen ADAV80X_PLL_CTRL1_PLLDIV, pll_ctrl1); 6752560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, ADAV80X_PLL_CTRL2, 676cc52688aSLars-Peter Clausen ADAV80X_PLL_CTRL2_PLL_MASK(pll_id), pll_ctrl2); 677cc52688aSLars-Peter Clausen 678cc52688aSLars-Peter Clausen if (source != adav80x->pll_src) { 679cc52688aSLars-Peter Clausen if (source == ADAV80X_PLL_SRC_MCLKI) 680cc52688aSLars-Peter Clausen pll_src = ADAV80X_PLL_CLK_SRC_PLL_MCLKI(pll_id); 681cc52688aSLars-Peter Clausen else 682cc52688aSLars-Peter Clausen pll_src = ADAV80X_PLL_CLK_SRC_PLL_XIN(pll_id); 683cc52688aSLars-Peter Clausen 6842560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, ADAV80X_PLL_CLK_SRC, 685cc52688aSLars-Peter Clausen ADAV80X_PLL_CLK_SRC_PLL_MASK(pll_id), pll_src); 686cc52688aSLars-Peter Clausen 687cc52688aSLars-Peter Clausen adav80x->pll_src = source; 688cc52688aSLars-Peter Clausen 689cc52688aSLars-Peter Clausen snd_soc_dapm_sync(&codec->dapm); 690cc52688aSLars-Peter Clausen } 691cc52688aSLars-Peter Clausen 692cc52688aSLars-Peter Clausen return 0; 693cc52688aSLars-Peter Clausen } 694cc52688aSLars-Peter Clausen 695cc52688aSLars-Peter Clausen static int adav80x_set_bias_level(struct snd_soc_codec *codec, 696cc52688aSLars-Peter Clausen enum snd_soc_bias_level level) 697cc52688aSLars-Peter Clausen { 6982560b3d1SLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 699cc52688aSLars-Peter Clausen unsigned int mask = ADAV80X_DAC_CTRL1_PD; 700cc52688aSLars-Peter Clausen 701cc52688aSLars-Peter Clausen switch (level) { 702cc52688aSLars-Peter Clausen case SND_SOC_BIAS_ON: 703cc52688aSLars-Peter Clausen break; 704cc52688aSLars-Peter Clausen case SND_SOC_BIAS_PREPARE: 705cc52688aSLars-Peter Clausen break; 706cc52688aSLars-Peter Clausen case SND_SOC_BIAS_STANDBY: 7072560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL1, mask, 7082560b3d1SLars-Peter Clausen 0x00); 709cc52688aSLars-Peter Clausen break; 710cc52688aSLars-Peter Clausen case SND_SOC_BIAS_OFF: 7112560b3d1SLars-Peter Clausen regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL1, mask, 7122560b3d1SLars-Peter Clausen mask); 713cc52688aSLars-Peter Clausen break; 714cc52688aSLars-Peter Clausen } 715cc52688aSLars-Peter Clausen 716cc52688aSLars-Peter Clausen codec->dapm.bias_level = level; 717cc52688aSLars-Peter Clausen return 0; 718cc52688aSLars-Peter Clausen } 719cc52688aSLars-Peter Clausen 720cc52688aSLars-Peter Clausen /* Enforce the same sample rate on all audio interfaces */ 721cc52688aSLars-Peter Clausen static int adav80x_dai_startup(struct snd_pcm_substream *substream, 722cc52688aSLars-Peter Clausen struct snd_soc_dai *dai) 723cc52688aSLars-Peter Clausen { 724cc52688aSLars-Peter Clausen struct snd_soc_codec *codec = dai->codec; 725cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 726cc52688aSLars-Peter Clausen 727cc52688aSLars-Peter Clausen if (!codec->active || !adav80x->rate) 728cc52688aSLars-Peter Clausen return 0; 729cc52688aSLars-Peter Clausen 730cc52688aSLars-Peter Clausen return snd_pcm_hw_constraint_minmax(substream->runtime, 731cc52688aSLars-Peter Clausen SNDRV_PCM_HW_PARAM_RATE, adav80x->rate, adav80x->rate); 732cc52688aSLars-Peter Clausen } 733cc52688aSLars-Peter Clausen 734cc52688aSLars-Peter Clausen static void adav80x_dai_shutdown(struct snd_pcm_substream *substream, 735cc52688aSLars-Peter Clausen struct snd_soc_dai *dai) 736cc52688aSLars-Peter Clausen { 737cc52688aSLars-Peter Clausen struct snd_soc_codec *codec = dai->codec; 738cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 739cc52688aSLars-Peter Clausen 740cc52688aSLars-Peter Clausen if (!codec->active) 741cc52688aSLars-Peter Clausen adav80x->rate = 0; 742cc52688aSLars-Peter Clausen } 743cc52688aSLars-Peter Clausen 744890754a8SLars-Peter Clausen static const struct snd_soc_dai_ops adav80x_dai_ops = { 745cc52688aSLars-Peter Clausen .set_fmt = adav80x_set_dai_fmt, 746cc52688aSLars-Peter Clausen .hw_params = adav80x_hw_params, 747cc52688aSLars-Peter Clausen .startup = adav80x_dai_startup, 748cc52688aSLars-Peter Clausen .shutdown = adav80x_dai_shutdown, 749cc52688aSLars-Peter Clausen }; 750cc52688aSLars-Peter Clausen 751cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ 752cc52688aSLars-Peter Clausen SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | \ 753cc52688aSLars-Peter Clausen SNDRV_PCM_RATE_96000) 754cc52688aSLars-Peter Clausen 755cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) 756cc52688aSLars-Peter Clausen 757cc52688aSLars-Peter Clausen #define ADAV80X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \ 758cc52688aSLars-Peter Clausen SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) 759cc52688aSLars-Peter Clausen 760cc52688aSLars-Peter Clausen static struct snd_soc_dai_driver adav80x_dais[] = { 761cc52688aSLars-Peter Clausen { 762cc52688aSLars-Peter Clausen .name = "adav80x-hifi", 763cc52688aSLars-Peter Clausen .id = 0, 764cc52688aSLars-Peter Clausen .playback = { 765cc52688aSLars-Peter Clausen .stream_name = "HiFi Playback", 766cc52688aSLars-Peter Clausen .channels_min = 2, 767cc52688aSLars-Peter Clausen .channels_max = 2, 768cc52688aSLars-Peter Clausen .rates = ADAV80X_PLAYBACK_RATES, 769cc52688aSLars-Peter Clausen .formats = ADAV80X_FORMATS, 770cc52688aSLars-Peter Clausen }, 771cc52688aSLars-Peter Clausen .capture = { 772cc52688aSLars-Peter Clausen .stream_name = "HiFi Capture", 773cc52688aSLars-Peter Clausen .channels_min = 2, 774cc52688aSLars-Peter Clausen .channels_max = 2, 775cc52688aSLars-Peter Clausen .rates = ADAV80X_CAPTURE_RATES, 776cc52688aSLars-Peter Clausen .formats = ADAV80X_FORMATS, 777cc52688aSLars-Peter Clausen }, 778cc52688aSLars-Peter Clausen .ops = &adav80x_dai_ops, 779cc52688aSLars-Peter Clausen }, 780cc52688aSLars-Peter Clausen { 781cc52688aSLars-Peter Clausen .name = "adav80x-aux", 782cc52688aSLars-Peter Clausen .id = 1, 783cc52688aSLars-Peter Clausen .playback = { 784cc52688aSLars-Peter Clausen .stream_name = "Aux Playback", 785cc52688aSLars-Peter Clausen .channels_min = 2, 786cc52688aSLars-Peter Clausen .channels_max = 2, 787cc52688aSLars-Peter Clausen .rates = ADAV80X_PLAYBACK_RATES, 788cc52688aSLars-Peter Clausen .formats = ADAV80X_FORMATS, 789cc52688aSLars-Peter Clausen }, 790cc52688aSLars-Peter Clausen .capture = { 791cc52688aSLars-Peter Clausen .stream_name = "Aux Capture", 792cc52688aSLars-Peter Clausen .channels_min = 2, 793cc52688aSLars-Peter Clausen .channels_max = 2, 794cc52688aSLars-Peter Clausen .rates = ADAV80X_CAPTURE_RATES, 795cc52688aSLars-Peter Clausen .formats = ADAV80X_FORMATS, 796cc52688aSLars-Peter Clausen }, 797cc52688aSLars-Peter Clausen .ops = &adav80x_dai_ops, 798cc52688aSLars-Peter Clausen }, 799cc52688aSLars-Peter Clausen }; 800cc52688aSLars-Peter Clausen 801cc52688aSLars-Peter Clausen static int adav80x_probe(struct snd_soc_codec *codec) 802cc52688aSLars-Peter Clausen { 803cc52688aSLars-Peter Clausen int ret; 804cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 805cc52688aSLars-Peter Clausen 8062560b3d1SLars-Peter Clausen ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); 807cc52688aSLars-Peter Clausen if (ret) { 808cc52688aSLars-Peter Clausen dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); 809cc52688aSLars-Peter Clausen return ret; 810cc52688aSLars-Peter Clausen } 811cc52688aSLars-Peter Clausen 812cc52688aSLars-Peter Clausen /* Force PLLs on for SYSCLK output */ 813cc52688aSLars-Peter Clausen snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); 814cc52688aSLars-Peter Clausen snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); 815cc52688aSLars-Peter Clausen 816cc52688aSLars-Peter Clausen /* Power down S/PDIF receiver, since it is currently not supported */ 8172560b3d1SLars-Peter Clausen regmap_write(adav80x->regmap, ADAV80X_PLL_OUTE, 0x20); 818cc52688aSLars-Peter Clausen /* Disable DAC zero flag */ 8192560b3d1SLars-Peter Clausen regmap_write(adav80x->regmap, ADAV80X_DAC_CTRL3, 0x6); 820cc52688aSLars-Peter Clausen 821cc52688aSLars-Peter Clausen return adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 822cc52688aSLars-Peter Clausen } 823cc52688aSLars-Peter Clausen 82484b315eeSLars-Peter Clausen static int adav80x_suspend(struct snd_soc_codec *codec) 825cc52688aSLars-Peter Clausen { 8262560b3d1SLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 8272560b3d1SLars-Peter Clausen int ret; 8282560b3d1SLars-Peter Clausen 8292560b3d1SLars-Peter Clausen ret = adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF); 8302560b3d1SLars-Peter Clausen regcache_cache_only(adav80x->regmap, true); 8312560b3d1SLars-Peter Clausen 8322560b3d1SLars-Peter Clausen return ret; 833cc52688aSLars-Peter Clausen } 834cc52688aSLars-Peter Clausen 835cc52688aSLars-Peter Clausen static int adav80x_resume(struct snd_soc_codec *codec) 836cc52688aSLars-Peter Clausen { 8372560b3d1SLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 8382560b3d1SLars-Peter Clausen 8392560b3d1SLars-Peter Clausen regcache_cache_only(adav80x->regmap, false); 840cc52688aSLars-Peter Clausen adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 8412560b3d1SLars-Peter Clausen regcache_sync(adav80x->regmap); 842cc52688aSLars-Peter Clausen 843cc52688aSLars-Peter Clausen return 0; 844cc52688aSLars-Peter Clausen } 845cc52688aSLars-Peter Clausen 846cc52688aSLars-Peter Clausen static int adav80x_remove(struct snd_soc_codec *codec) 847cc52688aSLars-Peter Clausen { 848cc52688aSLars-Peter Clausen return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF); 849cc52688aSLars-Peter Clausen } 850cc52688aSLars-Peter Clausen 851cc52688aSLars-Peter Clausen static struct snd_soc_codec_driver adav80x_codec_driver = { 852cc52688aSLars-Peter Clausen .probe = adav80x_probe, 853cc52688aSLars-Peter Clausen .remove = adav80x_remove, 854cc52688aSLars-Peter Clausen .suspend = adav80x_suspend, 855cc52688aSLars-Peter Clausen .resume = adav80x_resume, 856cc52688aSLars-Peter Clausen .set_bias_level = adav80x_set_bias_level, 857cc52688aSLars-Peter Clausen 858cc52688aSLars-Peter Clausen .set_pll = adav80x_set_pll, 859cc52688aSLars-Peter Clausen .set_sysclk = adav80x_set_sysclk, 860cc52688aSLars-Peter Clausen 861cc52688aSLars-Peter Clausen .controls = adav80x_controls, 862cc52688aSLars-Peter Clausen .num_controls = ARRAY_SIZE(adav80x_controls), 863cc52688aSLars-Peter Clausen .dapm_widgets = adav80x_dapm_widgets, 864cc52688aSLars-Peter Clausen .num_dapm_widgets = ARRAY_SIZE(adav80x_dapm_widgets), 865cc52688aSLars-Peter Clausen .dapm_routes = adav80x_dapm_routes, 866cc52688aSLars-Peter Clausen .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes), 867cc52688aSLars-Peter Clausen }; 868cc52688aSLars-Peter Clausen 8692560b3d1SLars-Peter Clausen static int adav80x_bus_probe(struct device *dev, struct regmap *regmap) 870cc52688aSLars-Peter Clausen { 871cc52688aSLars-Peter Clausen struct adav80x *adav80x; 872cc52688aSLars-Peter Clausen int ret; 873cc52688aSLars-Peter Clausen 8742560b3d1SLars-Peter Clausen if (IS_ERR(regmap)) 8752560b3d1SLars-Peter Clausen return PTR_ERR(regmap); 8762560b3d1SLars-Peter Clausen 877cc52688aSLars-Peter Clausen adav80x = kzalloc(sizeof(*adav80x), GFP_KERNEL); 878cc52688aSLars-Peter Clausen if (!adav80x) 879cc52688aSLars-Peter Clausen return -ENOMEM; 880cc52688aSLars-Peter Clausen 8812560b3d1SLars-Peter Clausen 882cc52688aSLars-Peter Clausen dev_set_drvdata(dev, adav80x); 8832560b3d1SLars-Peter Clausen adav80x->regmap = regmap; 884cc52688aSLars-Peter Clausen 885cc52688aSLars-Peter Clausen ret = snd_soc_register_codec(dev, &adav80x_codec_driver, 886cc52688aSLars-Peter Clausen adav80x_dais, ARRAY_SIZE(adav80x_dais)); 887cc52688aSLars-Peter Clausen if (ret) 888cc52688aSLars-Peter Clausen kfree(adav80x); 889cc52688aSLars-Peter Clausen 890cc52688aSLars-Peter Clausen return ret; 891cc52688aSLars-Peter Clausen } 892cc52688aSLars-Peter Clausen 8937a79e94eSBill Pemberton static int adav80x_bus_remove(struct device *dev) 894cc52688aSLars-Peter Clausen { 895cc52688aSLars-Peter Clausen snd_soc_unregister_codec(dev); 896cc52688aSLars-Peter Clausen kfree(dev_get_drvdata(dev)); 897cc52688aSLars-Peter Clausen return 0; 898cc52688aSLars-Peter Clausen } 899cc52688aSLars-Peter Clausen 900cc52688aSLars-Peter Clausen #if defined(CONFIG_SPI_MASTER) 9012560b3d1SLars-Peter Clausen static const struct regmap_config adav80x_spi_regmap_config = { 9022560b3d1SLars-Peter Clausen .val_bits = 8, 9032560b3d1SLars-Peter Clausen .pad_bits = 1, 9042560b3d1SLars-Peter Clausen .reg_bits = 7, 9052560b3d1SLars-Peter Clausen .read_flag_mask = 0x01, 9062560b3d1SLars-Peter Clausen 9072560b3d1SLars-Peter Clausen .max_register = ADAV80X_PLL_OUTE, 9082560b3d1SLars-Peter Clausen 9092560b3d1SLars-Peter Clausen .cache_type = REGCACHE_RBTREE, 9102560b3d1SLars-Peter Clausen .reg_defaults = adav80x_reg_defaults, 9112560b3d1SLars-Peter Clausen .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults), 9122560b3d1SLars-Peter Clausen }; 9132560b3d1SLars-Peter Clausen 914e394fe55SAxel Lin static const struct spi_device_id adav80x_spi_id[] = { 915e394fe55SAxel Lin { "adav801", 0 }, 916e394fe55SAxel Lin { } 917e394fe55SAxel Lin }; 918e394fe55SAxel Lin MODULE_DEVICE_TABLE(spi, adav80x_spi_id); 919e394fe55SAxel Lin 9207a79e94eSBill Pemberton static int adav80x_spi_probe(struct spi_device *spi) 921cc52688aSLars-Peter Clausen { 9222560b3d1SLars-Peter Clausen return adav80x_bus_probe(&spi->dev, 9232560b3d1SLars-Peter Clausen devm_regmap_init_spi(spi, &adav80x_spi_regmap_config)); 924cc52688aSLars-Peter Clausen } 925cc52688aSLars-Peter Clausen 9267a79e94eSBill Pemberton static int adav80x_spi_remove(struct spi_device *spi) 927cc52688aSLars-Peter Clausen { 928cc52688aSLars-Peter Clausen return adav80x_bus_remove(&spi->dev); 929cc52688aSLars-Peter Clausen } 930cc52688aSLars-Peter Clausen 931cc52688aSLars-Peter Clausen static struct spi_driver adav80x_spi_driver = { 932cc52688aSLars-Peter Clausen .driver = { 933cc52688aSLars-Peter Clausen .name = "adav801", 934cc52688aSLars-Peter Clausen .owner = THIS_MODULE, 935cc52688aSLars-Peter Clausen }, 936cc52688aSLars-Peter Clausen .probe = adav80x_spi_probe, 9377a79e94eSBill Pemberton .remove = adav80x_spi_remove, 938e394fe55SAxel Lin .id_table = adav80x_spi_id, 939cc52688aSLars-Peter Clausen }; 940cc52688aSLars-Peter Clausen #endif 941cc52688aSLars-Peter Clausen 942cc52688aSLars-Peter Clausen #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 9432560b3d1SLars-Peter Clausen static const struct regmap_config adav80x_i2c_regmap_config = { 9442560b3d1SLars-Peter Clausen .val_bits = 8, 9452560b3d1SLars-Peter Clausen .pad_bits = 1, 9462560b3d1SLars-Peter Clausen .reg_bits = 7, 9472560b3d1SLars-Peter Clausen 9482560b3d1SLars-Peter Clausen .max_register = ADAV80X_PLL_OUTE, 9492560b3d1SLars-Peter Clausen 9502560b3d1SLars-Peter Clausen .cache_type = REGCACHE_RBTREE, 9512560b3d1SLars-Peter Clausen .reg_defaults = adav80x_reg_defaults, 9522560b3d1SLars-Peter Clausen .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults), 9532560b3d1SLars-Peter Clausen }; 9542560b3d1SLars-Peter Clausen 955e394fe55SAxel Lin static const struct i2c_device_id adav80x_i2c_id[] = { 956cc52688aSLars-Peter Clausen { "adav803", 0 }, 957cc52688aSLars-Peter Clausen { } 958cc52688aSLars-Peter Clausen }; 959e394fe55SAxel Lin MODULE_DEVICE_TABLE(i2c, adav80x_i2c_id); 960cc52688aSLars-Peter Clausen 9617a79e94eSBill Pemberton static int adav80x_i2c_probe(struct i2c_client *client, 962cc52688aSLars-Peter Clausen const struct i2c_device_id *id) 963cc52688aSLars-Peter Clausen { 9642560b3d1SLars-Peter Clausen return adav80x_bus_probe(&client->dev, 9652560b3d1SLars-Peter Clausen devm_regmap_init_i2c(client, &adav80x_i2c_regmap_config)); 966cc52688aSLars-Peter Clausen } 967cc52688aSLars-Peter Clausen 9687a79e94eSBill Pemberton static int adav80x_i2c_remove(struct i2c_client *client) 969cc52688aSLars-Peter Clausen { 970cc52688aSLars-Peter Clausen return adav80x_bus_remove(&client->dev); 971cc52688aSLars-Peter Clausen } 972cc52688aSLars-Peter Clausen 973cc52688aSLars-Peter Clausen static struct i2c_driver adav80x_i2c_driver = { 974cc52688aSLars-Peter Clausen .driver = { 975cc52688aSLars-Peter Clausen .name = "adav803", 976cc52688aSLars-Peter Clausen .owner = THIS_MODULE, 977cc52688aSLars-Peter Clausen }, 978cc52688aSLars-Peter Clausen .probe = adav80x_i2c_probe, 9797a79e94eSBill Pemberton .remove = adav80x_i2c_remove, 980e394fe55SAxel Lin .id_table = adav80x_i2c_id, 981cc52688aSLars-Peter Clausen }; 982cc52688aSLars-Peter Clausen #endif 983cc52688aSLars-Peter Clausen 984cc52688aSLars-Peter Clausen static int __init adav80x_init(void) 985cc52688aSLars-Peter Clausen { 986cc52688aSLars-Peter Clausen int ret = 0; 987cc52688aSLars-Peter Clausen 988cc52688aSLars-Peter Clausen #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 989cc52688aSLars-Peter Clausen ret = i2c_add_driver(&adav80x_i2c_driver); 990cc52688aSLars-Peter Clausen if (ret) 991cc52688aSLars-Peter Clausen return ret; 992cc52688aSLars-Peter Clausen #endif 993cc52688aSLars-Peter Clausen 994cc52688aSLars-Peter Clausen #if defined(CONFIG_SPI_MASTER) 995cc52688aSLars-Peter Clausen ret = spi_register_driver(&adav80x_spi_driver); 996cc52688aSLars-Peter Clausen #endif 997cc52688aSLars-Peter Clausen 998cc52688aSLars-Peter Clausen return ret; 999cc52688aSLars-Peter Clausen } 1000cc52688aSLars-Peter Clausen module_init(adav80x_init); 1001cc52688aSLars-Peter Clausen 1002cc52688aSLars-Peter Clausen static void __exit adav80x_exit(void) 1003cc52688aSLars-Peter Clausen { 1004cc52688aSLars-Peter Clausen #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1005cc52688aSLars-Peter Clausen i2c_del_driver(&adav80x_i2c_driver); 1006cc52688aSLars-Peter Clausen #endif 1007cc52688aSLars-Peter Clausen #if defined(CONFIG_SPI_MASTER) 1008cc52688aSLars-Peter Clausen spi_unregister_driver(&adav80x_spi_driver); 1009cc52688aSLars-Peter Clausen #endif 1010cc52688aSLars-Peter Clausen } 1011cc52688aSLars-Peter Clausen module_exit(adav80x_exit); 1012cc52688aSLars-Peter Clausen 1013cc52688aSLars-Peter Clausen MODULE_DESCRIPTION("ASoC ADAV80x driver"); 1014cc52688aSLars-Peter Clausen MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 1015cc52688aSLars-Peter Clausen MODULE_AUTHOR("Yi Li <yi.li@analog.com>>"); 1016cc52688aSLars-Peter Clausen MODULE_LICENSE("GPL"); 1017