示例#1
0
static int ak5702_set_bias_level(struct snd_soc_codec *codec,
				 enum snd_soc_bias_level level)
{
	u8 reg = 0;

	switch (level) {
	case SND_SOC_BIAS_ON:
	case SND_SOC_BIAS_PREPARE:
		reg = ak5702_read_reg_cache(codec, AK5702_PM1);
		ak5702_write(codec, AK5702_PM1, reg | AK5702_PM1_PMVCM);
		reg = ak5702_read_reg_cache(codec, AK5702_PLL1);
		reg = reg | AK5702_PLL1_POWERUP | AK5702_PLL1_MASTER;
		ak5702_write(codec, AK5702_PLL1, reg);
		break;
	case SND_SOC_BIAS_STANDBY:
		reg = ak5702_read_reg_cache(codec, AK5702_PM1);
		ak5702_write(codec, AK5702_PM1, reg | AK5702_PM1_PMVCM);
		reg = ak5702_read_reg_cache(codec, AK5702_PLL1);
		ak5702_write(codec, AK5702_PLL1, reg & (~AK5702_PLL1_POWERUP));
		break;
	case SND_SOC_BIAS_OFF:
		reg = ak5702_read_reg_cache(codec, AK5702_PM1);
		ak5702_write(codec, AK5702_PM1, reg & (~AK5702_PM1_PMVCM));
		break;
	}

