wm8978.c (cf0dbba515415bb19b11f9323d5f7bebd7f24fd6) wm8978.c (b2c812e22de88bb79c290c0e718280f10b64a48d)
1/*
2 * wm8978.c -- WM8978 ALSA SoC Audio Codec driver
3 *
4 * Copyright (C) 2009-2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
5 * Copyright (C) 2007 Carlos Munoz <carlos@kenati.com>
6 * Copyright 2006-2009 Wolfson Microelectronics PLC.
7 * Based on wm8974 and wm8990 by Liam Girdwood <lrg@slimlogic.co.uk>
8 *

--- 5 unchanged lines hidden (view full) ---

14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19#include <linux/pm.h>
20#include <linux/i2c.h>
21#include <linux/platform_device.h>
1/*
2 * wm8978.c -- WM8978 ALSA SoC Audio Codec driver
3 *
4 * Copyright (C) 2009-2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
5 * Copyright (C) 2007 Carlos Munoz <carlos@kenati.com>
6 * Copyright 2006-2009 Wolfson Microelectronics PLC.
7 * Based on wm8974 and wm8990 by Liam Girdwood <lrg@slimlogic.co.uk>
8 *

--- 5 unchanged lines hidden (view full) ---

14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19#include <linux/pm.h>
20#include <linux/i2c.h>
21#include <linux/platform_device.h>
22#include <linux/slab.h>
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28#include <sound/initval.h>
29#include <sound/tlv.h>
30#include <asm/div64.h>

--- 403 unchanged lines hidden (view full) ---

434}
435
436/*
437 * Calculate internal frequencies and dividers, according to Figure 40
438 * "PLL and Clock Select Circuit" in WM8978 datasheet Rev. 2.6
439 */
440static int wm8978_configure_pll(struct snd_soc_codec *codec)
441{
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h>
26#include <sound/soc-dapm.h>
27#include <sound/initval.h>
28#include <sound/tlv.h>
29#include <asm/div64.h>

--- 403 unchanged lines hidden (view full) ---

433}
434
435/*
436 * Calculate internal frequencies and dividers, according to Figure 40
437 * "PLL and Clock Select Circuit" in WM8978 datasheet Rev. 2.6
438 */
439static int wm8978_configure_pll(struct snd_soc_codec *codec)
440{
442 struct wm8978_priv *wm8978 = codec->private_data;
441 struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
443 struct wm8978_pll_div pll_div;
444 unsigned int f_opclk = wm8978->f_opclk, f_mclk = wm8978->f_mclk,
445 f_256fs = wm8978->f_256fs;
446 unsigned int f2;
447
448 if (!f_mclk)
449 return -EINVAL;
450

--- 79 unchanged lines hidden (view full) ---

530
531/*
532 * Configure WM8978 clock dividers.
533 */
534static int wm8978_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
535 int div_id, int div)
536{
537 struct snd_soc_codec *codec = codec_dai->codec;
442 struct wm8978_pll_div pll_div;
443 unsigned int f_opclk = wm8978->f_opclk, f_mclk = wm8978->f_mclk,
444 f_256fs = wm8978->f_256fs;
445 unsigned int f2;
446
447 if (!f_mclk)
448 return -EINVAL;
449

--- 79 unchanged lines hidden (view full) ---

529
530/*
531 * Configure WM8978 clock dividers.
532 */
533static int wm8978_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
534 int div_id, int div)
535{
536 struct snd_soc_codec *codec = codec_dai->codec;
538 struct wm8978_priv *wm8978 = codec->private_data;
537 struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
539 int ret = 0;
540
541 switch (div_id) {
542 case WM8978_OPCLKRATE:
543 wm8978->f_opclk = div;
544
545 if (wm8978->f_mclk)
546 /*

--- 28 unchanged lines hidden (view full) ---

575
576/*
577 * @freq: when .set_pll() us not used, freq is codec MCLK input frequency
578 */
579static int wm8978_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id,
580 unsigned int freq, int dir)
581{
582 struct snd_soc_codec *codec = codec_dai->codec;
538 int ret = 0;
539
540 switch (div_id) {
541 case WM8978_OPCLKRATE:
542 wm8978->f_opclk = div;
543
544 if (wm8978->f_mclk)
545 /*

--- 28 unchanged lines hidden (view full) ---

574
575/*
576 * @freq: when .set_pll() us not used, freq is codec MCLK input frequency
577 */
578static int wm8978_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id,
579 unsigned int freq, int dir)
580{
581 struct snd_soc_codec *codec = codec_dai->codec;
583 struct wm8978_priv *wm8978 = codec->private_data;
582 struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
584 int ret = 0;
585
586 dev_dbg(codec->dev, "%s: ID %d, freq %u\n", __func__, clk_id, freq);
587
588 if (freq) {
589 wm8978->f_mclk = freq;
590
591 /* Even if MCLK is used for system clock, might have to drive OPCLK */

--- 95 unchanged lines hidden (view full) ---

687 */
688static int wm8978_hw_params(struct snd_pcm_substream *substream,
689 struct snd_pcm_hw_params *params,
690 struct snd_soc_dai *dai)
691{
692 struct snd_soc_pcm_runtime *rtd = substream->private_data;
693 struct snd_soc_device *socdev = rtd->socdev;
694 struct snd_soc_codec *codec = socdev->card->codec;
583 int ret = 0;
584
585 dev_dbg(codec->dev, "%s: ID %d, freq %u\n", __func__, clk_id, freq);
586
587 if (freq) {
588 wm8978->f_mclk = freq;
589
590 /* Even if MCLK is used for system clock, might have to drive OPCLK */

--- 95 unchanged lines hidden (view full) ---

686 */
687static int wm8978_hw_params(struct snd_pcm_substream *substream,
688 struct snd_pcm_hw_params *params,
689 struct snd_soc_dai *dai)
690{
691 struct snd_soc_pcm_runtime *rtd = substream->private_data;
692 struct snd_soc_device *socdev = rtd->socdev;
693 struct snd_soc_codec *codec = socdev->card->codec;
695 struct wm8978_priv *wm8978 = codec->private_data;
694 struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
696 /* Word length mask = 0x60 */
697 u16 iface_ctl = snd_soc_read(codec, WM8978_AUDIO_INTERFACE) & ~0x60;
698 /* Sampling rate mask = 0xe (for filters) */
699 u16 add_ctl = snd_soc_read(codec, WM8978_ADDITIONAL_CONTROL) & ~0xe;
700 u16 clking = snd_soc_read(codec, WM8978_CLOCKING);
701 enum wm8978_sysclk_src current_clk_id = clking & 0x100 ?
702 WM8978_PLL : WM8978_MCLK;
703 unsigned int f_sel, diff, diff_best = INT_MAX;

--- 203 unchanged lines hidden (view full) ---

907
908 return 0;
909}
910
911static int wm8978_resume(struct platform_device *pdev)
912{
913 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
914 struct snd_soc_codec *codec = socdev->card->codec;
695 /* Word length mask = 0x60 */
696 u16 iface_ctl = snd_soc_read(codec, WM8978_AUDIO_INTERFACE) & ~0x60;
697 /* Sampling rate mask = 0xe (for filters) */
698 u16 add_ctl = snd_soc_read(codec, WM8978_ADDITIONAL_CONTROL) & ~0xe;
699 u16 clking = snd_soc_read(codec, WM8978_CLOCKING);
700 enum wm8978_sysclk_src current_clk_id = clking & 0x100 ?
701 WM8978_PLL : WM8978_MCLK;
702 unsigned int f_sel, diff, diff_best = INT_MAX;

--- 203 unchanged lines hidden (view full) ---

906
907 return 0;
908}
909
910static int wm8978_resume(struct platform_device *pdev)
911{
912 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
913 struct snd_soc_codec *codec = socdev->card->codec;
915 struct wm8978_priv *wm8978 = codec->private_data;
914 struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
916 int i;
917 u16 *cache = codec->reg_cache;
918
919 /* Sync reg_cache with the hardware */
920 for (i = 0; i < ARRAY_SIZE(wm8978_reg); i++) {
921 if (i == WM8978_RESET)
922 continue;
923 if (cache[i] != wm8978_reg[i])

--- 91 unchanged lines hidden (view full) ---

1015 * default hardware setting
1016 */
1017 wm8978->sysclk = WM8978_PLL;
1018
1019 mutex_init(&codec->mutex);
1020 INIT_LIST_HEAD(&codec->dapm_widgets);
1021 INIT_LIST_HEAD(&codec->dapm_paths);
1022
915 int i;
916 u16 *cache = codec->reg_cache;
917
918 /* Sync reg_cache with the hardware */
919 for (i = 0; i < ARRAY_SIZE(wm8978_reg); i++) {
920 if (i == WM8978_RESET)
921 continue;
922 if (cache[i] != wm8978_reg[i])

--- 91 unchanged lines hidden (view full) ---

1014 * default hardware setting
1015 */
1016 wm8978->sysclk = WM8978_PLL;
1017
1018 mutex_init(&codec->mutex);
1019 INIT_LIST_HEAD(&codec->dapm_widgets);
1020 INIT_LIST_HEAD(&codec->dapm_paths);
1021
1023 codec->private_data = wm8978;
1022 snd_soc_codec_set_drvdata(codec, wm8978);
1024 codec->name = "WM8978";
1025 codec->owner = THIS_MODULE;
1026 codec->bias_level = SND_SOC_BIAS_OFF;
1027 codec->set_bias_level = wm8978_set_bias_level;
1028 codec->dai = &wm8978_dai;
1029 codec->num_dai = 1;
1030 codec->reg_cache_size = WM8978_CACHEREGNUM;
1031 codec->reg_cache = &wm8978->reg_cache;

--- 119 unchanged lines hidden ---
1023 codec->name = "WM8978";
1024 codec->owner = THIS_MODULE;
1025 codec->bias_level = SND_SOC_BIAS_OFF;
1026 codec->set_bias_level = wm8978_set_bias_level;
1027 codec->dai = &wm8978_dai;
1028 codec->num_dai = 1;
1029 codec->reg_cache_size = WM8978_CACHEREGNUM;
1030 codec->reg_cache = &wm8978->reg_cache;

--- 119 unchanged lines hidden ---