Commit 358a8bb5 authored by Lars-Peter Clausen's avatar Lars-Peter Clausen Committed by Mark Brown
Browse files

ASoC: ac97: Push snd_ac97 pointer to the driver level



Now that the ASoC core no longer needs a handle to the AC'97 device that is
associated with a CODEC we can remove it from the snd_soc_codec struct and
push it into the individual driver state structs like we do for other
communication buses. Doing so creates a clean separation between the AC'97
bus support and the ASoC core.

Signed-off-by: default avatarLars-Peter Clausen <lars@metafoo.de>
Acked-by: default avatarCharles Keepax <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent bc263214
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -499,8 +499,8 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg,
				unsigned int mask, unsigned int value);

#ifdef CONFIG_SND_SOC_AC97_BUS
int snd_soc_new_ac97_codec(struct snd_soc_codec *codec);
void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);
struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec);
void snd_soc_free_ac97_codec(struct snd_ac97 *ac97);

int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops);
int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops,
@@ -797,7 +797,6 @@ struct snd_soc_codec {
	struct list_head card_list;

	/* runtime */
	struct snd_ac97 *ac97;  /* for ad-hoc ac97 devices */
	unsigned int cache_bypass:1; /* Suppress access to the cache */
	unsigned int suspended:1; /* Codec is in suspend PM state */
	unsigned int cache_init:1; /* codec cache has been initialized */
+13 −4
Original line number Diff line number Diff line
@@ -37,10 +37,11 @@ static int ac97_prepare(struct snd_pcm_substream *substream,
			struct snd_soc_dai *dai)
{
	struct snd_soc_codec *codec = dai->codec;
	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);

	int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
		  AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
	return snd_ac97_set_rate(codec->ac97, reg, substream->runtime->rate);
	return snd_ac97_set_rate(ac97, reg, substream->runtime->rate);
}

#define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
@@ -70,6 +71,7 @@ static struct snd_soc_dai_driver ac97_dai = {

static int ac97_soc_probe(struct snd_soc_codec *codec)
{
	struct snd_ac97 *ac97;
	struct snd_ac97_bus *ac97_bus;
	struct snd_ac97_template ac97_template;
	int ret;
@@ -81,24 +83,31 @@ static int ac97_soc_probe(struct snd_soc_codec *codec)
		return ret;

	memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
	ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97);
	ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97);
	if (ret < 0)
		return ret;

	snd_soc_codec_set_drvdata(codec, ac97);

	return 0;
}

#ifdef CONFIG_PM
static int ac97_soc_suspend(struct snd_soc_codec *codec)
{
	snd_ac97_suspend(codec->ac97);
	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);

	snd_ac97_suspend(ac97);

	return 0;
}

