/* If the i2c layer weren't so broken, we could pass this kind of data around */ static int ak4671_codec_probe(struct i2c_adapter *adap, int addr, int kind) { struct snd_soc_device *socdev = ak4671_socdev; struct ak4671_setup_data *setup = socdev->codec_data; struct snd_soc_codec *codec = socdev->codec; struct i2c_client *i2c; int ret; if (addr != setup->i2c_address) return -ENODEV; ak4671_client.adapter = adap; ak4671_client.addr = addr; i2c = kmemdup(&ak4671_client, sizeof(ak4671_client), GFP_KERNEL); if (i2c == NULL) return -ENOMEM; i2c_set_clientdata(i2c, codec); codec->control_data = i2c; ret = i2c_attach_client(i2c); if (ret < 0) { printk(KERN_ERR "failed to attach codec at addr %x\n", addr); goto err; } ret = ak4671_init(socdev); if (ret < 0) { printk(KERN_ERR "failed to initialise AK4671\n"); goto err; } set_registers(codec, MM_AUDIO_PLAYBACK_SPK); #if 0 // i2c test p("---> 0x01 = 0x%02x\n", ak4671_read(codec, 0x01)); ak4671_write(codec, 0x01, 0x78); P("---> 0x01 = 0x%02x\n", ak4671_read(codec, 0x01)); P("---> 0x02 = 0x%02x\n", ak4671_read(codec, 0x02)); ak4671_write(codec, 0x02, 0x01); P("---> 0x02 = 0x%02x\n", ak4671_read(codec, 0x02)); P("---> 0x03 = 0x%02x\n", ak4671_read(codec, 0x03)); ak4671_write(codec, 0x03, 0x03); P("---> 0x03 = 0x%02x\n", ak4671_read(codec, 0x03)); #endif return ret; err: kfree(i2c); return ret; }
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_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; }
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_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; u8 mode1 = 0; /* interface format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: mode1 = 0x03; break; default: printk("!! invalid interface format !!\n"); return -EINVAL; } ak4671_write(codec, AK4671_FORMAT, mode1); return 0; }
static ssize_t ak4671_control_store( struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { u8 reg, value = 0; int ret = 0; struct snd_soc_device *socdev = dev_get_drvdata(dev); struct snd_soc_codec *codec = socdev->codec; printk("echo [REGISTER NUMBER(HEX)][VALUE(HEX)] > ak4671_control\n"); printk("ex) echo 030f > ak4671_control\n"); P("buf = %s", buf); P("buf size = %d", sizeof(buf)); P("buf size = %d", strlen(buf)); if(sizeof(buf) != 4) { printk("input error\n"); printk("store ex) echo 030f\n"); return -1; } ret = hex2dec(buf[0]); if (ret == -1) { printk("store error.\n"); return -1; } reg = ret << 4; ret = hex2dec(buf[1]); if (ret == -1) { printk("store error.\n"); return -1; } reg |= (ret & 0xf); ret = hex2dec(buf[2]); if (ret == -1) { printk("store error.\n"); return -1; } value = ret << 4; ret = hex2dec(buf[3]); if (ret == -1) { printk("store error.\n"); return -1; } value |= (ret & 0xf); if (reg == 0xf1) { // path control set_registers(codec, value); } else if (reg >= 0xe0 && reg <= 0xe5) amp_set_register(reg - 0xe0, value); else ak4671_write(codec, reg, value); printk("Set : reg = 0x%02x, value = 0x%02x\n", reg, value); printk("Read : reg = 0x%02x, value = 0x%02x\n", reg, ak4671_read(codec, reg)); return size; }