diff options
Diffstat (limited to 'sound/soc/codecs/wm9705.c')
| -rw-r--r-- | sound/soc/codecs/wm9705.c | 171 |
1 files changed, 64 insertions, 107 deletions
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index c2d1a7a18fa..c0b7f45dfa3 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c @@ -10,6 +10,7 @@ */ #include <linux/init.h> +#include <linux/slab.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/device.h> @@ -18,7 +19,6 @@ #include <sound/ac97_codec.h> #include <sound/initval.h> #include <sound/soc.h> -#include <sound/soc-dapm.h> #include "wm9705.h" @@ -67,12 +67,12 @@ static const char *wm9705_mic[] = {"Mic 1", "Mic 2"}; static const char *wm9705_rec_sel[] = {"Mic", "CD", "NC", "NC", "Line", "Stereo Mix", "Mono Mix", "Phone"}; -static const struct soc_enum wm9705_enum_mic = - SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, wm9705_mic); -static const struct soc_enum wm9705_enum_rec_l = - SOC_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9705_rec_sel); -static const struct soc_enum wm9705_enum_rec_r = - SOC_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9705_rec_sel); +static SOC_ENUM_SINGLE_DECL(wm9705_enum_mic, + AC97_GENERAL_PURPOSE, 8, wm9705_mic); +static SOC_ENUM_SINGLE_DECL(wm9705_enum_rec_l, + AC97_REC_SEL, 8, wm9705_rec_sel); +static SOC_ENUM_SINGLE_DECL(wm9705_enum_rec_r, + AC97_REC_SEL, 0, wm9705_rec_sel); /* Headphone Mixer */ static const struct snd_kcontrol_new wm9705_hp_mixer_controls[] = { @@ -142,7 +142,7 @@ static const struct snd_soc_dapm_widget wm9705_dapm_widgets[] = { * constantly enabled, we use the mutes on those inputs to simulate such * controls. */ -static const struct snd_soc_dapm_route audio_map[] = { +static const struct snd_soc_dapm_route wm9705_audio_map[] = { /* HP mixer */ {"HP Mixer", "PCBeep Playback Switch", "PCBEEP PGA"}, {"HP Mixer", "CD Playback Switch", "CD PGA"}, @@ -200,16 +200,6 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Right ADC", NULL, "ADC PGA"}, }; -static int wm9705_add_widgets(struct snd_soc_codec *codec) -{ - snd_soc_dapm_new_controls(codec, wm9705_dapm_widgets, - ARRAY_SIZE(wm9705_dapm_widgets)); - snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); - snd_soc_dapm_new_widgets(codec); - - return 0; -} - /* We use a register cache to enhance read performance. */ static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) { @@ -219,7 +209,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int 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(codec->ac97, reg); default: reg = reg >> 1; @@ -235,7 +225,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, { u16 *cache = codec->reg_cache; - soc_ac97_ops.write(codec->ac97, reg, val); + soc_ac97_ops->write(codec->ac97, reg, val); reg = reg >> 1; if (reg < (ARRAY_SIZE(wm9705_reg))) cache[reg] = val; @@ -246,10 +236,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, static int ac97_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = dai->codec; int reg; u16 vra; @@ -261,7 +248,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream, else reg = AC97_PCM_LR_ADC_RATE; - return ac97_write(codec, reg, runtime->rate); + return ac97_write(codec, reg, substream->runtime->rate); } #define WM9705_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | \ @@ -269,32 +256,32 @@ static int ac97_prepare(struct snd_pcm_substream *substream, SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000) -static struct snd_soc_dai_ops wm9705_dai_ops = { +static const struct snd_soc_dai_ops wm9705_dai_ops = { .prepare = ac97_prepare, }; -struct snd_soc_dai wm9705_dai[] = { +static struct snd_soc_dai_driver wm9705_dai[] = { { - .name = "AC97 HiFi", + .name = "wm9705-hifi", .ac97_control = 1, .playback = { .stream_name = "HiFi Playback", .channels_min = 1, .channels_max = 2, .rates = WM9705_AC97_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .formats = SND_SOC_STD_AC97_FMTS, }, .capture = { .stream_name = "HiFi Capture", .channels_min = 1, .channels_max = 2, .rates = WM9705_AC97_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .formats = SND_SOC_STD_AC97_FMTS, }, .ops = &wm9705_dai_ops, }, { - .name = "AC97 Aux", + .name = "wm9705-aux", .playback = { .stream_name = "Aux Playback", .channels_min = 1, @@ -304,12 +291,11 @@ struct snd_soc_dai wm9705_dai[] = { }, } }; -EXPORT_SYMBOL_GPL(wm9705_dai); static int wm9705_reset(struct snd_soc_codec *codec) { - if (soc_ac97_ops.reset) { - soc_ac97_ops.reset(codec->ac97); + if (soc_ac97_ops->reset) { + soc_ac97_ops->reset(codec->ac97); if (ac97_read(codec, 0) == wm9705_reg[0]) return 0; /* Success */ } @@ -318,20 +304,15 @@ static int wm9705_reset(struct snd_soc_codec *codec) } #ifdef CONFIG_PM -static int wm9705_soc_suspend(struct platform_device *pdev, pm_message_t msg) +static int wm9705_soc_suspend(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff); + soc_ac97_ops->write(codec->ac97, AC97_POWERDOWN, 0xffff); return 0; } -static int wm9705_soc_resume(struct platform_device *pdev) +static int wm9705_soc_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; int i, ret; u16 *cache = codec->reg_cache; @@ -342,7 +323,7 @@ static int wm9705_soc_resume(struct platform_device *pdev) } 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(codec->ac97, i, cache[i>>1]); } return 0; @@ -352,100 +333,76 @@ static int wm9705_soc_resume(struct platform_device *pdev) #define wm9705_soc_resume NULL #endif -static int wm9705_soc_probe(struct platform_device *pdev) +static int wm9705_soc_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; int ret = 0; - printk(KERN_INFO "WM9705 SoC Audio Codec\n"); - - socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), - GFP_KERNEL); - if (socdev->card->codec == NULL) - return -ENOMEM; - codec = socdev->card->codec; - mutex_init(&codec->mutex); - - codec->reg_cache = kmemdup(wm9705_reg, sizeof(wm9705_reg), GFP_KERNEL); - if (codec->reg_cache == NULL) { - ret = -ENOMEM; - goto cache_err; - } - codec->reg_cache_size = sizeof(wm9705_reg); - codec->reg_cache_step = 2; - - codec->name = "WM9705"; - codec->owner = THIS_MODULE; - codec->dai = wm9705_dai; - codec->num_dai = ARRAY_SIZE(wm9705_dai); - codec->write = ac97_write; - codec->read = ac97_read; - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); + ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); if (ret < 0) { printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); - goto codec_err; + return ret; } - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) - goto pcm_err; - ret = wm9705_reset(codec); if (ret) goto reset_err; - snd_soc_add_controls(codec, wm9705_snd_ac97_controls, + snd_soc_add_codec_controls(codec, wm9705_snd_ac97_controls, ARRAY_SIZE(wm9705_snd_ac97_controls)); - wm9705_add_widgets(codec); - - ret = snd_soc_init_card(socdev); - if (ret < 0) { - printk(KERN_ERR "wm9705: failed to register card\n"); - goto pcm_err; - } return 0; reset_err: - snd_soc_free_pcms(socdev); -pcm_err: snd_soc_free_ac97_codec(codec); -codec_err: - kfree(codec->reg_cache); -cache_err: - kfree(socdev->card->codec); - socdev->card->codec = NULL; return ret; } -static int wm9705_soc_remove(struct platform_device *pdev) +static int wm9705_soc_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec == NULL) - return 0; - - snd_soc_dapm_free(socdev); - snd_soc_free_pcms(socdev); snd_soc_free_ac97_codec(codec); - kfree(codec->reg_cache); - kfree(codec); return 0; } -struct snd_soc_codec_device soc_codec_dev_wm9705 = { +static struct snd_soc_codec_driver soc_codec_dev_wm9705 = { .probe = wm9705_soc_probe, .remove = wm9705_soc_remove, .suspend = wm9705_soc_suspend, .resume = wm9705_soc_resume, + .read = ac97_read, + .write = ac97_write, + .reg_cache_size = ARRAY_SIZE(wm9705_reg), + .reg_word_size = sizeof(u16), + .reg_cache_step = 2, + .reg_cache_default = wm9705_reg, + .dapm_widgets = wm9705_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm9705_dapm_widgets), + .dapm_routes = wm9705_audio_map, + .num_dapm_routes = ARRAY_SIZE(wm9705_audio_map), }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm9705); + +static int wm9705_probe(struct platform_device *pdev) +{ + return snd_soc_register_codec(&pdev->dev, + &soc_codec_dev_wm9705, wm9705_dai, ARRAY_SIZE(wm9705_dai)); +} + +static int wm9705_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + +static struct platform_driver wm9705_codec_driver = { + .driver = { + .name = "wm9705-codec", + .owner = THIS_MODULE, + }, + + .probe = wm9705_probe, + .remove = wm9705_remove, +}; + +module_platform_driver(wm9705_codec_driver); MODULE_DESCRIPTION("ASoC WM9705 driver"); MODULE_AUTHOR("Ian Molton"); |
