static int ak4671_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct snd_soc_codec *codec = dai->codec; u8 mode; u8 format; /* set master/slave audio interface */ mode = ak4671_read_reg_cache(codec, AK4671_PLL_MODE_SELECT1); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: mode |= AK4671_PMPLL; mode |= AK4671_M_S; break; case SND_SOC_DAIFMT_CBM_CFS: mode |= AK4671_PMPLL; mode &= ~(AK4671_M_S); break; default: return -EINVAL; } /* interface format */ format = ak4671_read_reg_cache(codec, AK4671_FORMAT_SELECT); format &= ~AK4671_DIF; switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: format |= AK4671_DIF_I2S_MODE; break; case SND_SOC_DAIFMT_LEFT_J: format |= AK4671_DIF_MSB_MODE; break; case SND_SOC_DAIFMT_DSP_A: format |= AK4671_DIF_DSP_MODE; format |= AK4671_BCKP; format |= AK4671_MSBS; break; default: return -EINVAL; } /* set mode and format */ ak4671_write(codec, AK4671_PLL_MODE_SELECT1, mode); ak4671_write(codec, AK4671_FORMAT_SELECT, format); return 0; }
static int ak4671_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { #if 0 struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->codec; struct ak4671_priv *ak4671 = codec->private_data; u8 mode2 = ak4671_read_reg_cache(codec, AK4671_MODE2) & ~(0x3 << 5); int rate = params_rate(params), fs = 256; if (rate) fs = ak4671->sysclk / rate; /* set fs */ switch (fs) { case 1024: mode2 |= (0x2 << 5); break; case 512: mode2 |= (0x1 << 5); break; case 256: break; } /* set rate */ ak4671_write(codec, ak4671_mode2, mode2); #endif return 0; }
static int ak4671_mute(struct snd_soc_dai *dai, int mute) { #if 0 P("mute %d", mute); struct snd_soc_codec *codec = dai->codec; u16 mute_reg = ak4671_read_reg_cache(codec, AK4671_MODE_CONTROL2) & 0xfffb; if (!mute) ak4671_write(codec, AK4671_MODE_CONTROL2, mute_reg | 1); else ak4671_write(codec, AK4671_MODE_CONTROL2, mute_reg | 0x4 | 1); #else P("mute is not supported (%d)", mute); #endif return 0; }
static int ak4671_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; u8 fs; fs = ak4671_read_reg_cache(codec, AK4671_PLL_MODE_SELECT0); fs &= ~AK4671_FS; switch (params_rate(params)) { case 8000: fs |= AK4671_FS_8KHZ; break; case 12000: fs |= AK4671_FS_12KHZ; break; case 16000: fs |= AK4671_FS_16KHZ; break; case 24000: fs |= AK4671_FS_24KHZ; break; case 11025: fs |= AK4671_FS_11_025KHZ; break; case 22050: fs |= AK4671_FS_22_05KHZ; break; case 32000: fs |= AK4671_FS_32KHZ; break; case 44100: fs |= AK4671_FS_44_1KHZ; break; case 48000: fs |= AK4671_FS_48KHZ; break; default: return -EINVAL; } ak4671_write(codec, AK4671_PLL_MODE_SELECT0, fs); return 0; }
static int ak4671_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int freq, int dir) { struct snd_soc_codec *codec = dai->codec; u8 pll; pll = ak4671_read_reg_cache(codec, AK4671_PLL_MODE_SELECT0); pll &= ~AK4671_PLL; switch (freq) { case 11289600: pll |= AK4671_PLL_11_2896MHZ; break; case 12000000: pll |= AK4671_PLL_12MHZ; break; case 12288000: pll |= AK4671_PLL_12_288MHZ; break; case 13000000: pll |= AK4671_PLL_13MHZ; break; case 13500000: pll |= AK4671_PLL_13_5MHZ; break; case 19200000: pll |= AK4671_PLL_19_2MHZ; break; case 24000000: pll |= AK4671_PLL_24MHZ; break; case 26000000: pll |= AK4671_PLL_26MHZ; break; case 27000000: pll |= AK4671_PLL_27MHZ; break; default: return -EINVAL; } ak4671_write(codec, AK4671_PLL_MODE_SELECT0, pll); return 0; }
static int ak4671_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { u8 reg; switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: reg = ak4671_read_reg_cache(codec, AK4671_AD_DA_POWER_MANAGEMENT); ak4671_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, reg | AK4671_PMVCM); break; case SND_SOC_BIAS_OFF: ak4671_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, 0x00); break; } codec->bias_level = level; return 0; }