1a1533d94SBarry Song /* 2a1533d94SBarry Song * AD193X Audio Codec driver supporting AD1936/7/8/9 3a1533d94SBarry Song * 4a1533d94SBarry Song * Copyright 2010 Analog Devices Inc. 5a1533d94SBarry Song * 6a1533d94SBarry Song * Licensed under the GPL-2 or later. 7a1533d94SBarry Song */ 8a1533d94SBarry Song 9a1533d94SBarry Song #include <linux/init.h> 10a1533d94SBarry Song #include <linux/module.h> 11a1533d94SBarry Song #include <linux/kernel.h> 12a1533d94SBarry Song #include <linux/device.h> 13a1533d94SBarry Song #include <linux/i2c.h> 14a1533d94SBarry Song #include <linux/spi/spi.h> 151b132ea0SStephen Rothwell #include <linux/slab.h> 16a1533d94SBarry Song #include <sound/core.h> 17a1533d94SBarry Song #include <sound/pcm.h> 18a1533d94SBarry Song #include <sound/pcm_params.h> 19a1533d94SBarry Song #include <sound/initval.h> 20a1533d94SBarry Song #include <sound/soc.h> 21a1533d94SBarry Song #include <sound/tlv.h> 22a1533d94SBarry Song #include <sound/soc-dapm.h> 23a1533d94SBarry Song #include "ad193x.h" 24a1533d94SBarry Song 25a1533d94SBarry Song /* codec private data */ 26a1533d94SBarry Song struct ad193x_priv { 27*fab90aa4SBarry Song unsigned int sysclk; 28a1533d94SBarry Song struct snd_soc_codec codec; 29a1533d94SBarry Song u8 reg_cache[AD193X_NUM_REGS]; 30a1533d94SBarry Song }; 31a1533d94SBarry Song 32a1533d94SBarry Song /* ad193x register cache & default register settings */ 33a1533d94SBarry Song static const u8 ad193x_reg[AD193X_NUM_REGS] = { 34a1533d94SBarry Song 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 35a1533d94SBarry Song }; 36a1533d94SBarry Song 37a1533d94SBarry Song static struct snd_soc_codec *ad193x_codec; 38a1533d94SBarry Song struct snd_soc_codec_device soc_codec_dev_ad193x; 39a1533d94SBarry Song 40a1533d94SBarry Song /* 41a1533d94SBarry Song * AD193X volume/mute/de-emphasis etc. controls 42a1533d94SBarry Song */ 43a1533d94SBarry Song static const char *ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"}; 44a1533d94SBarry Song 45a1533d94SBarry Song static const struct soc_enum ad193x_deemp_enum = 46a1533d94SBarry Song SOC_ENUM_SINGLE(AD193X_DAC_CTRL2, 1, 4, ad193x_deemp); 47a1533d94SBarry Song 48a1533d94SBarry Song static const struct snd_kcontrol_new ad193x_snd_controls[] = { 49a1533d94SBarry Song /* DAC volume control */ 50a1533d94SBarry Song SOC_DOUBLE_R("DAC1 Volume", AD193X_DAC_L1_VOL, 51a1533d94SBarry Song AD193X_DAC_R1_VOL, 0, 0xFF, 1), 52a1533d94SBarry Song SOC_DOUBLE_R("DAC2 Volume", AD193X_DAC_L2_VOL, 53a1533d94SBarry Song AD193X_DAC_R2_VOL, 0, 0xFF, 1), 54a1533d94SBarry Song SOC_DOUBLE_R("DAC3 Volume", AD193X_DAC_L3_VOL, 55a1533d94SBarry Song AD193X_DAC_R3_VOL, 0, 0xFF, 1), 56a1533d94SBarry Song SOC_DOUBLE_R("DAC4 Volume", AD193X_DAC_L4_VOL, 57a1533d94SBarry Song AD193X_DAC_R4_VOL, 0, 0xFF, 1), 58a1533d94SBarry Song 59a1533d94SBarry Song /* ADC switch control */ 60a1533d94SBarry Song SOC_DOUBLE("ADC1 Switch", AD193X_ADC_CTRL0, AD193X_ADCL1_MUTE, 61a1533d94SBarry Song AD193X_ADCR1_MUTE, 1, 1), 62a1533d94SBarry Song SOC_DOUBLE("ADC2 Switch", AD193X_ADC_CTRL0, AD193X_ADCL2_MUTE, 63a1533d94SBarry Song AD193X_ADCR2_MUTE, 1, 1), 64a1533d94SBarry Song 65a1533d94SBarry Song /* DAC switch control */ 66a1533d94SBarry Song SOC_DOUBLE("DAC1 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL1_MUTE, 67a1533d94SBarry Song AD193X_DACR1_MUTE, 1, 1), 68a1533d94SBarry Song SOC_DOUBLE("DAC2 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL2_MUTE, 69a1533d94SBarry Song AD193X_DACR2_MUTE, 1, 1), 70a1533d94SBarry Song SOC_DOUBLE("DAC3 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL3_MUTE, 71a1533d94SBarry Song AD193X_DACR3_MUTE, 1, 1), 72a1533d94SBarry Song SOC_DOUBLE("DAC4 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL4_MUTE, 73a1533d94SBarry Song AD193X_DACR4_MUTE, 1, 1), 74a1533d94SBarry Song 75a1533d94SBarry Song /* ADC high-pass filter */ 76a1533d94SBarry Song SOC_SINGLE("ADC High Pass Filter Switch", AD193X_ADC_CTRL0, 77a1533d94SBarry Song AD193X_ADC_HIGHPASS_FILTER, 1, 0), 78a1533d94SBarry Song 79a1533d94SBarry Song /* DAC de-emphasis */ 80a1533d94SBarry Song SOC_ENUM("Playback Deemphasis", ad193x_deemp_enum), 81a1533d94SBarry Song }; 82a1533d94SBarry Song 83a1533d94SBarry Song static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = { 84a1533d94SBarry Song SND_SOC_DAPM_DAC("DAC", "Playback", AD193X_DAC_CTRL0, 0, 1), 85a1533d94SBarry Song SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), 86a1533d94SBarry Song SND_SOC_DAPM_SUPPLY("PLL_PWR", AD193X_PLL_CLK_CTRL0, 0, 1, NULL, 0), 87a1533d94SBarry Song SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0), 88a1533d94SBarry Song SND_SOC_DAPM_OUTPUT("DAC1OUT"), 89a1533d94SBarry Song SND_SOC_DAPM_OUTPUT("DAC2OUT"), 90a1533d94SBarry Song SND_SOC_DAPM_OUTPUT("DAC3OUT"), 91a1533d94SBarry Song SND_SOC_DAPM_OUTPUT("DAC4OUT"), 92a1533d94SBarry Song SND_SOC_DAPM_INPUT("ADC1IN"), 93a1533d94SBarry Song SND_SOC_DAPM_INPUT("ADC2IN"), 94a1533d94SBarry Song }; 95a1533d94SBarry Song 96a1533d94SBarry Song static const struct snd_soc_dapm_route audio_paths[] = { 97a1533d94SBarry Song { "DAC", NULL, "PLL_PWR" }, 98a1533d94SBarry Song { "ADC", NULL, "PLL_PWR" }, 99a1533d94SBarry Song { "DAC", NULL, "ADC_PWR" }, 100a1533d94SBarry Song { "ADC", NULL, "ADC_PWR" }, 101a1533d94SBarry Song { "DAC1OUT", "DAC1 Switch", "DAC" }, 102a1533d94SBarry Song { "DAC2OUT", "DAC2 Switch", "DAC" }, 103a1533d94SBarry Song { "DAC3OUT", "DAC3 Switch", "DAC" }, 104a1533d94SBarry Song { "DAC4OUT", "DAC4 Switch", "DAC" }, 105a1533d94SBarry Song { "ADC", "ADC1 Switch", "ADC1IN" }, 106a1533d94SBarry Song { "ADC", "ADC2 Switch", "ADC2IN" }, 107a1533d94SBarry Song }; 108a1533d94SBarry Song 109a1533d94SBarry Song /* 110a1533d94SBarry Song * DAI ops entries 111a1533d94SBarry Song */ 112a1533d94SBarry Song 113a1533d94SBarry Song static int ad193x_mute(struct snd_soc_dai *dai, int mute) 114a1533d94SBarry Song { 115a1533d94SBarry Song struct snd_soc_codec *codec = dai->codec; 116a1533d94SBarry Song int reg; 117a1533d94SBarry Song 118a1533d94SBarry Song reg = snd_soc_read(codec, AD193X_DAC_CTRL2); 119a1533d94SBarry Song reg = (mute > 0) ? reg | AD193X_DAC_MASTER_MUTE : reg & 120a1533d94SBarry Song (~AD193X_DAC_MASTER_MUTE); 121a1533d94SBarry Song snd_soc_write(codec, AD193X_DAC_CTRL2, reg); 122a1533d94SBarry Song 123a1533d94SBarry Song return 0; 124a1533d94SBarry Song } 125a1533d94SBarry Song 126a1533d94SBarry Song static int ad193x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 127a1533d94SBarry Song unsigned int rx_mask, int slots, int width) 128a1533d94SBarry Song { 129a1533d94SBarry Song struct snd_soc_codec *codec = dai->codec; 130a1533d94SBarry Song int dac_reg = snd_soc_read(codec, AD193X_DAC_CTRL1); 131a1533d94SBarry Song int adc_reg = snd_soc_read(codec, AD193X_ADC_CTRL2); 132a1533d94SBarry Song 133a1533d94SBarry Song dac_reg &= ~AD193X_DAC_CHAN_MASK; 134a1533d94SBarry Song adc_reg &= ~AD193X_ADC_CHAN_MASK; 135a1533d94SBarry Song 136a1533d94SBarry Song switch (slots) { 137a1533d94SBarry Song case 2: 138a1533d94SBarry Song dac_reg |= AD193X_DAC_2_CHANNELS << AD193X_DAC_CHAN_SHFT; 139a1533d94SBarry Song adc_reg |= AD193X_ADC_2_CHANNELS << AD193X_ADC_CHAN_SHFT; 140a1533d94SBarry Song break; 141a1533d94SBarry Song case 4: 142a1533d94SBarry Song dac_reg |= AD193X_DAC_4_CHANNELS << AD193X_DAC_CHAN_SHFT; 143a1533d94SBarry Song adc_reg |= AD193X_ADC_4_CHANNELS << AD193X_ADC_CHAN_SHFT; 144a1533d94SBarry Song break; 145a1533d94SBarry Song case 8: 146a1533d94SBarry Song dac_reg |= AD193X_DAC_8_CHANNELS << AD193X_DAC_CHAN_SHFT; 147a1533d94SBarry Song adc_reg |= AD193X_ADC_8_CHANNELS << AD193X_ADC_CHAN_SHFT; 148a1533d94SBarry Song break; 149a1533d94SBarry Song case 16: 150a1533d94SBarry Song dac_reg |= AD193X_DAC_16_CHANNELS << AD193X_DAC_CHAN_SHFT; 151a1533d94SBarry Song adc_reg |= AD193X_ADC_16_CHANNELS << AD193X_ADC_CHAN_SHFT; 152a1533d94SBarry Song break; 153a1533d94SBarry Song default: 154a1533d94SBarry Song return -EINVAL; 155a1533d94SBarry Song } 156a1533d94SBarry Song 157a1533d94SBarry Song snd_soc_write(codec, AD193X_DAC_CTRL1, dac_reg); 158a1533d94SBarry Song snd_soc_write(codec, AD193X_ADC_CTRL2, adc_reg); 159a1533d94SBarry Song 160a1533d94SBarry Song return 0; 161a1533d94SBarry Song } 162a1533d94SBarry Song 163a1533d94SBarry Song static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai, 164a1533d94SBarry Song unsigned int fmt) 165a1533d94SBarry Song { 166a1533d94SBarry Song struct snd_soc_codec *codec = codec_dai->codec; 167d6bdc0f7SBarry Song int adc_reg1, adc_reg2, dac_reg; 168a1533d94SBarry Song 169d6bdc0f7SBarry Song adc_reg1 = snd_soc_read(codec, AD193X_ADC_CTRL1); 170d6bdc0f7SBarry Song adc_reg2 = snd_soc_read(codec, AD193X_ADC_CTRL2); 171a1533d94SBarry Song dac_reg = snd_soc_read(codec, AD193X_DAC_CTRL1); 172a1533d94SBarry Song 173a1533d94SBarry Song /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S 174a1533d94SBarry Song * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A) 175a1533d94SBarry Song */ 176a1533d94SBarry Song switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 177a1533d94SBarry Song case SND_SOC_DAIFMT_I2S: 178d6bdc0f7SBarry Song adc_reg1 &= ~AD193X_ADC_SERFMT_MASK; 179d6bdc0f7SBarry Song adc_reg1 |= AD193X_ADC_SERFMT_TDM; 180a1533d94SBarry Song break; 181a1533d94SBarry Song case SND_SOC_DAIFMT_DSP_A: 182d6bdc0f7SBarry Song adc_reg1 &= ~AD193X_ADC_SERFMT_MASK; 183d6bdc0f7SBarry Song adc_reg1 |= AD193X_ADC_SERFMT_AUX; 184a1533d94SBarry Song break; 185a1533d94SBarry Song default: 186a1533d94SBarry Song return -EINVAL; 187a1533d94SBarry Song } 188a1533d94SBarry Song 189a1533d94SBarry Song switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 190a1533d94SBarry Song case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */ 191d6bdc0f7SBarry Song adc_reg2 &= ~AD193X_ADC_LEFT_HIGH; 192d6bdc0f7SBarry Song adc_reg2 &= ~AD193X_ADC_BCLK_INV; 193a1533d94SBarry Song dac_reg &= ~AD193X_DAC_LEFT_HIGH; 194a1533d94SBarry Song dac_reg &= ~AD193X_DAC_BCLK_INV; 195a1533d94SBarry Song break; 196a1533d94SBarry Song case SND_SOC_DAIFMT_NB_IF: /* normal bclk + invert frm */ 197d6bdc0f7SBarry Song adc_reg2 |= AD193X_ADC_LEFT_HIGH; 198d6bdc0f7SBarry Song adc_reg2 &= ~AD193X_ADC_BCLK_INV; 199a1533d94SBarry Song dac_reg |= AD193X_DAC_LEFT_HIGH; 200a1533d94SBarry Song dac_reg &= ~AD193X_DAC_BCLK_INV; 201a1533d94SBarry Song break; 202a1533d94SBarry Song case SND_SOC_DAIFMT_IB_NF: /* invert bclk + normal frm */ 203d6bdc0f7SBarry Song adc_reg2 &= ~AD193X_ADC_LEFT_HIGH; 204d6bdc0f7SBarry Song adc_reg2 |= AD193X_ADC_BCLK_INV; 205a1533d94SBarry Song dac_reg &= ~AD193X_DAC_LEFT_HIGH; 206a1533d94SBarry Song dac_reg |= AD193X_DAC_BCLK_INV; 207a1533d94SBarry Song break; 208a1533d94SBarry Song 209a1533d94SBarry Song case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */ 210d6bdc0f7SBarry Song adc_reg2 |= AD193X_ADC_LEFT_HIGH; 211d6bdc0f7SBarry Song adc_reg2 |= AD193X_ADC_BCLK_INV; 212a1533d94SBarry Song dac_reg |= AD193X_DAC_LEFT_HIGH; 213a1533d94SBarry Song dac_reg |= AD193X_DAC_BCLK_INV; 214a1533d94SBarry Song break; 215a1533d94SBarry Song default: 216a1533d94SBarry Song return -EINVAL; 217a1533d94SBarry Song } 218a1533d94SBarry Song 219a1533d94SBarry Song switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 220a1533d94SBarry Song case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */ 221d6bdc0f7SBarry Song adc_reg2 |= AD193X_ADC_LCR_MASTER; 222d6bdc0f7SBarry Song adc_reg2 |= AD193X_ADC_BCLK_MASTER; 223a1533d94SBarry Song dac_reg |= AD193X_DAC_LCR_MASTER; 224a1533d94SBarry Song dac_reg |= AD193X_DAC_BCLK_MASTER; 225a1533d94SBarry Song break; 226a1533d94SBarry Song case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & frm master */ 227d6bdc0f7SBarry Song adc_reg2 |= AD193X_ADC_LCR_MASTER; 228d6bdc0f7SBarry Song adc_reg2 &= ~AD193X_ADC_BCLK_MASTER; 229a1533d94SBarry Song dac_reg |= AD193X_DAC_LCR_MASTER; 230a1533d94SBarry Song dac_reg &= ~AD193X_DAC_BCLK_MASTER; 231a1533d94SBarry Song break; 232a1533d94SBarry Song case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */ 233d6bdc0f7SBarry Song adc_reg2 &= ~AD193X_ADC_LCR_MASTER; 234d6bdc0f7SBarry Song adc_reg2 |= AD193X_ADC_BCLK_MASTER; 235a1533d94SBarry Song dac_reg &= ~AD193X_DAC_LCR_MASTER; 236a1533d94SBarry Song dac_reg |= AD193X_DAC_BCLK_MASTER; 237a1533d94SBarry Song break; 238a1533d94SBarry Song case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */ 239d6bdc0f7SBarry Song adc_reg2 &= ~AD193X_ADC_LCR_MASTER; 240d6bdc0f7SBarry Song adc_reg2 &= ~AD193X_ADC_BCLK_MASTER; 241a1533d94SBarry Song dac_reg &= ~AD193X_DAC_LCR_MASTER; 242a1533d94SBarry Song dac_reg &= ~AD193X_DAC_BCLK_MASTER; 243a1533d94SBarry Song break; 244a1533d94SBarry Song default: 245a1533d94SBarry Song return -EINVAL; 246a1533d94SBarry Song } 247a1533d94SBarry Song 248d6bdc0f7SBarry Song snd_soc_write(codec, AD193X_ADC_CTRL1, adc_reg1); 249d6bdc0f7SBarry Song snd_soc_write(codec, AD193X_ADC_CTRL2, adc_reg2); 250a1533d94SBarry Song snd_soc_write(codec, AD193X_DAC_CTRL1, dac_reg); 251a1533d94SBarry Song 252a1533d94SBarry Song return 0; 253a1533d94SBarry Song } 254a1533d94SBarry Song 255*fab90aa4SBarry Song static int ad193x_set_dai_sysclk(struct snd_soc_dai *codec_dai, 256*fab90aa4SBarry Song int clk_id, unsigned int freq, int dir) 257*fab90aa4SBarry Song { 258*fab90aa4SBarry Song struct snd_soc_codec *codec = codec_dai->codec; 259*fab90aa4SBarry Song struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); 260*fab90aa4SBarry Song switch (freq) { 261*fab90aa4SBarry Song case 12288000: 262*fab90aa4SBarry Song case 18432000: 263*fab90aa4SBarry Song case 24576000: 264*fab90aa4SBarry Song case 36864000: 265*fab90aa4SBarry Song ad193x->sysclk = freq; 266*fab90aa4SBarry Song return 0; 267*fab90aa4SBarry Song } 268*fab90aa4SBarry Song return -EINVAL; 269*fab90aa4SBarry Song } 270*fab90aa4SBarry Song 271a1533d94SBarry Song static int ad193x_hw_params(struct snd_pcm_substream *substream, 272a1533d94SBarry Song struct snd_pcm_hw_params *params, 273a1533d94SBarry Song struct snd_soc_dai *dai) 274a1533d94SBarry Song { 275*fab90aa4SBarry Song int word_len = 0, reg = 0, master_rate = 0; 276a1533d94SBarry Song 277a1533d94SBarry Song struct snd_soc_pcm_runtime *rtd = substream->private_data; 278a1533d94SBarry Song struct snd_soc_device *socdev = rtd->socdev; 279a1533d94SBarry Song struct snd_soc_codec *codec = socdev->card->codec; 280*fab90aa4SBarry Song struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); 281a1533d94SBarry Song 282a1533d94SBarry Song /* bit size */ 283a1533d94SBarry Song switch (params_format(params)) { 284a1533d94SBarry Song case SNDRV_PCM_FORMAT_S16_LE: 285a1533d94SBarry Song word_len = 3; 286a1533d94SBarry Song break; 287a1533d94SBarry Song case SNDRV_PCM_FORMAT_S20_3LE: 288a1533d94SBarry Song word_len = 1; 289a1533d94SBarry Song break; 290a1533d94SBarry Song case SNDRV_PCM_FORMAT_S24_LE: 291a1533d94SBarry Song case SNDRV_PCM_FORMAT_S32_LE: 292a1533d94SBarry Song word_len = 0; 293a1533d94SBarry Song break; 294a1533d94SBarry Song } 295a1533d94SBarry Song 296*fab90aa4SBarry Song switch (ad193x->sysclk) { 297*fab90aa4SBarry Song case 12288000: 298*fab90aa4SBarry Song master_rate = AD193X_PLL_INPUT_256; 299*fab90aa4SBarry Song break; 300*fab90aa4SBarry Song case 18432000: 301*fab90aa4SBarry Song master_rate = AD193X_PLL_INPUT_384; 302*fab90aa4SBarry Song break; 303*fab90aa4SBarry Song case 24576000: 304*fab90aa4SBarry Song master_rate = AD193X_PLL_INPUT_512; 305*fab90aa4SBarry Song break; 306*fab90aa4SBarry Song case 36864000: 307*fab90aa4SBarry Song master_rate = AD193X_PLL_INPUT_768; 308*fab90aa4SBarry Song break; 309*fab90aa4SBarry Song } 310*fab90aa4SBarry Song 311*fab90aa4SBarry Song reg = snd_soc_read(codec, AD193X_PLL_CLK_CTRL0); 312*fab90aa4SBarry Song reg = (reg & AD193X_PLL_INPUT_MASK) | master_rate; 313*fab90aa4SBarry Song snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, reg); 314*fab90aa4SBarry Song 315a1533d94SBarry Song reg = snd_soc_read(codec, AD193X_DAC_CTRL2); 316a1533d94SBarry Song reg = (reg & (~AD193X_DAC_WORD_LEN_MASK)) | word_len; 317a1533d94SBarry Song snd_soc_write(codec, AD193X_DAC_CTRL2, reg); 318a1533d94SBarry Song 319a1533d94SBarry Song reg = snd_soc_read(codec, AD193X_ADC_CTRL1); 320a1533d94SBarry Song reg = (reg & (~AD193X_ADC_WORD_LEN_MASK)) | word_len; 321a1533d94SBarry Song snd_soc_write(codec, AD193X_ADC_CTRL1, reg); 322a1533d94SBarry Song 323a1533d94SBarry Song return 0; 324a1533d94SBarry Song } 325a1533d94SBarry Song 326cffce322SMark Brown static int ad193x_bus_probe(struct device *dev, void *ctrl_data, int bus_type) 327a1533d94SBarry Song { 328a1533d94SBarry Song struct snd_soc_codec *codec; 329a1533d94SBarry Song struct ad193x_priv *ad193x; 3309dd7b79aSBarry Song int ret; 3319dd7b79aSBarry Song 3329dd7b79aSBarry Song if (ad193x_codec) { 3339dd7b79aSBarry Song dev_err(dev, "Another ad193x is registered\n"); 3349dd7b79aSBarry Song return -EINVAL; 3359dd7b79aSBarry Song } 336a1533d94SBarry Song 337a1533d94SBarry Song ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL); 338a1533d94SBarry Song if (ad193x == NULL) 339a1533d94SBarry Song return -ENOMEM; 340a1533d94SBarry Song 341a1533d94SBarry Song dev_set_drvdata(dev, ad193x); 342a1533d94SBarry Song 3439dd7b79aSBarry Song codec = &ad193x->codec; 344a1533d94SBarry Song mutex_init(&codec->mutex); 3459dd7b79aSBarry Song codec->control_data = ctrl_data; 3469dd7b79aSBarry Song codec->dev = dev; 347b2c812e2SMark Brown snd_soc_codec_set_drvdata(codec, ad193x); 348a1533d94SBarry Song codec->reg_cache = ad193x->reg_cache; 349a1533d94SBarry Song codec->reg_cache_size = AD193X_NUM_REGS; 350a1533d94SBarry Song codec->name = "AD193X"; 351a1533d94SBarry Song codec->owner = THIS_MODULE; 352a1533d94SBarry Song codec->dai = &ad193x_dai; 353a1533d94SBarry Song codec->num_dai = 1; 354a1533d94SBarry Song INIT_LIST_HEAD(&codec->dapm_widgets); 355a1533d94SBarry Song INIT_LIST_HEAD(&codec->dapm_paths); 356a1533d94SBarry Song 357a1533d94SBarry Song ad193x_dai.dev = codec->dev; 358a1533d94SBarry Song ad193x_codec = codec; 359a1533d94SBarry Song 360a1533d94SBarry Song memcpy(codec->reg_cache, ad193x_reg, AD193X_NUM_REGS); 361a1533d94SBarry Song 362a1533d94SBarry Song if (bus_type == SND_SOC_I2C) 363a1533d94SBarry Song ret = snd_soc_codec_set_cache_io(codec, 8, 8, bus_type); 364a1533d94SBarry Song else 365a1533d94SBarry Song ret = snd_soc_codec_set_cache_io(codec, 16, 8, bus_type); 366a1533d94SBarry Song if (ret < 0) { 367a1533d94SBarry Song dev_err(codec->dev, "failed to set cache I/O: %d\n", 368a1533d94SBarry Song ret); 369a1533d94SBarry Song kfree(ad193x); 370a1533d94SBarry Song return ret; 371a1533d94SBarry Song } 372a1533d94SBarry Song 373a1533d94SBarry Song /* default setting for ad193x */ 374a1533d94SBarry Song 375a1533d94SBarry Song /* unmute dac channels */ 376a1533d94SBarry Song snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0); 377a1533d94SBarry Song /* de-emphasis: 48kHz, powedown dac */ 378a1533d94SBarry Song snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A); 379a1533d94SBarry Song /* powerdown dac, dac in tdm mode */ 380a1533d94SBarry Song snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41); 381a1533d94SBarry Song /* high-pass filter enable */ 382a1533d94SBarry Song snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3); 383a1533d94SBarry Song /* sata delay=1, adc aux mode */ 384a1533d94SBarry Song snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43); 385a1533d94SBarry Song /* pll input: mclki/xi */ 386a1533d94SBarry Song snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ 387a1533d94SBarry Song snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04); 388*fab90aa4SBarry Song ad193x->sysclk = 12288000; 389a1533d94SBarry Song 390a1533d94SBarry Song ret = snd_soc_register_codec(codec); 391a1533d94SBarry Song if (ret != 0) { 392a1533d94SBarry Song dev_err(codec->dev, "Failed to register codec: %d\n", ret); 393a1533d94SBarry Song kfree(ad193x); 394a1533d94SBarry Song return ret; 395a1533d94SBarry Song } 396a1533d94SBarry Song 397a1533d94SBarry Song ret = snd_soc_register_dai(&ad193x_dai); 398a1533d94SBarry Song if (ret != 0) { 399a1533d94SBarry Song dev_err(codec->dev, "Failed to register DAI: %d\n", ret); 400a1533d94SBarry Song snd_soc_unregister_codec(codec); 401a1533d94SBarry Song kfree(ad193x); 402a1533d94SBarry Song return ret; 403a1533d94SBarry Song } 404a1533d94SBarry Song 405a1533d94SBarry Song return 0; 406a1533d94SBarry Song } 407a1533d94SBarry Song 4089dd7b79aSBarry Song static int ad193x_bus_remove(struct device *dev) 409a1533d94SBarry Song { 4109dd7b79aSBarry Song struct ad193x_priv *ad193x = dev_get_drvdata(dev); 4119dd7b79aSBarry Song 412a1533d94SBarry Song snd_soc_unregister_dai(&ad193x_dai); 413a1533d94SBarry Song snd_soc_unregister_codec(&ad193x->codec); 414a1533d94SBarry Song kfree(ad193x); 415a1533d94SBarry Song ad193x_codec = NULL; 4169dd7b79aSBarry Song 4179dd7b79aSBarry Song return 0; 418a1533d94SBarry Song } 419a1533d94SBarry Song 4209dd7b79aSBarry Song static struct snd_soc_dai_ops ad193x_dai_ops = { 4219dd7b79aSBarry Song .hw_params = ad193x_hw_params, 4229dd7b79aSBarry Song .digital_mute = ad193x_mute, 4239dd7b79aSBarry Song .set_tdm_slot = ad193x_set_tdm_slot, 424*fab90aa4SBarry Song .set_sysclk = ad193x_set_dai_sysclk, 4259dd7b79aSBarry Song .set_fmt = ad193x_set_dai_fmt, 4269dd7b79aSBarry Song }; 4279dd7b79aSBarry Song 4289dd7b79aSBarry Song /* codec DAI instance */ 4299dd7b79aSBarry Song struct snd_soc_dai ad193x_dai = { 4309dd7b79aSBarry Song .name = "AD193X", 4319dd7b79aSBarry Song .playback = { 4329dd7b79aSBarry Song .stream_name = "Playback", 4339dd7b79aSBarry Song .channels_min = 2, 4349dd7b79aSBarry Song .channels_max = 8, 4359dd7b79aSBarry Song .rates = SNDRV_PCM_RATE_48000, 4369dd7b79aSBarry Song .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | 4379dd7b79aSBarry Song SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, 4389dd7b79aSBarry Song }, 4399dd7b79aSBarry Song .capture = { 4409dd7b79aSBarry Song .stream_name = "Capture", 4419dd7b79aSBarry Song .channels_min = 2, 4429dd7b79aSBarry Song .channels_max = 4, 4439dd7b79aSBarry Song .rates = SNDRV_PCM_RATE_48000, 4449dd7b79aSBarry Song .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | 4459dd7b79aSBarry Song SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, 4469dd7b79aSBarry Song }, 4479dd7b79aSBarry Song .ops = &ad193x_dai_ops, 4489dd7b79aSBarry Song }; 4499dd7b79aSBarry Song EXPORT_SYMBOL_GPL(ad193x_dai); 4509dd7b79aSBarry Song 451a1533d94SBarry Song static int ad193x_probe(struct platform_device *pdev) 452a1533d94SBarry Song { 453a1533d94SBarry Song struct snd_soc_device *socdev = platform_get_drvdata(pdev); 454a1533d94SBarry Song struct snd_soc_codec *codec; 455a1533d94SBarry Song int ret = 0; 456a1533d94SBarry Song 457a1533d94SBarry Song if (ad193x_codec == NULL) { 458a1533d94SBarry Song dev_err(&pdev->dev, "Codec device not registered\n"); 459a1533d94SBarry Song return -ENODEV; 460a1533d94SBarry Song } 461a1533d94SBarry Song 462a1533d94SBarry Song socdev->card->codec = ad193x_codec; 463a1533d94SBarry Song codec = ad193x_codec; 464a1533d94SBarry Song 465a1533d94SBarry Song /* register pcms */ 466a1533d94SBarry Song ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 467a1533d94SBarry Song if (ret < 0) { 468a1533d94SBarry Song dev_err(codec->dev, "failed to create pcms: %d\n", ret); 469a1533d94SBarry Song goto pcm_err; 470a1533d94SBarry Song } 471a1533d94SBarry Song 472a1533d94SBarry Song snd_soc_add_controls(codec, ad193x_snd_controls, 473a1533d94SBarry Song ARRAY_SIZE(ad193x_snd_controls)); 474a1533d94SBarry Song snd_soc_dapm_new_controls(codec, ad193x_dapm_widgets, 475a1533d94SBarry Song ARRAY_SIZE(ad193x_dapm_widgets)); 476a1533d94SBarry Song snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); 477a1533d94SBarry Song 478a1533d94SBarry Song pcm_err: 479a1533d94SBarry Song return ret; 480a1533d94SBarry Song } 481a1533d94SBarry Song 482a1533d94SBarry Song /* power down chip */ 483a1533d94SBarry Song static int ad193x_remove(struct platform_device *pdev) 484a1533d94SBarry Song { 485a1533d94SBarry Song struct snd_soc_device *socdev = platform_get_drvdata(pdev); 486a1533d94SBarry Song 487a1533d94SBarry Song snd_soc_free_pcms(socdev); 488a1533d94SBarry Song snd_soc_dapm_free(socdev); 489a1533d94SBarry Song 490a1533d94SBarry Song return 0; 491a1533d94SBarry Song } 492a1533d94SBarry Song 493a1533d94SBarry Song struct snd_soc_codec_device soc_codec_dev_ad193x = { 494a1533d94SBarry Song .probe = ad193x_probe, 495a1533d94SBarry Song .remove = ad193x_remove, 496a1533d94SBarry Song }; 497a1533d94SBarry Song EXPORT_SYMBOL_GPL(soc_codec_dev_ad193x); 498a1533d94SBarry Song 499a1533d94SBarry Song #if defined(CONFIG_SPI_MASTER) 500a1533d94SBarry Song static int __devinit ad193x_spi_probe(struct spi_device *spi) 501a1533d94SBarry Song { 502a1533d94SBarry Song return ad193x_bus_probe(&spi->dev, spi, SND_SOC_SPI); 503a1533d94SBarry Song } 504a1533d94SBarry Song 505a1533d94SBarry Song static int __devexit ad193x_spi_remove(struct spi_device *spi) 506a1533d94SBarry Song { 507a1533d94SBarry Song return ad193x_bus_remove(&spi->dev); 508a1533d94SBarry Song } 509a1533d94SBarry Song 510a1533d94SBarry Song static struct spi_driver ad193x_spi_driver = { 511a1533d94SBarry Song .driver = { 512a1533d94SBarry Song .name = "ad193x", 513a1533d94SBarry Song .owner = THIS_MODULE, 514a1533d94SBarry Song }, 515a1533d94SBarry Song .probe = ad193x_spi_probe, 516a1533d94SBarry Song .remove = __devexit_p(ad193x_spi_remove), 517a1533d94SBarry Song }; 518a1533d94SBarry Song #endif 519a1533d94SBarry Song 520a1533d94SBarry Song #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 521a1533d94SBarry Song static const struct i2c_device_id ad193x_id[] = { 522a1533d94SBarry Song { "ad1936", 0 }, 523a1533d94SBarry Song { "ad1937", 0 }, 524a1533d94SBarry Song { } 525a1533d94SBarry Song }; 526a1533d94SBarry Song MODULE_DEVICE_TABLE(i2c, ad193x_id); 527a1533d94SBarry Song 528a1533d94SBarry Song static int __devinit ad193x_i2c_probe(struct i2c_client *client, 529a1533d94SBarry Song const struct i2c_device_id *id) 530a1533d94SBarry Song { 531a1533d94SBarry Song return ad193x_bus_probe(&client->dev, client, SND_SOC_I2C); 532a1533d94SBarry Song } 533a1533d94SBarry Song 534a1533d94SBarry Song static int __devexit ad193x_i2c_remove(struct i2c_client *client) 535a1533d94SBarry Song { 536a1533d94SBarry Song return ad193x_bus_remove(&client->dev); 537a1533d94SBarry Song } 538a1533d94SBarry Song 539a1533d94SBarry Song static struct i2c_driver ad193x_i2c_driver = { 540a1533d94SBarry Song .driver = { 541a1533d94SBarry Song .name = "ad193x", 542a1533d94SBarry Song }, 543a1533d94SBarry Song .probe = ad193x_i2c_probe, 544a1533d94SBarry Song .remove = __devexit_p(ad193x_i2c_remove), 545a1533d94SBarry Song .id_table = ad193x_id, 546a1533d94SBarry Song }; 547a1533d94SBarry Song #endif 548a1533d94SBarry Song 549a1533d94SBarry Song static int __init ad193x_modinit(void) 550a1533d94SBarry Song { 551a1533d94SBarry Song int ret; 552a1533d94SBarry Song 553a1533d94SBarry Song #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 554a1533d94SBarry Song ret = i2c_add_driver(&ad193x_i2c_driver); 555a1533d94SBarry Song if (ret != 0) { 556a1533d94SBarry Song printk(KERN_ERR "Failed to register AD193X I2C driver: %d\n", 557a1533d94SBarry Song ret); 558a1533d94SBarry Song } 559a1533d94SBarry Song #endif 560a1533d94SBarry Song 561a1533d94SBarry Song #if defined(CONFIG_SPI_MASTER) 562a1533d94SBarry Song ret = spi_register_driver(&ad193x_spi_driver); 563a1533d94SBarry Song if (ret != 0) { 564a1533d94SBarry Song printk(KERN_ERR "Failed to register AD193X SPI driver: %d\n", 565a1533d94SBarry Song ret); 566a1533d94SBarry Song } 567a1533d94SBarry Song #endif 568a1533d94SBarry Song return ret; 569a1533d94SBarry Song } 570a1533d94SBarry Song module_init(ad193x_modinit); 571a1533d94SBarry Song 572a1533d94SBarry Song static void __exit ad193x_modexit(void) 573a1533d94SBarry Song { 574a1533d94SBarry Song #if defined(CONFIG_SPI_MASTER) 575a1533d94SBarry Song spi_unregister_driver(&ad193x_spi_driver); 576a1533d94SBarry Song #endif 577a1533d94SBarry Song 578a1533d94SBarry Song #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 579a1533d94SBarry Song i2c_del_driver(&ad193x_i2c_driver); 580a1533d94SBarry Song #endif 581a1533d94SBarry Song } 582a1533d94SBarry Song module_exit(ad193x_modexit); 583a1533d94SBarry Song 584a1533d94SBarry Song MODULE_DESCRIPTION("ASoC ad193x driver"); 585a1533d94SBarry Song MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); 586a1533d94SBarry Song MODULE_LICENSE("GPL"); 587