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 118cc52688aSLars-Peter Clausen static u8 adav80x_default_regs[] = { 119cc52688aSLars-Peter Clausen 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x01, 0x80, 0x26, 0x00, 0x00, 120cc52688aSLars-Peter Clausen 0x02, 0x40, 0x20, 0x00, 0x09, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 121cc52688aSLars-Peter Clausen 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x92, 0xb1, 0x37, 122cc52688aSLars-Peter Clausen 0x48, 0xd2, 0xfb, 0xca, 0xd2, 0x15, 0xe8, 0x29, 0xb9, 0x6a, 0xda, 0x2b, 123cc52688aSLars-Peter Clausen 0xb7, 0xc0, 0x11, 0x65, 0x5c, 0xf6, 0xff, 0x8d, 0x00, 0x00, 0x00, 0x00, 124cc52688aSLars-Peter Clausen 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 125cc52688aSLars-Peter Clausen 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 126cc52688aSLars-Peter Clausen 0x00, 0xe8, 0x46, 0xe1, 0x5b, 0xd3, 0x43, 0x77, 0x93, 0xa7, 0x44, 0xee, 127cc52688aSLars-Peter Clausen 0x32, 0x12, 0xc0, 0x11, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x3f, 128cc52688aSLars-Peter Clausen 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 129cc52688aSLars-Peter Clausen 0x00, 0x00, 0x00, 0x00, 0x52, 0x00, 130cc52688aSLars-Peter Clausen }; 131cc52688aSLars-Peter Clausen 132cc52688aSLars-Peter Clausen struct adav80x { 133cc52688aSLars-Peter Clausen enum snd_soc_control_type control_type; 134cc52688aSLars-Peter Clausen 135cc52688aSLars-Peter Clausen enum adav80x_clk_src clk_src; 136cc52688aSLars-Peter Clausen unsigned int sysclk; 137cc52688aSLars-Peter Clausen enum adav80x_pll_src pll_src; 138cc52688aSLars-Peter Clausen 139cc52688aSLars-Peter Clausen unsigned int dai_fmt[2]; 140cc52688aSLars-Peter Clausen unsigned int rate; 141cc52688aSLars-Peter Clausen bool deemph; 142cc52688aSLars-Peter Clausen bool sysclk_pd[3]; 143cc52688aSLars-Peter Clausen }; 144cc52688aSLars-Peter Clausen 145cc52688aSLars-Peter Clausen static const char *adav80x_mux_text[] = { 146cc52688aSLars-Peter Clausen "ADC", 147cc52688aSLars-Peter Clausen "Playback", 148cc52688aSLars-Peter Clausen "Aux Playback", 149cc52688aSLars-Peter Clausen }; 150cc52688aSLars-Peter Clausen 151cc52688aSLars-Peter Clausen static const unsigned int adav80x_mux_values[] = { 152cc52688aSLars-Peter Clausen 0, 2, 3, 153cc52688aSLars-Peter Clausen }; 154cc52688aSLars-Peter Clausen 155cc52688aSLars-Peter Clausen #define ADAV80X_MUX_ENUM_DECL(name, reg, shift) \ 156cc52688aSLars-Peter Clausen SOC_VALUE_ENUM_DOUBLE_DECL(name, reg, shift, 7, \ 157cc52688aSLars-Peter Clausen ARRAY_SIZE(adav80x_mux_text), adav80x_mux_text, \ 158cc52688aSLars-Peter Clausen adav80x_mux_values) 159cc52688aSLars-Peter Clausen 160cc52688aSLars-Peter Clausen static ADAV80X_MUX_ENUM_DECL(adav80x_aux_capture_enum, ADAV80X_DPATH_CTRL1, 0); 161cc52688aSLars-Peter Clausen static ADAV80X_MUX_ENUM_DECL(adav80x_capture_enum, ADAV80X_DPATH_CTRL1, 3); 162cc52688aSLars-Peter Clausen static ADAV80X_MUX_ENUM_DECL(adav80x_dac_enum, ADAV80X_DPATH_CTRL2, 3); 163cc52688aSLars-Peter Clausen 164cc52688aSLars-Peter Clausen static const struct snd_kcontrol_new adav80x_aux_capture_mux_ctrl = 165cc52688aSLars-Peter Clausen SOC_DAPM_VALUE_ENUM("Route", adav80x_aux_capture_enum); 166cc52688aSLars-Peter Clausen static const struct snd_kcontrol_new adav80x_capture_mux_ctrl = 167cc52688aSLars-Peter Clausen SOC_DAPM_VALUE_ENUM("Route", adav80x_capture_enum); 168cc52688aSLars-Peter Clausen static const struct snd_kcontrol_new adav80x_dac_mux_ctrl = 169cc52688aSLars-Peter Clausen SOC_DAPM_VALUE_ENUM("Route", adav80x_dac_enum); 170cc52688aSLars-Peter Clausen 171cc52688aSLars-Peter Clausen #define ADAV80X_MUX(name, ctrl) \ 172cc52688aSLars-Peter Clausen SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl) 173cc52688aSLars-Peter Clausen 174cc52688aSLars-Peter Clausen static const struct snd_soc_dapm_widget adav80x_dapm_widgets[] = { 175cc52688aSLars-Peter Clausen SND_SOC_DAPM_DAC("DAC", NULL, ADAV80X_DAC_CTRL1, 7, 1), 176cc52688aSLars-Peter Clausen SND_SOC_DAPM_ADC("ADC", NULL, ADAV80X_ADC_CTRL1, 5, 1), 177cc52688aSLars-Peter Clausen 178cc52688aSLars-Peter Clausen SND_SOC_DAPM_PGA("Right PGA", ADAV80X_ADC_CTRL1, 0, 1, NULL, 0), 179cc52688aSLars-Peter Clausen SND_SOC_DAPM_PGA("Left PGA", ADAV80X_ADC_CTRL1, 1, 1, NULL, 0), 180cc52688aSLars-Peter Clausen 181cc52688aSLars-Peter Clausen SND_SOC_DAPM_AIF_OUT("AIFOUT", "HiFi Capture", 0, SND_SOC_NOPM, 0, 0), 182cc52688aSLars-Peter Clausen SND_SOC_DAPM_AIF_IN("AIFIN", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0), 183cc52688aSLars-Peter Clausen 184cc52688aSLars-Peter Clausen SND_SOC_DAPM_AIF_OUT("AIFAUXOUT", "Aux Capture", 0, SND_SOC_NOPM, 0, 0), 185cc52688aSLars-Peter Clausen SND_SOC_DAPM_AIF_IN("AIFAUXIN", "Aux Playback", 0, SND_SOC_NOPM, 0, 0), 186cc52688aSLars-Peter Clausen 187cc52688aSLars-Peter Clausen ADAV80X_MUX("Aux Capture Select", &adav80x_aux_capture_mux_ctrl), 188cc52688aSLars-Peter Clausen ADAV80X_MUX("Capture Select", &adav80x_capture_mux_ctrl), 189cc52688aSLars-Peter Clausen ADAV80X_MUX("DAC Select", &adav80x_dac_mux_ctrl), 190cc52688aSLars-Peter Clausen 191cc52688aSLars-Peter Clausen SND_SOC_DAPM_INPUT("VINR"), 192cc52688aSLars-Peter Clausen SND_SOC_DAPM_INPUT("VINL"), 193cc52688aSLars-Peter Clausen SND_SOC_DAPM_OUTPUT("VOUTR"), 194cc52688aSLars-Peter Clausen SND_SOC_DAPM_OUTPUT("VOUTL"), 195cc52688aSLars-Peter Clausen 196cc52688aSLars-Peter Clausen SND_SOC_DAPM_SUPPLY("SYSCLK", SND_SOC_NOPM, 0, 0, NULL, 0), 197cc52688aSLars-Peter Clausen SND_SOC_DAPM_SUPPLY("PLL1", ADAV80X_PLL_CTRL1, 2, 1, NULL, 0), 198cc52688aSLars-Peter Clausen SND_SOC_DAPM_SUPPLY("PLL2", ADAV80X_PLL_CTRL1, 3, 1, NULL, 0), 199cc52688aSLars-Peter Clausen SND_SOC_DAPM_SUPPLY("OSC", ADAV80X_PLL_CTRL1, 1, 1, NULL, 0), 200cc52688aSLars-Peter Clausen }; 201cc52688aSLars-Peter Clausen 202cc52688aSLars-Peter Clausen static int adav80x_dapm_sysclk_check(struct snd_soc_dapm_widget *source, 203cc52688aSLars-Peter Clausen struct snd_soc_dapm_widget *sink) 204cc52688aSLars-Peter Clausen { 205cc52688aSLars-Peter Clausen struct snd_soc_codec *codec = source->codec; 206cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 207cc52688aSLars-Peter Clausen const char *clk; 208cc52688aSLars-Peter Clausen 209cc52688aSLars-Peter Clausen switch (adav80x->clk_src) { 210cc52688aSLars-Peter Clausen case ADAV80X_CLK_PLL1: 211cc52688aSLars-Peter Clausen clk = "PLL1"; 212cc52688aSLars-Peter Clausen break; 213cc52688aSLars-Peter Clausen case ADAV80X_CLK_PLL2: 214cc52688aSLars-Peter Clausen clk = "PLL2"; 215cc52688aSLars-Peter Clausen break; 216cc52688aSLars-Peter Clausen case ADAV80X_CLK_XTAL: 217cc52688aSLars-Peter Clausen clk = "OSC"; 218cc52688aSLars-Peter Clausen break; 219cc52688aSLars-Peter Clausen default: 220cc52688aSLars-Peter Clausen return 0; 221cc52688aSLars-Peter Clausen } 222cc52688aSLars-Peter Clausen 223cc52688aSLars-Peter Clausen return strcmp(source->name, clk) == 0; 224cc52688aSLars-Peter Clausen } 225cc52688aSLars-Peter Clausen 226cc52688aSLars-Peter Clausen static int adav80x_dapm_pll_check(struct snd_soc_dapm_widget *source, 227cc52688aSLars-Peter Clausen struct snd_soc_dapm_widget *sink) 228cc52688aSLars-Peter Clausen { 229cc52688aSLars-Peter Clausen struct snd_soc_codec *codec = source->codec; 230cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 231cc52688aSLars-Peter Clausen 232cc52688aSLars-Peter Clausen return adav80x->pll_src == ADAV80X_PLL_SRC_XTAL; 233cc52688aSLars-Peter Clausen } 234cc52688aSLars-Peter Clausen 235cc52688aSLars-Peter Clausen 236cc52688aSLars-Peter Clausen static const struct snd_soc_dapm_route adav80x_dapm_routes[] = { 237cc52688aSLars-Peter Clausen { "DAC Select", "ADC", "ADC" }, 238cc52688aSLars-Peter Clausen { "DAC Select", "Playback", "AIFIN" }, 239cc52688aSLars-Peter Clausen { "DAC Select", "Aux Playback", "AIFAUXIN" }, 240cc52688aSLars-Peter Clausen { "DAC", NULL, "DAC Select" }, 241cc52688aSLars-Peter Clausen 242cc52688aSLars-Peter Clausen { "Capture Select", "ADC", "ADC" }, 243cc52688aSLars-Peter Clausen { "Capture Select", "Playback", "AIFIN" }, 244cc52688aSLars-Peter Clausen { "Capture Select", "Aux Playback", "AIFAUXIN" }, 245cc52688aSLars-Peter Clausen { "AIFOUT", NULL, "Capture Select" }, 246cc52688aSLars-Peter Clausen 247cc52688aSLars-Peter Clausen { "Aux Capture Select", "ADC", "ADC" }, 248cc52688aSLars-Peter Clausen { "Aux Capture Select", "Playback", "AIFIN" }, 249cc52688aSLars-Peter Clausen { "Aux Capture Select", "Aux Playback", "AIFAUXIN" }, 250cc52688aSLars-Peter Clausen { "AIFAUXOUT", NULL, "Aux Capture Select" }, 251cc52688aSLars-Peter Clausen 252cc52688aSLars-Peter Clausen { "VOUTR", NULL, "DAC" }, 253cc52688aSLars-Peter Clausen { "VOUTL", NULL, "DAC" }, 254cc52688aSLars-Peter Clausen 255cc52688aSLars-Peter Clausen { "Left PGA", NULL, "VINL" }, 256cc52688aSLars-Peter Clausen { "Right PGA", NULL, "VINR" }, 257cc52688aSLars-Peter Clausen { "ADC", NULL, "Left PGA" }, 258cc52688aSLars-Peter Clausen { "ADC", NULL, "Right PGA" }, 259cc52688aSLars-Peter Clausen 260cc52688aSLars-Peter Clausen { "SYSCLK", NULL, "PLL1", adav80x_dapm_sysclk_check }, 261cc52688aSLars-Peter Clausen { "SYSCLK", NULL, "PLL2", adav80x_dapm_sysclk_check }, 262cc52688aSLars-Peter Clausen { "SYSCLK", NULL, "OSC", adav80x_dapm_sysclk_check }, 263cc52688aSLars-Peter Clausen { "PLL1", NULL, "OSC", adav80x_dapm_pll_check }, 264cc52688aSLars-Peter Clausen { "PLL2", NULL, "OSC", adav80x_dapm_pll_check }, 265cc52688aSLars-Peter Clausen 266cc52688aSLars-Peter Clausen { "ADC", NULL, "SYSCLK" }, 267cc52688aSLars-Peter Clausen { "DAC", NULL, "SYSCLK" }, 268cc52688aSLars-Peter Clausen { "AIFOUT", NULL, "SYSCLK" }, 269cc52688aSLars-Peter Clausen { "AIFAUXOUT", NULL, "SYSCLK" }, 270cc52688aSLars-Peter Clausen { "AIFIN", NULL, "SYSCLK" }, 271cc52688aSLars-Peter Clausen { "AIFAUXIN", NULL, "SYSCLK" }, 272cc52688aSLars-Peter Clausen }; 273cc52688aSLars-Peter Clausen 274cc52688aSLars-Peter Clausen static int adav80x_set_deemph(struct snd_soc_codec *codec) 275cc52688aSLars-Peter Clausen { 276cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 277cc52688aSLars-Peter Clausen unsigned int val; 278cc52688aSLars-Peter Clausen 279cc52688aSLars-Peter Clausen if (adav80x->deemph) { 280cc52688aSLars-Peter Clausen switch (adav80x->rate) { 281cc52688aSLars-Peter Clausen case 32000: 282cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DEEMPH_32; 283cc52688aSLars-Peter Clausen break; 284cc52688aSLars-Peter Clausen case 44100: 285cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DEEMPH_44; 286cc52688aSLars-Peter Clausen break; 287cc52688aSLars-Peter Clausen case 48000: 288cc52688aSLars-Peter Clausen case 64000: 289cc52688aSLars-Peter Clausen case 88200: 290cc52688aSLars-Peter Clausen case 96000: 291cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DEEMPH_48; 292cc52688aSLars-Peter Clausen break; 293cc52688aSLars-Peter Clausen default: 294cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DEEMPH_NONE; 295cc52688aSLars-Peter Clausen break; 296cc52688aSLars-Peter Clausen } 297cc52688aSLars-Peter Clausen } else { 298cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DEEMPH_NONE; 299cc52688aSLars-Peter Clausen } 300cc52688aSLars-Peter Clausen 301cc52688aSLars-Peter Clausen return snd_soc_update_bits(codec, ADAV80X_DAC_CTRL2, 302cc52688aSLars-Peter Clausen ADAV80X_DAC_CTRL2_DEEMPH_MASK, val); 303cc52688aSLars-Peter Clausen } 304cc52688aSLars-Peter Clausen 305cc52688aSLars-Peter Clausen static int adav80x_put_deemph(struct snd_kcontrol *kcontrol, 306cc52688aSLars-Peter Clausen struct snd_ctl_elem_value *ucontrol) 307cc52688aSLars-Peter Clausen { 308cc52688aSLars-Peter Clausen struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 309cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 310cc52688aSLars-Peter Clausen unsigned int deemph = ucontrol->value.enumerated.item[0]; 311cc52688aSLars-Peter Clausen 312cc52688aSLars-Peter Clausen if (deemph > 1) 313cc52688aSLars-Peter Clausen return -EINVAL; 314cc52688aSLars-Peter Clausen 315cc52688aSLars-Peter Clausen adav80x->deemph = deemph; 316cc52688aSLars-Peter Clausen 317cc52688aSLars-Peter Clausen return adav80x_set_deemph(codec); 318cc52688aSLars-Peter Clausen } 319cc52688aSLars-Peter Clausen 320cc52688aSLars-Peter Clausen static int adav80x_get_deemph(struct snd_kcontrol *kcontrol, 321cc52688aSLars-Peter Clausen struct snd_ctl_elem_value *ucontrol) 322cc52688aSLars-Peter Clausen { 323cc52688aSLars-Peter Clausen struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 324cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 325cc52688aSLars-Peter Clausen 326cc52688aSLars-Peter Clausen ucontrol->value.enumerated.item[0] = adav80x->deemph; 327cc52688aSLars-Peter Clausen return 0; 328cc52688aSLars-Peter Clausen }; 329cc52688aSLars-Peter Clausen 330cc52688aSLars-Peter Clausen static const DECLARE_TLV_DB_SCALE(adav80x_inpga_tlv, 0, 50, 0); 331cc52688aSLars-Peter Clausen static const DECLARE_TLV_DB_MINMAX(adav80x_digital_tlv, -9563, 0); 332cc52688aSLars-Peter Clausen 333cc52688aSLars-Peter Clausen static const struct snd_kcontrol_new adav80x_controls[] = { 334cc52688aSLars-Peter Clausen SOC_DOUBLE_R_TLV("Master Playback Volume", ADAV80X_DAC_L_VOL, 335cc52688aSLars-Peter Clausen ADAV80X_DAC_R_VOL, 0, 0xff, 0, adav80x_digital_tlv), 336cc52688aSLars-Peter Clausen SOC_DOUBLE_R_TLV("Master Capture Volume", ADAV80X_ADC_L_VOL, 337cc52688aSLars-Peter Clausen ADAV80X_ADC_R_VOL, 0, 0xff, 0, adav80x_digital_tlv), 338cc52688aSLars-Peter Clausen 339cc52688aSLars-Peter Clausen SOC_DOUBLE_R_TLV("PGA Capture Volume", ADAV80X_PGA_L_VOL, 340cc52688aSLars-Peter Clausen ADAV80X_PGA_R_VOL, 0, 0x30, 0, adav80x_inpga_tlv), 341cc52688aSLars-Peter Clausen 342cc52688aSLars-Peter Clausen SOC_DOUBLE("Master Playback Switch", ADAV80X_DAC_CTRL1, 0, 1, 1, 0), 343cc52688aSLars-Peter Clausen SOC_DOUBLE("Master Capture Switch", ADAV80X_ADC_CTRL1, 2, 3, 1, 1), 344cc52688aSLars-Peter Clausen 345cc52688aSLars-Peter Clausen SOC_SINGLE("ADC High Pass Filter Switch", ADAV80X_ADC_CTRL1, 6, 1, 0), 346cc52688aSLars-Peter Clausen 347cc52688aSLars-Peter Clausen SOC_SINGLE_BOOL_EXT("Playback De-emphasis Switch", 0, 348cc52688aSLars-Peter Clausen adav80x_get_deemph, adav80x_put_deemph), 349cc52688aSLars-Peter Clausen }; 350cc52688aSLars-Peter Clausen 351cc52688aSLars-Peter Clausen static unsigned int adav80x_port_ctrl_regs[2][2] = { 352cc52688aSLars-Peter Clausen { ADAV80X_REC_CTRL, ADAV80X_PLAYBACK_CTRL, }, 353cc52688aSLars-Peter Clausen { ADAV80X_AUX_OUT_CTRL, ADAV80X_AUX_IN_CTRL }, 354cc52688aSLars-Peter Clausen }; 355cc52688aSLars-Peter Clausen 356cc52688aSLars-Peter Clausen static int adav80x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 357cc52688aSLars-Peter Clausen { 358cc52688aSLars-Peter Clausen struct snd_soc_codec *codec = dai->codec; 359cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 360cc52688aSLars-Peter Clausen unsigned int capture = 0x00; 361cc52688aSLars-Peter Clausen unsigned int playback = 0x00; 362cc52688aSLars-Peter Clausen 363cc52688aSLars-Peter Clausen switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 364cc52688aSLars-Peter Clausen case SND_SOC_DAIFMT_CBM_CFM: 365cc52688aSLars-Peter Clausen capture |= ADAV80X_CAPTURE_MODE_MASTER; 366cc52688aSLars-Peter Clausen playback |= ADAV80X_PLAYBACK_MODE_MASTER; 367cc52688aSLars-Peter Clausen case SND_SOC_DAIFMT_CBS_CFS: 368cc52688aSLars-Peter Clausen break; 369cc52688aSLars-Peter Clausen default: 370cc52688aSLars-Peter Clausen return -EINVAL; 371cc52688aSLars-Peter Clausen } 372cc52688aSLars-Peter Clausen 373cc52688aSLars-Peter Clausen switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 374cc52688aSLars-Peter Clausen case SND_SOC_DAIFMT_I2S: 375cc52688aSLars-Peter Clausen capture |= ADAV80X_CAPTURE_MODE_I2S; 376cc52688aSLars-Peter Clausen playback |= ADAV80X_PLAYBACK_MODE_I2S; 377cc52688aSLars-Peter Clausen break; 378cc52688aSLars-Peter Clausen case SND_SOC_DAIFMT_LEFT_J: 379cc52688aSLars-Peter Clausen capture |= ADAV80X_CAPTURE_MODE_LEFT_J; 380cc52688aSLars-Peter Clausen playback |= ADAV80X_PLAYBACK_MODE_LEFT_J; 381cc52688aSLars-Peter Clausen break; 382cc52688aSLars-Peter Clausen case SND_SOC_DAIFMT_RIGHT_J: 383cc52688aSLars-Peter Clausen capture |= ADAV80X_CAPTURE_MODE_RIGHT_J; 384cc52688aSLars-Peter Clausen playback |= ADAV80X_PLAYBACK_MODE_RIGHT_J_24; 385cc52688aSLars-Peter Clausen break; 386cc52688aSLars-Peter Clausen default: 387cc52688aSLars-Peter Clausen return -EINVAL; 388cc52688aSLars-Peter Clausen } 389cc52688aSLars-Peter Clausen 390cc52688aSLars-Peter Clausen switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 391cc52688aSLars-Peter Clausen case SND_SOC_DAIFMT_NB_NF: 392cc52688aSLars-Peter Clausen break; 393cc52688aSLars-Peter Clausen default: 394cc52688aSLars-Peter Clausen return -EINVAL; 395cc52688aSLars-Peter Clausen } 396cc52688aSLars-Peter Clausen 397cc52688aSLars-Peter Clausen snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][0], 398cc52688aSLars-Peter Clausen ADAV80X_CAPTURE_MODE_MASK | ADAV80X_CAPTURE_MODE_MASTER, 399cc52688aSLars-Peter Clausen capture); 400cc52688aSLars-Peter Clausen snd_soc_write(codec, adav80x_port_ctrl_regs[dai->id][1], playback); 401cc52688aSLars-Peter Clausen 402cc52688aSLars-Peter Clausen adav80x->dai_fmt[dai->id] = fmt & SND_SOC_DAIFMT_FORMAT_MASK; 403cc52688aSLars-Peter Clausen 404cc52688aSLars-Peter Clausen return 0; 405cc52688aSLars-Peter Clausen } 406cc52688aSLars-Peter Clausen 407cc52688aSLars-Peter Clausen static int adav80x_set_adc_clock(struct snd_soc_codec *codec, 408cc52688aSLars-Peter Clausen unsigned int sample_rate) 409cc52688aSLars-Peter Clausen { 410cc52688aSLars-Peter Clausen unsigned int val; 411cc52688aSLars-Peter Clausen 412cc52688aSLars-Peter Clausen if (sample_rate <= 48000) 413cc52688aSLars-Peter Clausen val = ADAV80X_ADC_CTRL1_MODULATOR_128FS; 414cc52688aSLars-Peter Clausen else 415cc52688aSLars-Peter Clausen val = ADAV80X_ADC_CTRL1_MODULATOR_64FS; 416cc52688aSLars-Peter Clausen 417cc52688aSLars-Peter Clausen snd_soc_update_bits(codec, ADAV80X_ADC_CTRL1, 418cc52688aSLars-Peter Clausen ADAV80X_ADC_CTRL1_MODULATOR_MASK, val); 419cc52688aSLars-Peter Clausen 420cc52688aSLars-Peter Clausen return 0; 421cc52688aSLars-Peter Clausen } 422cc52688aSLars-Peter Clausen 423cc52688aSLars-Peter Clausen static int adav80x_set_dac_clock(struct snd_soc_codec *codec, 424cc52688aSLars-Peter Clausen unsigned int sample_rate) 425cc52688aSLars-Peter Clausen { 426cc52688aSLars-Peter Clausen unsigned int val; 427cc52688aSLars-Peter Clausen 428cc52688aSLars-Peter Clausen if (sample_rate <= 48000) 429cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DIV1 | ADAV80X_DAC_CTRL2_INTERPOL_256FS; 430cc52688aSLars-Peter Clausen else 431cc52688aSLars-Peter Clausen val = ADAV80X_DAC_CTRL2_DIV2 | ADAV80X_DAC_CTRL2_INTERPOL_128FS; 432cc52688aSLars-Peter Clausen 433cc52688aSLars-Peter Clausen snd_soc_update_bits(codec, ADAV80X_DAC_CTRL2, 434cc52688aSLars-Peter Clausen ADAV80X_DAC_CTRL2_DIV_MASK | ADAV80X_DAC_CTRL2_INTERPOL_MASK, 435cc52688aSLars-Peter Clausen val); 436cc52688aSLars-Peter Clausen 437cc52688aSLars-Peter Clausen return 0; 438cc52688aSLars-Peter Clausen } 439cc52688aSLars-Peter Clausen 440cc52688aSLars-Peter Clausen static int adav80x_set_capture_pcm_format(struct snd_soc_codec *codec, 441cc52688aSLars-Peter Clausen struct snd_soc_dai *dai, snd_pcm_format_t format) 442cc52688aSLars-Peter Clausen { 443cc52688aSLars-Peter Clausen unsigned int val; 444cc52688aSLars-Peter Clausen 445cc52688aSLars-Peter Clausen switch (format) { 446cc52688aSLars-Peter Clausen case SNDRV_PCM_FORMAT_S16_LE: 447cc52688aSLars-Peter Clausen val = ADAV80X_CAPTURE_WORD_LEN16; 448cc52688aSLars-Peter Clausen break; 449cc52688aSLars-Peter Clausen case SNDRV_PCM_FORMAT_S18_3LE: 450cc52688aSLars-Peter Clausen val = ADAV80X_CAPTRUE_WORD_LEN18; 451cc52688aSLars-Peter Clausen break; 452cc52688aSLars-Peter Clausen case SNDRV_PCM_FORMAT_S20_3LE: 453cc52688aSLars-Peter Clausen val = ADAV80X_CAPTURE_WORD_LEN20; 454cc52688aSLars-Peter Clausen break; 455cc52688aSLars-Peter Clausen case SNDRV_PCM_FORMAT_S24_LE: 456cc52688aSLars-Peter Clausen val = ADAV80X_CAPTURE_WORD_LEN24; 457cc52688aSLars-Peter Clausen break; 458cc52688aSLars-Peter Clausen default: 459ca1004baSMark Brown return -EINVAL; 460cc52688aSLars-Peter Clausen } 461cc52688aSLars-Peter Clausen 462cc52688aSLars-Peter Clausen snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][0], 463cc52688aSLars-Peter Clausen ADAV80X_CAPTURE_WORD_LEN_MASK, val); 464cc52688aSLars-Peter Clausen 465cc52688aSLars-Peter Clausen return 0; 466cc52688aSLars-Peter Clausen } 467cc52688aSLars-Peter Clausen 468cc52688aSLars-Peter Clausen static int adav80x_set_playback_pcm_format(struct snd_soc_codec *codec, 469cc52688aSLars-Peter Clausen struct snd_soc_dai *dai, snd_pcm_format_t format) 470cc52688aSLars-Peter Clausen { 471cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 472cc52688aSLars-Peter Clausen unsigned int val; 473cc52688aSLars-Peter Clausen 474cc52688aSLars-Peter Clausen if (adav80x->dai_fmt[dai->id] != SND_SOC_DAIFMT_RIGHT_J) 475cc52688aSLars-Peter Clausen return 0; 476cc52688aSLars-Peter Clausen 477cc52688aSLars-Peter Clausen switch (format) { 478cc52688aSLars-Peter Clausen case SNDRV_PCM_FORMAT_S16_LE: 479cc52688aSLars-Peter Clausen val = ADAV80X_PLAYBACK_MODE_RIGHT_J_16; 480cc52688aSLars-Peter Clausen break; 481cc52688aSLars-Peter Clausen case SNDRV_PCM_FORMAT_S18_3LE: 482cc52688aSLars-Peter Clausen val = ADAV80X_PLAYBACK_MODE_RIGHT_J_18; 483cc52688aSLars-Peter Clausen break; 484cc52688aSLars-Peter Clausen case SNDRV_PCM_FORMAT_S20_3LE: 485cc52688aSLars-Peter Clausen val = ADAV80X_PLAYBACK_MODE_RIGHT_J_20; 486cc52688aSLars-Peter Clausen break; 487cc52688aSLars-Peter Clausen case SNDRV_PCM_FORMAT_S24_LE: 488cc52688aSLars-Peter Clausen val = ADAV80X_PLAYBACK_MODE_RIGHT_J_24; 489cc52688aSLars-Peter Clausen break; 490cc52688aSLars-Peter Clausen default: 491ca1004baSMark Brown return -EINVAL; 492cc52688aSLars-Peter Clausen } 493cc52688aSLars-Peter Clausen 494cc52688aSLars-Peter Clausen snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][1], 495cc52688aSLars-Peter Clausen ADAV80X_PLAYBACK_MODE_MASK, val); 496cc52688aSLars-Peter Clausen 497cc52688aSLars-Peter Clausen return 0; 498cc52688aSLars-Peter Clausen } 499cc52688aSLars-Peter Clausen 500cc52688aSLars-Peter Clausen static int adav80x_hw_params(struct snd_pcm_substream *substream, 501cc52688aSLars-Peter Clausen struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 502cc52688aSLars-Peter Clausen { 503cc52688aSLars-Peter Clausen struct snd_soc_codec *codec = dai->codec; 504cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 505cc52688aSLars-Peter Clausen unsigned int rate = params_rate(params); 506cc52688aSLars-Peter Clausen 507cc52688aSLars-Peter Clausen if (rate * 256 != adav80x->sysclk) 508cc52688aSLars-Peter Clausen return -EINVAL; 509cc52688aSLars-Peter Clausen 510cc52688aSLars-Peter Clausen if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 511cc52688aSLars-Peter Clausen adav80x_set_playback_pcm_format(codec, dai, 512cc52688aSLars-Peter Clausen params_format(params)); 513cc52688aSLars-Peter Clausen adav80x_set_dac_clock(codec, rate); 514cc52688aSLars-Peter Clausen } else { 515cc52688aSLars-Peter Clausen adav80x_set_capture_pcm_format(codec, dai, 516cc52688aSLars-Peter Clausen params_format(params)); 517cc52688aSLars-Peter Clausen adav80x_set_adc_clock(codec, rate); 518cc52688aSLars-Peter Clausen } 519cc52688aSLars-Peter Clausen adav80x->rate = rate; 520cc52688aSLars-Peter Clausen adav80x_set_deemph(codec); 521cc52688aSLars-Peter Clausen 522cc52688aSLars-Peter Clausen return 0; 523cc52688aSLars-Peter Clausen } 524cc52688aSLars-Peter Clausen 525cc52688aSLars-Peter Clausen static int adav80x_set_sysclk(struct snd_soc_codec *codec, 526da1c6ea6SMark Brown int clk_id, int source, 527da1c6ea6SMark Brown unsigned int freq, int dir) 528cc52688aSLars-Peter Clausen { 529cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 530cc52688aSLars-Peter Clausen 531cc52688aSLars-Peter Clausen if (dir == SND_SOC_CLOCK_IN) { 532cc52688aSLars-Peter Clausen switch (clk_id) { 533cc52688aSLars-Peter Clausen case ADAV80X_CLK_XIN: 534cc52688aSLars-Peter Clausen case ADAV80X_CLK_XTAL: 535cc52688aSLars-Peter Clausen case ADAV80X_CLK_MCLKI: 536cc52688aSLars-Peter Clausen case ADAV80X_CLK_PLL1: 537cc52688aSLars-Peter Clausen case ADAV80X_CLK_PLL2: 538cc52688aSLars-Peter Clausen break; 539cc52688aSLars-Peter Clausen default: 540cc52688aSLars-Peter Clausen return -EINVAL; 541cc52688aSLars-Peter Clausen } 542cc52688aSLars-Peter Clausen 543cc52688aSLars-Peter Clausen adav80x->sysclk = freq; 544cc52688aSLars-Peter Clausen 545cc52688aSLars-Peter Clausen if (adav80x->clk_src != clk_id) { 546cc52688aSLars-Peter Clausen unsigned int iclk_ctrl1, iclk_ctrl2; 547cc52688aSLars-Peter Clausen 548cc52688aSLars-Peter Clausen adav80x->clk_src = clk_id; 549cc52688aSLars-Peter Clausen if (clk_id == ADAV80X_CLK_XTAL) 550cc52688aSLars-Peter Clausen clk_id = ADAV80X_CLK_XIN; 551cc52688aSLars-Peter Clausen 552cc52688aSLars-Peter Clausen iclk_ctrl1 = ADAV80X_ICLK_CTRL1_DAC_SRC(clk_id) | 553cc52688aSLars-Peter Clausen ADAV80X_ICLK_CTRL1_ADC_SRC(clk_id) | 554cc52688aSLars-Peter Clausen ADAV80X_ICLK_CTRL1_ICLK2_SRC(clk_id); 555cc52688aSLars-Peter Clausen iclk_ctrl2 = ADAV80X_ICLK_CTRL2_ICLK1_SRC(clk_id); 556cc52688aSLars-Peter Clausen 557cc52688aSLars-Peter Clausen snd_soc_write(codec, ADAV80X_ICLK_CTRL1, iclk_ctrl1); 558cc52688aSLars-Peter Clausen snd_soc_write(codec, ADAV80X_ICLK_CTRL2, iclk_ctrl2); 559cc52688aSLars-Peter Clausen 560cc52688aSLars-Peter Clausen snd_soc_dapm_sync(&codec->dapm); 561cc52688aSLars-Peter Clausen } 562cc52688aSLars-Peter Clausen } else { 563cc52688aSLars-Peter Clausen unsigned int mask; 564cc52688aSLars-Peter Clausen 565cc52688aSLars-Peter Clausen switch (clk_id) { 566cc52688aSLars-Peter Clausen case ADAV80X_CLK_SYSCLK1: 567cc52688aSLars-Peter Clausen case ADAV80X_CLK_SYSCLK2: 568cc52688aSLars-Peter Clausen case ADAV80X_CLK_SYSCLK3: 569cc52688aSLars-Peter Clausen break; 570cc52688aSLars-Peter Clausen default: 571cc52688aSLars-Peter Clausen return -EINVAL; 572cc52688aSLars-Peter Clausen } 573cc52688aSLars-Peter Clausen 574cc52688aSLars-Peter Clausen clk_id -= ADAV80X_CLK_SYSCLK1; 575cc52688aSLars-Peter Clausen mask = ADAV80X_PLL_OUTE_SYSCLKPD(clk_id); 576cc52688aSLars-Peter Clausen 577cc52688aSLars-Peter Clausen if (freq == 0) { 578cc52688aSLars-Peter Clausen snd_soc_update_bits(codec, ADAV80X_PLL_OUTE, mask, mask); 579cc52688aSLars-Peter Clausen adav80x->sysclk_pd[clk_id] = true; 580cc52688aSLars-Peter Clausen } else { 581cc52688aSLars-Peter Clausen snd_soc_update_bits(codec, ADAV80X_PLL_OUTE, mask, 0); 582cc52688aSLars-Peter Clausen adav80x->sysclk_pd[clk_id] = false; 583cc52688aSLars-Peter Clausen } 584cc52688aSLars-Peter Clausen 585cc52688aSLars-Peter Clausen if (adav80x->sysclk_pd[0]) 586cc52688aSLars-Peter Clausen snd_soc_dapm_disable_pin(&codec->dapm, "PLL1"); 587cc52688aSLars-Peter Clausen else 588cc52688aSLars-Peter Clausen snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); 589cc52688aSLars-Peter Clausen 590cc52688aSLars-Peter Clausen if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2]) 591cc52688aSLars-Peter Clausen snd_soc_dapm_disable_pin(&codec->dapm, "PLL2"); 592cc52688aSLars-Peter Clausen else 593cc52688aSLars-Peter Clausen snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); 594cc52688aSLars-Peter Clausen 595cc52688aSLars-Peter Clausen snd_soc_dapm_sync(&codec->dapm); 596cc52688aSLars-Peter Clausen } 597cc52688aSLars-Peter Clausen 598cc52688aSLars-Peter Clausen return 0; 599cc52688aSLars-Peter Clausen } 600cc52688aSLars-Peter Clausen 601cc52688aSLars-Peter Clausen static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id, 602cc52688aSLars-Peter Clausen int source, unsigned int freq_in, unsigned int freq_out) 603cc52688aSLars-Peter Clausen { 604cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 605cc52688aSLars-Peter Clausen unsigned int pll_ctrl1 = 0; 606cc52688aSLars-Peter Clausen unsigned int pll_ctrl2 = 0; 607cc52688aSLars-Peter Clausen unsigned int pll_src; 608cc52688aSLars-Peter Clausen 609cc52688aSLars-Peter Clausen switch (source) { 610cc52688aSLars-Peter Clausen case ADAV80X_PLL_SRC_XTAL: 611cc52688aSLars-Peter Clausen case ADAV80X_PLL_SRC_XIN: 612cc52688aSLars-Peter Clausen case ADAV80X_PLL_SRC_MCLKI: 613cc52688aSLars-Peter Clausen break; 614cc52688aSLars-Peter Clausen default: 615cc52688aSLars-Peter Clausen return -EINVAL; 616cc52688aSLars-Peter Clausen } 617cc52688aSLars-Peter Clausen 618cc52688aSLars-Peter Clausen if (!freq_out) 619cc52688aSLars-Peter Clausen return 0; 620cc52688aSLars-Peter Clausen 621cc52688aSLars-Peter Clausen switch (freq_in) { 622cc52688aSLars-Peter Clausen case 27000000: 623cc52688aSLars-Peter Clausen break; 624cc52688aSLars-Peter Clausen case 54000000: 625cc52688aSLars-Peter Clausen if (source == ADAV80X_PLL_SRC_XIN) { 626cc52688aSLars-Peter Clausen pll_ctrl1 |= ADAV80X_PLL_CTRL1_PLLDIV; 627cc52688aSLars-Peter Clausen break; 628cc52688aSLars-Peter Clausen } 629cc52688aSLars-Peter Clausen default: 630cc52688aSLars-Peter Clausen return -EINVAL; 631cc52688aSLars-Peter Clausen } 632cc52688aSLars-Peter Clausen 633cc52688aSLars-Peter Clausen if (freq_out > 12288000) { 634cc52688aSLars-Peter Clausen pll_ctrl2 |= ADAV80X_PLL_CTRL2_DOUB(pll_id); 635cc52688aSLars-Peter Clausen freq_out /= 2; 636cc52688aSLars-Peter Clausen } 637cc52688aSLars-Peter Clausen 638cc52688aSLars-Peter Clausen /* freq_out = sample_rate * 256 */ 639cc52688aSLars-Peter Clausen switch (freq_out) { 640cc52688aSLars-Peter Clausen case 8192000: 641cc52688aSLars-Peter Clausen pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_32(pll_id); 642cc52688aSLars-Peter Clausen break; 643cc52688aSLars-Peter Clausen case 11289600: 644cc52688aSLars-Peter Clausen pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_44(pll_id); 645cc52688aSLars-Peter Clausen break; 646cc52688aSLars-Peter Clausen case 12288000: 647cc52688aSLars-Peter Clausen pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_48(pll_id); 648cc52688aSLars-Peter Clausen break; 649cc52688aSLars-Peter Clausen default: 650cc52688aSLars-Peter Clausen return -EINVAL; 651cc52688aSLars-Peter Clausen } 652cc52688aSLars-Peter Clausen 653cc52688aSLars-Peter Clausen snd_soc_update_bits(codec, ADAV80X_PLL_CTRL1, ADAV80X_PLL_CTRL1_PLLDIV, 654cc52688aSLars-Peter Clausen pll_ctrl1); 655cc52688aSLars-Peter Clausen snd_soc_update_bits(codec, ADAV80X_PLL_CTRL2, 656cc52688aSLars-Peter Clausen ADAV80X_PLL_CTRL2_PLL_MASK(pll_id), pll_ctrl2); 657cc52688aSLars-Peter Clausen 658cc52688aSLars-Peter Clausen if (source != adav80x->pll_src) { 659cc52688aSLars-Peter Clausen if (source == ADAV80X_PLL_SRC_MCLKI) 660cc52688aSLars-Peter Clausen pll_src = ADAV80X_PLL_CLK_SRC_PLL_MCLKI(pll_id); 661cc52688aSLars-Peter Clausen else 662cc52688aSLars-Peter Clausen pll_src = ADAV80X_PLL_CLK_SRC_PLL_XIN(pll_id); 663cc52688aSLars-Peter Clausen 664cc52688aSLars-Peter Clausen snd_soc_update_bits(codec, ADAV80X_PLL_CLK_SRC, 665cc52688aSLars-Peter Clausen ADAV80X_PLL_CLK_SRC_PLL_MASK(pll_id), pll_src); 666cc52688aSLars-Peter Clausen 667cc52688aSLars-Peter Clausen adav80x->pll_src = source; 668cc52688aSLars-Peter Clausen 669cc52688aSLars-Peter Clausen snd_soc_dapm_sync(&codec->dapm); 670cc52688aSLars-Peter Clausen } 671cc52688aSLars-Peter Clausen 672cc52688aSLars-Peter Clausen return 0; 673cc52688aSLars-Peter Clausen } 674cc52688aSLars-Peter Clausen 675cc52688aSLars-Peter Clausen static int adav80x_set_bias_level(struct snd_soc_codec *codec, 676cc52688aSLars-Peter Clausen enum snd_soc_bias_level level) 677cc52688aSLars-Peter Clausen { 678cc52688aSLars-Peter Clausen unsigned int mask = ADAV80X_DAC_CTRL1_PD; 679cc52688aSLars-Peter Clausen 680cc52688aSLars-Peter Clausen switch (level) { 681cc52688aSLars-Peter Clausen case SND_SOC_BIAS_ON: 682cc52688aSLars-Peter Clausen break; 683cc52688aSLars-Peter Clausen case SND_SOC_BIAS_PREPARE: 684cc52688aSLars-Peter Clausen break; 685cc52688aSLars-Peter Clausen case SND_SOC_BIAS_STANDBY: 686cc52688aSLars-Peter Clausen snd_soc_update_bits(codec, ADAV80X_DAC_CTRL1, mask, 0x00); 687cc52688aSLars-Peter Clausen break; 688cc52688aSLars-Peter Clausen case SND_SOC_BIAS_OFF: 689cc52688aSLars-Peter Clausen snd_soc_update_bits(codec, ADAV80X_DAC_CTRL1, mask, mask); 690cc52688aSLars-Peter Clausen break; 691cc52688aSLars-Peter Clausen } 692cc52688aSLars-Peter Clausen 693cc52688aSLars-Peter Clausen codec->dapm.bias_level = level; 694cc52688aSLars-Peter Clausen return 0; 695cc52688aSLars-Peter Clausen } 696cc52688aSLars-Peter Clausen 697cc52688aSLars-Peter Clausen /* Enforce the same sample rate on all audio interfaces */ 698cc52688aSLars-Peter Clausen static int adav80x_dai_startup(struct snd_pcm_substream *substream, 699cc52688aSLars-Peter Clausen struct snd_soc_dai *dai) 700cc52688aSLars-Peter Clausen { 701cc52688aSLars-Peter Clausen struct snd_soc_codec *codec = dai->codec; 702cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 703cc52688aSLars-Peter Clausen 704cc52688aSLars-Peter Clausen if (!codec->active || !adav80x->rate) 705cc52688aSLars-Peter Clausen return 0; 706cc52688aSLars-Peter Clausen 707cc52688aSLars-Peter Clausen return snd_pcm_hw_constraint_minmax(substream->runtime, 708cc52688aSLars-Peter Clausen SNDRV_PCM_HW_PARAM_RATE, adav80x->rate, adav80x->rate); 709cc52688aSLars-Peter Clausen } 710cc52688aSLars-Peter Clausen 711cc52688aSLars-Peter Clausen static void adav80x_dai_shutdown(struct snd_pcm_substream *substream, 712cc52688aSLars-Peter Clausen struct snd_soc_dai *dai) 713cc52688aSLars-Peter Clausen { 714cc52688aSLars-Peter Clausen struct snd_soc_codec *codec = dai->codec; 715cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 716cc52688aSLars-Peter Clausen 717cc52688aSLars-Peter Clausen if (!codec->active) 718cc52688aSLars-Peter Clausen adav80x->rate = 0; 719cc52688aSLars-Peter Clausen } 720cc52688aSLars-Peter Clausen 721890754a8SLars-Peter Clausen static const struct snd_soc_dai_ops adav80x_dai_ops = { 722cc52688aSLars-Peter Clausen .set_fmt = adav80x_set_dai_fmt, 723cc52688aSLars-Peter Clausen .hw_params = adav80x_hw_params, 724cc52688aSLars-Peter Clausen .startup = adav80x_dai_startup, 725cc52688aSLars-Peter Clausen .shutdown = adav80x_dai_shutdown, 726cc52688aSLars-Peter Clausen }; 727cc52688aSLars-Peter Clausen 728cc52688aSLars-Peter Clausen #define ADAV80X_PLAYBACK_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ 729cc52688aSLars-Peter Clausen SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | \ 730cc52688aSLars-Peter Clausen SNDRV_PCM_RATE_96000) 731cc52688aSLars-Peter Clausen 732cc52688aSLars-Peter Clausen #define ADAV80X_CAPTURE_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) 733cc52688aSLars-Peter Clausen 734cc52688aSLars-Peter Clausen #define ADAV80X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \ 735cc52688aSLars-Peter Clausen SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) 736cc52688aSLars-Peter Clausen 737cc52688aSLars-Peter Clausen static struct snd_soc_dai_driver adav80x_dais[] = { 738cc52688aSLars-Peter Clausen { 739cc52688aSLars-Peter Clausen .name = "adav80x-hifi", 740cc52688aSLars-Peter Clausen .id = 0, 741cc52688aSLars-Peter Clausen .playback = { 742cc52688aSLars-Peter Clausen .stream_name = "HiFi Playback", 743cc52688aSLars-Peter Clausen .channels_min = 2, 744cc52688aSLars-Peter Clausen .channels_max = 2, 745cc52688aSLars-Peter Clausen .rates = ADAV80X_PLAYBACK_RATES, 746cc52688aSLars-Peter Clausen .formats = ADAV80X_FORMATS, 747cc52688aSLars-Peter Clausen }, 748cc52688aSLars-Peter Clausen .capture = { 749cc52688aSLars-Peter Clausen .stream_name = "HiFi Capture", 750cc52688aSLars-Peter Clausen .channels_min = 2, 751cc52688aSLars-Peter Clausen .channels_max = 2, 752cc52688aSLars-Peter Clausen .rates = ADAV80X_CAPTURE_RATES, 753cc52688aSLars-Peter Clausen .formats = ADAV80X_FORMATS, 754cc52688aSLars-Peter Clausen }, 755cc52688aSLars-Peter Clausen .ops = &adav80x_dai_ops, 756cc52688aSLars-Peter Clausen }, 757cc52688aSLars-Peter Clausen { 758cc52688aSLars-Peter Clausen .name = "adav80x-aux", 759cc52688aSLars-Peter Clausen .id = 1, 760cc52688aSLars-Peter Clausen .playback = { 761cc52688aSLars-Peter Clausen .stream_name = "Aux Playback", 762cc52688aSLars-Peter Clausen .channels_min = 2, 763cc52688aSLars-Peter Clausen .channels_max = 2, 764cc52688aSLars-Peter Clausen .rates = ADAV80X_PLAYBACK_RATES, 765cc52688aSLars-Peter Clausen .formats = ADAV80X_FORMATS, 766cc52688aSLars-Peter Clausen }, 767cc52688aSLars-Peter Clausen .capture = { 768cc52688aSLars-Peter Clausen .stream_name = "Aux Capture", 769cc52688aSLars-Peter Clausen .channels_min = 2, 770cc52688aSLars-Peter Clausen .channels_max = 2, 771cc52688aSLars-Peter Clausen .rates = ADAV80X_CAPTURE_RATES, 772cc52688aSLars-Peter Clausen .formats = ADAV80X_FORMATS, 773cc52688aSLars-Peter Clausen }, 774cc52688aSLars-Peter Clausen .ops = &adav80x_dai_ops, 775cc52688aSLars-Peter Clausen }, 776cc52688aSLars-Peter Clausen }; 777cc52688aSLars-Peter Clausen 778cc52688aSLars-Peter Clausen static int adav80x_probe(struct snd_soc_codec *codec) 779cc52688aSLars-Peter Clausen { 780cc52688aSLars-Peter Clausen int ret; 781cc52688aSLars-Peter Clausen struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 782cc52688aSLars-Peter Clausen 783cc52688aSLars-Peter Clausen ret = snd_soc_codec_set_cache_io(codec, 7, 9, adav80x->control_type); 784cc52688aSLars-Peter Clausen if (ret) { 785cc52688aSLars-Peter Clausen dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); 786cc52688aSLars-Peter Clausen return ret; 787cc52688aSLars-Peter Clausen } 788cc52688aSLars-Peter Clausen 789cc52688aSLars-Peter Clausen /* Force PLLs on for SYSCLK output */ 790cc52688aSLars-Peter Clausen snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); 791cc52688aSLars-Peter Clausen snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); 792cc52688aSLars-Peter Clausen 793cc52688aSLars-Peter Clausen /* Power down S/PDIF receiver, since it is currently not supported */ 794cc52688aSLars-Peter Clausen snd_soc_write(codec, ADAV80X_PLL_OUTE, 0x20); 795cc52688aSLars-Peter Clausen /* Disable DAC zero flag */ 796cc52688aSLars-Peter Clausen snd_soc_write(codec, ADAV80X_DAC_CTRL3, 0x6); 797cc52688aSLars-Peter Clausen 798cc52688aSLars-Peter Clausen return adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 799cc52688aSLars-Peter Clausen } 800cc52688aSLars-Peter Clausen 80184b315eeSLars-Peter Clausen static int adav80x_suspend(struct snd_soc_codec *codec) 802cc52688aSLars-Peter Clausen { 803cc52688aSLars-Peter Clausen return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF); 804cc52688aSLars-Peter Clausen } 805cc52688aSLars-Peter Clausen 806cc52688aSLars-Peter Clausen static int adav80x_resume(struct snd_soc_codec *codec) 807cc52688aSLars-Peter Clausen { 808cc52688aSLars-Peter Clausen adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 809cc52688aSLars-Peter Clausen codec->cache_sync = 1; 810cc52688aSLars-Peter Clausen snd_soc_cache_sync(codec); 811cc52688aSLars-Peter Clausen 812cc52688aSLars-Peter Clausen return 0; 813cc52688aSLars-Peter Clausen } 814cc52688aSLars-Peter Clausen 815cc52688aSLars-Peter Clausen static int adav80x_remove(struct snd_soc_codec *codec) 816cc52688aSLars-Peter Clausen { 817cc52688aSLars-Peter Clausen return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF); 818cc52688aSLars-Peter Clausen } 819cc52688aSLars-Peter Clausen 820cc52688aSLars-Peter Clausen static struct snd_soc_codec_driver adav80x_codec_driver = { 821cc52688aSLars-Peter Clausen .probe = adav80x_probe, 822cc52688aSLars-Peter Clausen .remove = adav80x_remove, 823cc52688aSLars-Peter Clausen .suspend = adav80x_suspend, 824cc52688aSLars-Peter Clausen .resume = adav80x_resume, 825cc52688aSLars-Peter Clausen .set_bias_level = adav80x_set_bias_level, 826cc52688aSLars-Peter Clausen 827cc52688aSLars-Peter Clausen .set_pll = adav80x_set_pll, 828cc52688aSLars-Peter Clausen .set_sysclk = adav80x_set_sysclk, 829cc52688aSLars-Peter Clausen 830cc52688aSLars-Peter Clausen .reg_word_size = sizeof(u8), 831cc52688aSLars-Peter Clausen .reg_cache_size = ARRAY_SIZE(adav80x_default_regs), 832cc52688aSLars-Peter Clausen .reg_cache_default = adav80x_default_regs, 833cc52688aSLars-Peter Clausen 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), 840cc52688aSLars-Peter Clausen }; 841cc52688aSLars-Peter Clausen 842cc52688aSLars-Peter Clausen static int __devinit adav80x_bus_probe(struct device *dev, 843cc52688aSLars-Peter Clausen enum snd_soc_control_type control_type) 844cc52688aSLars-Peter Clausen { 845cc52688aSLars-Peter Clausen struct adav80x *adav80x; 846cc52688aSLars-Peter Clausen int ret; 847cc52688aSLars-Peter Clausen 848cc52688aSLars-Peter Clausen adav80x = kzalloc(sizeof(*adav80x), GFP_KERNEL); 849cc52688aSLars-Peter Clausen if (!adav80x) 850cc52688aSLars-Peter Clausen return -ENOMEM; 851cc52688aSLars-Peter Clausen 852cc52688aSLars-Peter Clausen dev_set_drvdata(dev, adav80x); 853cc52688aSLars-Peter Clausen adav80x->control_type = control_type; 854cc52688aSLars-Peter Clausen 855cc52688aSLars-Peter Clausen ret = snd_soc_register_codec(dev, &adav80x_codec_driver, 856cc52688aSLars-Peter Clausen adav80x_dais, ARRAY_SIZE(adav80x_dais)); 857cc52688aSLars-Peter Clausen if (ret) 858cc52688aSLars-Peter Clausen kfree(adav80x); 859cc52688aSLars-Peter Clausen 860cc52688aSLars-Peter Clausen return ret; 861cc52688aSLars-Peter Clausen } 862cc52688aSLars-Peter Clausen 863cc52688aSLars-Peter Clausen static int __devexit adav80x_bus_remove(struct device *dev) 864cc52688aSLars-Peter Clausen { 865cc52688aSLars-Peter Clausen snd_soc_unregister_codec(dev); 866cc52688aSLars-Peter Clausen kfree(dev_get_drvdata(dev)); 867cc52688aSLars-Peter Clausen return 0; 868cc52688aSLars-Peter Clausen } 869cc52688aSLars-Peter Clausen 870cc52688aSLars-Peter Clausen #if defined(CONFIG_SPI_MASTER) 871cc52688aSLars-Peter Clausen static int __devinit adav80x_spi_probe(struct spi_device *spi) 872cc52688aSLars-Peter Clausen { 873cc52688aSLars-Peter Clausen return adav80x_bus_probe(&spi->dev, SND_SOC_SPI); 874cc52688aSLars-Peter Clausen } 875cc52688aSLars-Peter Clausen 876cc52688aSLars-Peter Clausen static int __devexit adav80x_spi_remove(struct spi_device *spi) 877cc52688aSLars-Peter Clausen { 878cc52688aSLars-Peter Clausen return adav80x_bus_remove(&spi->dev); 879cc52688aSLars-Peter Clausen } 880cc52688aSLars-Peter Clausen 881cc52688aSLars-Peter Clausen static struct spi_driver adav80x_spi_driver = { 882cc52688aSLars-Peter Clausen .driver = { 883cc52688aSLars-Peter Clausen .name = "adav801", 884cc52688aSLars-Peter Clausen .owner = THIS_MODULE, 885cc52688aSLars-Peter Clausen }, 886cc52688aSLars-Peter Clausen .probe = adav80x_spi_probe, 887cc52688aSLars-Peter Clausen .remove = __devexit_p(adav80x_spi_remove), 888cc52688aSLars-Peter Clausen }; 889cc52688aSLars-Peter Clausen #endif 890cc52688aSLars-Peter Clausen 891cc52688aSLars-Peter Clausen #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 892cc52688aSLars-Peter Clausen static const struct i2c_device_id adav80x_id[] = { 893cc52688aSLars-Peter Clausen { "adav803", 0 }, 894cc52688aSLars-Peter Clausen { } 895cc52688aSLars-Peter Clausen }; 896cc52688aSLars-Peter Clausen MODULE_DEVICE_TABLE(i2c, adav80x_id); 897cc52688aSLars-Peter Clausen 898cc52688aSLars-Peter Clausen static int __devinit adav80x_i2c_probe(struct i2c_client *client, 899cc52688aSLars-Peter Clausen const struct i2c_device_id *id) 900cc52688aSLars-Peter Clausen { 901cc52688aSLars-Peter Clausen return adav80x_bus_probe(&client->dev, SND_SOC_I2C); 902cc52688aSLars-Peter Clausen } 903cc52688aSLars-Peter Clausen 904cc52688aSLars-Peter Clausen static int __devexit adav80x_i2c_remove(struct i2c_client *client) 905cc52688aSLars-Peter Clausen { 906cc52688aSLars-Peter Clausen return adav80x_bus_remove(&client->dev); 907cc52688aSLars-Peter Clausen } 908cc52688aSLars-Peter Clausen 909cc52688aSLars-Peter Clausen static struct i2c_driver adav80x_i2c_driver = { 910cc52688aSLars-Peter Clausen .driver = { 911cc52688aSLars-Peter Clausen .name = "adav803", 912cc52688aSLars-Peter Clausen .owner = THIS_MODULE, 913cc52688aSLars-Peter Clausen }, 914cc52688aSLars-Peter Clausen .probe = adav80x_i2c_probe, 915cc52688aSLars-Peter Clausen .remove = __devexit_p(adav80x_i2c_remove), 916cc52688aSLars-Peter Clausen .id_table = adav80x_id, 917cc52688aSLars-Peter Clausen }; 918cc52688aSLars-Peter Clausen #endif 919cc52688aSLars-Peter Clausen 920cc52688aSLars-Peter Clausen static int __init adav80x_init(void) 921cc52688aSLars-Peter Clausen { 922cc52688aSLars-Peter Clausen int ret = 0; 923cc52688aSLars-Peter Clausen 924cc52688aSLars-Peter Clausen #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 925cc52688aSLars-Peter Clausen ret = i2c_add_driver(&adav80x_i2c_driver); 926cc52688aSLars-Peter Clausen if (ret) 927cc52688aSLars-Peter Clausen return ret; 928cc52688aSLars-Peter Clausen #endif 929cc52688aSLars-Peter Clausen 930cc52688aSLars-Peter Clausen #if defined(CONFIG_SPI_MASTER) 931cc52688aSLars-Peter Clausen ret = spi_register_driver(&adav80x_spi_driver); 932cc52688aSLars-Peter Clausen #endif 933cc52688aSLars-Peter Clausen 934cc52688aSLars-Peter Clausen return ret; 935cc52688aSLars-Peter Clausen } 936cc52688aSLars-Peter Clausen module_init(adav80x_init); 937cc52688aSLars-Peter Clausen 938cc52688aSLars-Peter Clausen static void __exit adav80x_exit(void) 939cc52688aSLars-Peter Clausen { 940cc52688aSLars-Peter Clausen #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 941cc52688aSLars-Peter Clausen i2c_del_driver(&adav80x_i2c_driver); 942cc52688aSLars-Peter Clausen #endif 943cc52688aSLars-Peter Clausen #if defined(CONFIG_SPI_MASTER) 944cc52688aSLars-Peter Clausen spi_unregister_driver(&adav80x_spi_driver); 945cc52688aSLars-Peter Clausen #endif 946cc52688aSLars-Peter Clausen } 947cc52688aSLars-Peter Clausen module_exit(adav80x_exit); 948cc52688aSLars-Peter Clausen 949cc52688aSLars-Peter Clausen MODULE_DESCRIPTION("ASoC ADAV80x driver"); 950cc52688aSLars-Peter Clausen MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 951cc52688aSLars-Peter Clausen MODULE_AUTHOR("Yi Li <yi.li@analog.com>>"); 952cc52688aSLars-Peter Clausen MODULE_LICENSE("GPL"); 953