static int stac9766_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { switch (level) { case SND_SOC_BIAS_ON: case SND_SOC_BIAS_PREPARE: case SND_SOC_BIAS_STANDBY: stac9766_ac97_write(codec, AC97_POWERDOWN, 0x0000); break; case SND_SOC_BIAS_OFF: stac9766_ac97_write(codec, AC97_POWERDOWN, 0xffff); break; } codec->dapm.bias_level = level; return 0; }
static int stac9766_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { switch (level) { case SND_SOC_BIAS_ON: /* full On */ case SND_SOC_BIAS_PREPARE: /* partial On */ case SND_SOC_BIAS_STANDBY: /* Off, with power */ stac9766_ac97_write(codec, AC97_POWERDOWN, 0x0000); break; case SND_SOC_BIAS_OFF: /* Off, without power */ /* disable everything including AC link */ stac9766_ac97_write(codec, AC97_POWERDOWN, 0xffff); break; } codec->dapm.bias_level = level; return 0; }
static int ac97_digital_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct snd_pcm_runtime *runtime = substream->runtime; unsigned short reg, vra; stac9766_ac97_write(codec, AC97_SPDIF, 0x2002); vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS); vra |= 0x5; /* Enable VRA and SPDIF out */ stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra); reg = AC97_PCM_FRONT_DAC_RATE; return stac9766_ac97_write(codec, reg, runtime->rate); }
static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int val) { u16 *cache = codec->reg_cache; if (reg > AC97_STAC_PAGE0) { stac9766_ac97_write(codec, AC97_INT_PAGING, 0); soc_ac97_ops.write(codec->ac97, reg, val); stac9766_ac97_write(codec, AC97_INT_PAGING, 1); return 0; } if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) return -EIO; soc_ac97_ops.write(codec->ac97, reg, val); cache[reg / 2] = val; return 0; }
static int ac97_analog_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct snd_pcm_runtime *runtime = substream->runtime; unsigned short reg, vra; vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS); vra |= 0x1; /* enable variable rate audio */ stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) reg = AC97_PCM_FRONT_DAC_RATE; else reg = AC97_PCM_LR_ADC_RATE; return stac9766_ac97_write(codec, reg, runtime->rate); }
static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, unsigned int reg) { u16 val = 0, *cache = codec->reg_cache; if (reg > AC97_STAC_PAGE0) { stac9766_ac97_write(codec, AC97_INT_PAGING, 0); val = soc_ac97_ops.read(codec->ac97, reg - AC97_STAC_PAGE0); stac9766_ac97_write(codec, AC97_INT_PAGING, 1); return val; } if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) return -EIO; if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2) { val = soc_ac97_ops.read(codec->ac97, reg); return val; } return cache[reg / 2]; }
static int ac97_digital_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; unsigned short vra; switch (cmd) { case SNDRV_PCM_TRIGGER_STOP: vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS); vra &= !0x04; stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra); break; } return 0; }