	codec->bias_level = level;
	return 0;
}
示例#2
0
static int ak5702_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
				 int div_id, int div)
{
	struct snd_soc_codec *codec = codec_dai->codec;
	u8 reg = 0;

	if (div_id == AK5702_BCLK_CLKDIV) {
		reg = ak5702_read_reg_cache(codec, AK5702_FS1);
		switch (div) {
		case AK5702_BCLK_DIV_32:
			reg &= (~AK5702_FS1_BCKO_MASK);
			reg |= AK5702_FS1_BCKO_32FS;
			ak5702_write(codec, AK5702_FS1, reg);
			break;
		case AK5702_BCLK_DIV_64:
			reg &= (~AK5702_FS1_BCKO_MASK);
			reg |= AK5702_FS1_BCKO_64FS;
			ak5702_write(codec, AK5702_FS1, reg);
			break;
		default:
			return -EINVAL;
		}
	}
	return 0;
}
示例#3
0
static int ak5702_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
{
	struct snd_soc_codec *codec = codec_dai->codec;
	u8 fmt1 = 0;

	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_I2S:
		fmt1 = AK5702_FMT1_I2S;
		break;
	case SND_SOC_DAIFMT_LEFT_J:
		fmt1 = AK5702_FMT1_MSB;
		break;
	default:
		return -EINVAL;
	}

	ak5702_write(codec, AK5702_FMT1, fmt1);
	ak5702_write(codec, AK5702_FMT2, AK5702_FMT2_STEREO);
	return 0;
}
示例#4
0
static int ak5702_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
			      int source, unsigned int freq_in,
			      unsigned int freq_out)
{
	struct snd_soc_codec *codec = codec_dai->codec;
	u8 reg = 0;

	reg = ak5702_read_reg_cache(codec, AK5702_PLL1);
	switch (pll_id) {
	case AK5702_PLL_POWERDOWN:
		reg &= (~AK5702_PLL1_PM_MASK);
		reg |= AK5702_PLL1_POWERDOWN;
		break;
	case AK5702_PLL_MASTER:
		reg &= (~AK5702_PLL1_MODE_MASK);
		reg |= AK5702_PLL1_MASTER;
		reg |= AK5702_PLL1_POWERUP;
		break;
	case AK5702_PLL_SLAVE:
		reg &= (~AK5702_PLL1_MODE_MASK);
		reg |= AK5702_PLL1_SLAVE;
		reg |= AK5702_PLL1_POWERUP;
		break;
	default:
		return -ENODEV;
	}

	switch (freq_in) {
	case 11289600:
		reg &= (~AK5702_PLL1_PLL_MASK);
		reg |= AK5702_PLL1_11289600;
		break;
	case 12000000:
		reg &= (~AK5702_PLL1_PLL_MASK);
		reg |= AK5702_PLL1_12000000;
		break;
	case 12288000:
		reg &= (~AK5702_PLL1_PLL_MASK);
		reg |= AK5702_PLL1_12288000;
		break;
	case 19200000:
		reg &= (~AK5702_PLL1_PLL_MASK);
		reg |= AK5702_PLL1_19200000;
		break;
	default:
		return -ENODEV;
	}

	ak5702_write(codec, AK5702_PLL1, reg);
	return 0;
}
示例#5
0
static int ak5702_resume(struct platform_device *pdev)
{
	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
	struct snd_soc_codec *codec = socdev->card->codec;
	int i;

	/* Bring the codec back up to standby first to minimise pop/clicks */
	ak5702_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
	ak5702_set_bias_level(codec, codec->suspend_bias_level);

	/* Sync back everything else */
	for (i = 0; i < ARRAY_SIZE(ak5702_reg); i++)
		ak5702_write(codec, i, ak5702_reg[i]);

	return 0;
}
示例#6
0
static int ak5702_set_dai_sysclk(struct snd_soc_dai *codec_dai,
				 int clk_id, unsigned int freq, int dir)
{
	struct snd_soc_codec *codec = codec_dai->codec;
	u8 fs = 0;
	u8 value;

	switch (freq) {
	case 8000:
		fs = 0x0;
		break;
	case 11025:
		fs = 0x05;
		break;
	case 12000:
		fs = 0x01;
		break;
	case 16000:
		fs = 0x02;
		break;
	case 22050:
		fs = 0x07;
		break;
	case 24000:
		fs = 0x03;
		break;
	case 32000:
		fs = 0x0a;
		break;
	case 44100:
		fs = 0x0f;
		break;
	case 48000:
		fs = 0x0b;
		break;
	default:
		return -EINVAL;
	}

	value = ak5702_read_reg_cache(codec, AK5702_FS1);
	value &= (~AK5702_FS1_FS_MASK);
	value |= fs;
	ak5702_write(codec, AK5702_FS1, value);
	return 0;
}
示例#7
0
static int ak5702_probe(struct platform_device *pdev)
{
	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
	struct snd_soc_codec *codec = ak5702_codec;
	int ret = 0;
	u8 reg = 0;

	socdev->card->codec = ak5702_codec;

	/* register pcms */
	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
	if (ret < 0) {
		printk(KERN_ERR "ak5702: failed to create pcms\n");
		goto pcm_err;
	}

	/* power on device */
	reg = ak5702_read_reg_cache(codec, AK5702_PM1);
	reg |= AK5702_PM1_PMVCM;
	ak5702_write(codec, AK5702_PM1, reg);

	/* initialize ADC */
	reg = AK5702_SIG1_L_LIN1 | AK5702_SIG1_R_RIN2;
	ak5702_write(codec, AK5702_SIG1, reg);
	reg = AK5702_SIG2_L_LIN3 | AK5702_SIG2_R_RIN4;
	ak5702_write(codec, AK5702_SIG2, reg);

	reg = ak5702_read_reg_cache(codec, AK5702_PM1);
	reg = reg | AK5702_PM1_PMADAL | AK5702_PM1_PMADAR;
	ak5702_write(codec, AK5702_PM1, reg);
	reg = ak5702_read_reg_cache(codec, AK5702_PM2);
	reg = reg | AK5702_PM2_PMADBL | AK5702_PM2_PMADBR;
	ak5702_write(codec, AK5702_PM2, reg);

	/* initialize volume */
	ak5702_write(codec, AK5702_MICG1, AK5702_MICG1_INIT);
	ak5702_write(codec, AK5702_MICG2, AK5702_MICG2_INIT);
	ak5702_write(codec, AK5702_VOL1, AK5702_VOL1_IVOLAC);
	ak5702_write(codec, AK5702_VOL2, AK5702_VOL2_IVOLBC);
	ak5702_write(codec, AK5702_LVOL1, AK5702_LVOL1_INIT);
	ak5702_write(codec, AK5702_RVOL1, AK5702_RVOL1_INIT);
	ak5702_write(codec, AK5702_LVOL2, AK5702_LVOL2_INIT);
	ak5702_write(codec, AK5702_RVOL2, AK5702_RVOL2_INIT);

	snd_soc_add_controls(codec, ak5702_snd_controls,
			     ARRAY_SIZE(ak5702_snd_controls));
	ak5702_add_widgets(codec);

	ret = snd_soc_init_card(socdev);
	if (ret < 0) {
		printk(KERN_ERR "ak5702: failed to register card\n");
		goto card_err;
	}

	return ret;
card_err:
	snd_soc_free_pcms(socdev);
	snd_soc_dapm_free(socdev);
pcm_err:
	kfree(codec->reg_cache);
	return ret;
}