static int ac97_soc_resume(struct snd_soc_codec *codec)
{
	snd_ac97_resume(codec->ac97);

	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);

	snd_ac97_resume(ac97);

	return 0;
}
+18 −9
Original line number Diff line number Diff line
@@ -135,6 +135,7 @@ static const struct snd_soc_dapm_route ad1980_dapm_routes[] = {
static unsigned int ac97_read(struct snd_soc_codec *codec,
	unsigned int reg)
{
	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
	u16 *cache = codec->reg_cache;

	switch (reg) {
@@ -144,7 +145,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec,
	case AC97_EXTENDED_STATUS:
	case AC97_VENDOR_ID1:
	case AC97_VENDOR_ID2:
		return soc_ac97_ops->read(codec->ac97, reg);
		return soc_ac97_ops->read(ac97, reg);
	default:
		reg = reg >> 1;

@@ -158,9 +159,10 @@ static unsigned int ac97_read(struct snd_soc_codec *codec,
static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
	unsigned int val)
{
	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
	u16 *cache = codec->reg_cache;

	soc_ac97_ops->write(codec->ac97, reg, val);
	soc_ac97_ops->write(ac97, reg, val);
	reg = reg >> 1;
	if (reg < ARRAY_SIZE(ad1980_reg))
		cache[reg] = val;
@@ -186,16 +188,17 @@ static struct snd_soc_dai_driver ad1980_dai = {

static int ad1980_reset(struct snd_soc_codec *codec, int try_warm)
{
	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
	unsigned int retry_cnt = 0;

	do {
		if (try_warm && soc_ac97_ops->warm_reset) {
			soc_ac97_ops->warm_reset(codec->ac97);
			soc_ac97_ops->warm_reset(ac97);
			if (ac97_read(codec, AC97_RESET) == 0x0090)
				return 1;
		}

		soc_ac97_ops->reset(codec->ac97);
		soc_ac97_ops->reset(ac97);
		/*
		 * Set bit 16slot in register 74h, then every slot will has only
		 * 16 bits. This command is sent out in 20bit mode, in which
@@ -215,16 +218,20 @@ static int ad1980_reset(struct snd_soc_codec *codec, int try_warm)

static int ad1980_soc_probe(struct snd_soc_codec *codec)
{
	struct snd_ac97 *ac97;
	int ret;
	u16 vendor_id2;
	u16 ext_status;

	ret = snd_soc_new_ac97_codec(codec);
	if (ret < 0) {
		dev_err(codec->dev, "Failed to register AC97 codec\n");
	ac97 = snd_soc_new_ac97_codec(codec);
	if (IS_ERR(ac97)) {
		ret = PTR_ERR(ac97);
		dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret);
		return ret;
	}

	snd_soc_codec_set_drvdata(codec, ac97);

	ret = ad1980_reset(codec, 0);
	if (ret < 0)
		goto reset_err;
@@ -261,13 +268,15 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec)
	return 0;

reset_err:
	snd_soc_free_ac97_codec(codec);
	snd_soc_free_ac97_codec(ac97);
	return ret;
}

static int ad1980_soc_remove(struct snd_soc_codec *codec)
{
	snd_soc_free_ac97_codec(codec);
	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);

	snd_soc_free_ac97_codec(ac97);
	return 0;
}

+24 −14
Original line number Diff line number Diff line
@@ -139,18 +139,19 @@ static const struct snd_kcontrol_new stac9766_snd_ac97_controls[] = {
static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg,
			       unsigned int val)
{
	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
	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);
		soc_ac97_ops->write(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);
	soc_ac97_ops->write(ac97, reg, val);
	cache[reg / 2] = val;
	return 0;
}
@@ -158,11 +159,12 @@ static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg,
static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec,
				       unsigned int reg)
{
	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
	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);
		val = soc_ac97_ops->read(ac97, reg - AC97_STAC_PAGE0);
		stac9766_ac97_write(codec, AC97_INT_PAGING, 1);
		return val;
	}
@@ -173,7 +175,7 @@ static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec,
		reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 ||
		reg == AC97_VENDOR_ID2) {

		val = soc_ac97_ops->read(codec->ac97, reg);
		val = soc_ac97_ops->read(ac97, reg);
		return val;
	}
	return cache[reg / 2];
@@ -240,15 +242,17 @@ static int stac9766_set_bias_level(struct snd_soc_codec *codec,

static int stac9766_reset(struct snd_soc_codec *codec, int try_warm)
{
	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);

	if (try_warm && soc_ac97_ops->warm_reset) {
		soc_ac97_ops->warm_reset(codec->ac97);
		soc_ac97_ops->warm_reset(ac97);
		if (stac9766_ac97_read(codec, 0) == stac9766_reg[0])
			return 1;
	}

	soc_ac97_ops->reset(codec->ac97);
	soc_ac97_ops->reset(ac97);
	if (soc_ac97_ops->warm_reset)
		soc_ac97_ops->warm_reset(codec->ac97);
		soc_ac97_ops->warm_reset(ac97);
	if (stac9766_ac97_read(codec, 0) != stac9766_reg[0])
		return -EIO;
	return 0;
@@ -262,6 +266,7 @@ static int stac9766_codec_suspend(struct snd_soc_codec *codec)

static int stac9766_codec_resume(struct snd_soc_codec *codec)
{
	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
	u16 id, reset;

	reset = 0;
@@ -271,8 +276,8 @@ reset:
		printk(KERN_ERR "stac9766 failed to resume");
		return -EIO;
	}
	codec->ac97->bus->ops->warm_reset(codec->ac97);
	id = soc_ac97_ops->read(codec->ac97, AC97_VENDOR_ID2);
	ac97->bus->ops->warm_reset(ac97);
	id = soc_ac97_ops->read(ac97, AC97_VENDOR_ID2);
	if (id != 0x4c13) {
		stac9766_reset(codec, 0);
		reset++;
@@ -332,11 +337,14 @@ static struct snd_soc_dai_driver stac9766_dai[] = {

static int stac9766_codec_probe(struct snd_soc_codec *codec)
{
	struct snd_ac97 *ac97;
	int ret = 0;

	ret = snd_soc_new_ac97_codec(codec);
	if (ret < 0)
		goto codec_err;
	ac97 = snd_soc_new_ac97_codec(codec);
	if (IS_ERR(ac97))
		return PTR_ERR(ac97);

	snd_soc_codec_set_drvdata(codec, ac97);

	/* do a cold reset for the controller and then try
	 * a warm reset followed by an optional cold reset for codec */
@@ -355,13 +363,15 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec)
	return 0;

codec_err:
	snd_soc_free_ac97_codec(codec);
	snd_soc_free_ac97_codec(ac97);
	return ret;
}

static int stac9766_codec_remove(struct snd_soc_codec *codec)
{
	snd_soc_free_ac97_codec(codec);
	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);

	snd_soc_free_ac97_codec(ac97);
	return 0;
}

+22 −9
Original line number Diff line number Diff line
@@ -203,13 +203,14 @@ static const struct snd_soc_dapm_route wm9705_audio_map[] = {
/* We use a register cache to enhance read performance. */
static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg)
{
	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
	u16 *cache = codec->reg_cache;

	switch (reg) {
	case AC97_RESET:
	case AC97_VENDOR_ID1:
	case AC97_VENDOR_ID2:
		return soc_ac97_ops->read(codec->ac97, reg);
		return soc_ac97_ops->read(ac97, reg);
	default:
		reg = reg >> 1;

@@ -223,9 +224,10 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg)
static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
	unsigned int val)
{
	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
	u16 *cache = codec->reg_cache;

	soc_ac97_ops->write(codec->ac97, reg, val);
	soc_ac97_ops->write(ac97, reg, val);
	reg = reg >> 1;
	if (reg < (ARRAY_SIZE(wm9705_reg)))
		cache[reg] = val;
@@ -293,8 +295,10 @@ static struct snd_soc_dai_driver wm9705_dai[] = {

static int wm9705_reset(struct snd_soc_codec *codec)
{
	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);

	if (soc_ac97_ops->reset) {
		soc_ac97_ops->reset(codec->ac97);
		soc_ac97_ops->reset(ac97);
		if (ac97_read(codec, 0) == wm9705_reg[0])
			return 0; /* Success */
	}
@@ -307,13 +311,16 @@ static int wm9705_reset(struct snd_soc_codec *codec)
#ifdef CONFIG_PM
static int wm9705_soc_suspend(struct snd_soc_codec *codec)
{
	soc_ac97_ops->write(codec->ac97, AC97_POWERDOWN, 0xffff);
	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);

	soc_ac97_ops->write(ac97, AC97_POWERDOWN, 0xffff);

	return 0;
}

static int wm9705_soc_resume(struct snd_soc_codec *codec)
{
	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
	int i, ret;
	u16 *cache = codec->reg_cache;

@@ -322,7 +329,7 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec)
		return ret;

	for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) {
		soc_ac97_ops->write(codec->ac97, i, cache[i>>1]);
		soc_ac97_ops->write(ac97, i, cache[i>>1]);
	}

	return 0;
@@ -334,14 +341,18 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec)

static int wm9705_soc_probe(struct snd_soc_codec *codec)
{
	struct snd_ac97 *ac97;
	int ret = 0;

	ret = snd_soc_new_ac97_codec(codec);
	if (ret < 0) {
	ac97 = snd_soc_new_ac97_codec(codec);
	if (IS_ERR(ac97)) {
		ret = PTR_ERR(ac97);
		dev_err(codec->dev, "Failed to register AC97 codec\n");
		return ret;
	}

	snd_soc_codec_set_drvdata(codec, ac97);

	ret = wm9705_reset(codec);
	if (ret)
		goto reset_err;
@@ -349,13 +360,15 @@ static int wm9705_soc_probe(struct snd_soc_codec *codec)
	return 0;

reset_err:
	snd_soc_free_ac97_codec(codec);
	snd_soc_free_ac97_codec(ac97);
	return ret;
}

static int wm9705_soc_remove(struct snd_soc_codec *codec)
{
	snd_soc_free_ac97_codec(codec);
	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);

	snd_soc_free_ac97_codec(ac97);
	return 0;
}

Loading