Merge branch 'for-2.6.32' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound-2.6 into topic/asoc
This commit is contained in:
commit
62b1653e29
|
@ -279,6 +279,7 @@ int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
|
|||
/* dapm events */
|
||||
int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, char *stream,
|
||||
int event);
|
||||
void snd_soc_dapm_shutdown(struct snd_soc_device *socdev);
|
||||
|
||||
/* dapm sys fs - used by the core */
|
||||
int snd_soc_dapm_sys_add(struct device *dev);
|
||||
|
|
|
@ -192,6 +192,11 @@ void snd_soc_unregister_platform(struct snd_soc_platform *platform);
|
|||
int snd_soc_register_codec(struct snd_soc_codec *codec);
|
||||
void snd_soc_unregister_codec(struct snd_soc_codec *codec);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int snd_soc_suspend_device(struct device *dev);
|
||||
int snd_soc_resume_device(struct device *dev);
|
||||
#endif
|
||||
|
||||
/* pcm <-> DAI connect */
|
||||
void snd_soc_free_pcms(struct snd_soc_device *socdev);
|
||||
int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid);
|
||||
|
@ -216,9 +221,9 @@ void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
|
|||
|
||||
/* codec register bit access */
|
||||
int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
|
||||
unsigned short mask, unsigned short value);
|
||||
unsigned int mask, unsigned int value);
|
||||
int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
|
||||
unsigned short mask, unsigned short value);
|
||||
unsigned int mask, unsigned int value);
|
||||
|
||||
int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
|
||||
struct snd_ac97_bus_ops *ops, int num);
|
||||
|
@ -369,8 +374,6 @@ struct snd_soc_codec {
|
|||
enum snd_soc_bias_level bias_level;
|
||||
enum snd_soc_bias_level suspend_bias_level;
|
||||
struct delayed_work delayed_work;
|
||||
struct list_head up_list;
|
||||
struct list_head down_list;
|
||||
|
||||
/* codec DAI's */
|
||||
struct snd_soc_dai *dai;
|
||||
|
|
22
include/sound/uda1380.h
Normal file
22
include/sound/uda1380.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* UDA1380 ALSA SoC Codec driver
|
||||
*
|
||||
* Copyright 2009 Philipp Zabel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __UDA1380_H
|
||||
#define __UDA1380_H
|
||||
|
||||
struct uda1380_platform_data {
|
||||
int gpio_power;
|
||||
int gpio_reset;
|
||||
int dac_clk;
|
||||
#define UDA1380_DAC_CLK_SYSCLK 0
|
||||
#define UDA1380_DAC_CLK_WSPLL 1
|
||||
};
|
||||
|
||||
#endif /* __UDA1380_H */
|
|
@ -203,23 +203,23 @@ static struct snd_soc_device bf5xx_ad73311_snd_devdata = {
|
|||
.codec_dev = &soc_codec_dev_ad73311,
|
||||
};
|
||||
|
||||
static struct platform_device *bf52x_ad73311_snd_device;
|
||||
static struct platform_device *bf5xx_ad73311_snd_device;
|
||||
|
||||
static int __init bf5xx_ad73311_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
pr_debug("%s enter\n", __func__);
|
||||
bf52x_ad73311_snd_device = platform_device_alloc("soc-audio", -1);
|
||||
if (!bf52x_ad73311_snd_device)
|
||||
bf5xx_ad73311_snd_device = platform_device_alloc("soc-audio", -1);
|
||||
if (!bf5xx_ad73311_snd_device)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(bf52x_ad73311_snd_device, &bf5xx_ad73311_snd_devdata);
|
||||
bf5xx_ad73311_snd_devdata.dev = &bf52x_ad73311_snd_device->dev;
|
||||
ret = platform_device_add(bf52x_ad73311_snd_device);
|
||||
platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311_snd_devdata);
|
||||
bf5xx_ad73311_snd_devdata.dev = &bf5xx_ad73311_snd_device->dev;
|
||||
ret = platform_device_add(bf5xx_ad73311_snd_device);
|
||||
|
||||
if (ret)
|
||||
platform_device_put(bf52x_ad73311_snd_device);
|
||||
platform_device_put(bf5xx_ad73311_snd_device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ static int __init bf5xx_ad73311_init(void)
|
|||
static void __exit bf5xx_ad73311_exit(void)
|
||||
{
|
||||
pr_debug("%s enter\n", __func__);
|
||||
platform_device_unregister(bf52x_ad73311_snd_device);
|
||||
platform_device_unregister(bf5xx_ad73311_snd_device);
|
||||
}
|
||||
|
||||
module_init(bf5xx_ad73311_init);
|
||||
|
|
|
@ -148,24 +148,24 @@ static struct snd_soc_device bf5xx_ssm2602_snd_devdata = {
|
|||
.codec_data = &bf5xx_ssm2602_setup,
|
||||
};
|
||||
|
||||
static struct platform_device *bf52x_ssm2602_snd_device;
|
||||
static struct platform_device *bf5xx_ssm2602_snd_device;
|
||||
|
||||
static int __init bf5xx_ssm2602_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
pr_debug("%s enter\n", __func__);
|
||||
bf52x_ssm2602_snd_device = platform_device_alloc("soc-audio", -1);
|
||||
if (!bf52x_ssm2602_snd_device)
|
||||
bf5xx_ssm2602_snd_device = platform_device_alloc("soc-audio", -1);
|
||||
if (!bf5xx_ssm2602_snd_device)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(bf52x_ssm2602_snd_device,
|
||||
platform_set_drvdata(bf5xx_ssm2602_snd_device,
|
||||
&bf5xx_ssm2602_snd_devdata);
|
||||
bf5xx_ssm2602_snd_devdata.dev = &bf52x_ssm2602_snd_device->dev;
|
||||
ret = platform_device_add(bf52x_ssm2602_snd_device);
|
||||
bf5xx_ssm2602_snd_devdata.dev = &bf5xx_ssm2602_snd_device->dev;
|
||||
ret = platform_device_add(bf5xx_ssm2602_snd_device);
|
||||
|
||||
if (ret)
|
||||
platform_device_put(bf52x_ssm2602_snd_device);
|
||||
platform_device_put(bf5xx_ssm2602_snd_device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ static int __init bf5xx_ssm2602_init(void)
|
|||
static void __exit bf5xx_ssm2602_exit(void)
|
||||
{
|
||||
pr_debug("%s enter\n", __func__);
|
||||
platform_device_unregister(bf52x_ssm2602_snd_device);
|
||||
platform_device_unregister(bf5xx_ssm2602_snd_device);
|
||||
}
|
||||
|
||||
module_init(bf5xx_ssm2602_init);
|
||||
|
|
|
@ -39,6 +39,7 @@ config SND_SOC_ALL_CODECS
|
|||
select SND_SOC_WM8903 if I2C
|
||||
select SND_SOC_WM8940 if I2C
|
||||
select SND_SOC_WM8960 if I2C
|
||||
select SND_SOC_WM8961 if I2C
|
||||
select SND_SOC_WM8971 if I2C
|
||||
select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI
|
||||
select SND_SOC_WM8990 if I2C
|
||||
|
@ -156,6 +157,9 @@ config SND_SOC_WM8940
|
|||
config SND_SOC_WM8960
|
||||
tristate
|
||||
|
||||
config SND_SOC_WM8961
|
||||
tristate
|
||||
|
||||
config SND_SOC_WM8971
|
||||
tristate
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ snd-soc-wm8900-objs := wm8900.o
|
|||
snd-soc-wm8903-objs := wm8903.o
|
||||
snd-soc-wm8940-objs := wm8940.o
|
||||
snd-soc-wm8960-objs := wm8960.o
|
||||
snd-soc-wm8961-objs := wm8961.o
|
||||
snd-soc-wm8971-objs := wm8971.o
|
||||
snd-soc-wm8988-objs := wm8988.o
|
||||
snd-soc-wm8990-objs := wm8990.o
|
||||
|
@ -65,6 +66,7 @@ obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o
|
|||
obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o
|
||||
obj-$(CONFIG_SND_SOC_WM8940) += snd-soc-wm8940.o
|
||||
obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o
|
||||
obj-$(CONFIG_SND_SOC_WM8961) += snd-soc-wm8961.o
|
||||
obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o
|
||||
obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o
|
||||
obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o
|
||||
|
|
|
@ -712,7 +712,19 @@ static int bypass_event(struct snd_soc_dapm_widget *w,
|
|||
|
||||
reg = twl4030_read_reg_cache(w->codec, m->reg);
|
||||
|
||||
if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) {
|
||||
/*
|
||||
* bypass_state[0:3] - analog HiFi bypass
|
||||
* bypass_state[4] - analog voice bypass
|
||||
* bypass_state[5] - digital voice bypass
|
||||
* bypass_state[6:7] - digital HiFi bypass
|
||||
*/
|
||||
if (m->reg == TWL4030_REG_VSTPGA) {
|
||||
/* Voice digital bypass */
|
||||
if (reg)
|
||||
twl4030->bypass_state |= (1 << 5);
|
||||
else
|
||||
twl4030->bypass_state &= ~(1 << 5);
|
||||
} else if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) {
|
||||
/* Analog bypass */
|
||||
if (reg & (1 << m->shift))
|
||||
twl4030->bypass_state |=
|
||||
|
@ -726,12 +738,6 @@ static int bypass_event(struct snd_soc_dapm_widget *w,
|
|||
twl4030->bypass_state |= (1 << 4);
|
||||
else
|
||||
twl4030->bypass_state &= ~(1 << 4);
|
||||
} else if (m->reg == TWL4030_REG_VSTPGA) {
|
||||
/* Voice digital bypass */
|
||||
if (reg)
|
||||
twl4030->bypass_state |= (1 << 5);
|
||||
else
|
||||
twl4030->bypass_state &= ~(1 << 5);
|
||||
} else {
|
||||
/* Digital bypass */
|
||||
if (reg & (0x7 << m->shift))
|
||||
|
@ -924,7 +930,7 @@ static const struct soc_enum twl4030_op_modes_enum =
|
|||
ARRAY_SIZE(twl4030_op_modes_texts),
|
||||
twl4030_op_modes_texts);
|
||||
|
||||
int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol,
|
||||
static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
|
@ -1005,6 +1011,16 @@ static DECLARE_TLV_DB_SCALE(digital_capture_tlv, 0, 100, 0);
|
|||
*/
|
||||
static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0);
|
||||
|
||||
/* AVADC clock priority */
|
||||
static const char *twl4030_avadc_clk_priority_texts[] = {
|
||||
"Voice high priority", "HiFi high priority"
|
||||
};
|
||||
|
||||
static const struct soc_enum twl4030_avadc_clk_priority_enum =
|
||||
SOC_ENUM_SINGLE(TWL4030_REG_AVADC_CTL, 2,
|
||||
ARRAY_SIZE(twl4030_avadc_clk_priority_texts),
|
||||
twl4030_avadc_clk_priority_texts);
|
||||
|
||||
static const char *twl4030_rampdelay_texts[] = {
|
||||
"27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms",
|
||||
"437/323/218 ms", "874/645/437 ms", "1748/1291/874 ms",
|
||||
|
@ -1106,6 +1122,8 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
|
|||
SOC_DOUBLE_TLV("Analog Capture Volume", TWL4030_REG_ANAMIC_GAIN,
|
||||
0, 3, 5, 0, input_gain_tlv),
|
||||
|
||||
SOC_ENUM("AVADC Clock Priority", twl4030_avadc_clk_priority_enum),
|
||||
|
||||
SOC_ENUM("HS ramp delay", twl4030_rampdelay_enum),
|
||||
|
||||
SOC_ENUM("Vibra H-bridge mode", twl4030_vibradirmode_enum),
|
||||
|
@ -1609,8 +1627,6 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
|
|||
|
||||
/* If the substream has 4 channel, do the necessary setup */
|
||||
if (params_channels(params) == 4) {
|
||||
u8 format, mode;
|
||||
|
||||
format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
|
||||
mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
|
||||
|
||||
|
@ -1948,7 +1964,7 @@ static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
|||
|
||||
/* set master/slave audio interface */
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
case SND_SOC_DAIFMT_CBS_CFM:
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
format &= ~(TWL4030_VIF_SLAVE_EN);
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Copyright (c) 2007 Philipp Zabel <philipp.zabel@gmail.com>
|
||||
* Improved support for DAPM and audio routing/mixing capabilities,
|
||||
* added TLV support.
|
||||
* Copyright (c) 2007-2009 Philipp Zabel <philipp.zabel@gmail.com>
|
||||
*
|
||||
* Modified by Richard Purdie <richard@openedhand.com> to fit into SoC
|
||||
* codec model.
|
||||
|
@ -19,26 +17,32 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/info.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <sound/uda1380.h>
|
||||
|
||||
#include "uda1380.h"
|
||||
|
||||
static struct work_struct uda1380_work;
|
||||
static struct snd_soc_codec *uda1380_codec;
|
||||
|
||||
/* codec private data */
|
||||
struct uda1380_priv {
|
||||
struct snd_soc_codec codec;
|
||||
u16 reg_cache[UDA1380_CACHEREGNUM];
|
||||
unsigned int dac_clk;
|
||||
struct work_struct work;
|
||||
};
|
||||
|
||||
/*
|
||||
* uda1380 register cache
|
||||
*/
|
||||
|
@ -473,6 +477,7 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd,
|
|||
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 uda1380_priv *uda1380 = codec->private_data;
|
||||
int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER);
|
||||
|
||||
switch (cmd) {
|
||||
|
@ -480,13 +485,13 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd,
|
|||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
uda1380_write_reg_cache(codec, UDA1380_MIXER,
|
||||
mixer & ~R14_SILENCE);
|
||||
schedule_work(&uda1380_work);
|
||||
schedule_work(&uda1380->work);
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
uda1380_write_reg_cache(codec, UDA1380_MIXER,
|
||||
mixer | R14_SILENCE);
|
||||
schedule_work(&uda1380_work);
|
||||
schedule_work(&uda1380->work);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
@ -670,44 +675,33 @@ static int uda1380_resume(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* initialise the UDA1380 driver
|
||||
* register mixer and dsp interfaces with the kernel
|
||||
*/
|
||||
static int uda1380_init(struct snd_soc_device *socdev, int dac_clk)
|
||||
static int uda1380_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec;
|
||||
struct uda1380_platform_data *pdata;
|
||||
int ret = 0;
|
||||
|
||||
codec->name = "UDA1380";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->read = uda1380_read_reg_cache;
|
||||
codec->write = uda1380_write;
|
||||
codec->set_bias_level = uda1380_set_bias_level;
|
||||
codec->dai = uda1380_dai;
|
||||
codec->num_dai = ARRAY_SIZE(uda1380_dai);
|
||||
codec->reg_cache = kmemdup(uda1380_reg, sizeof(uda1380_reg),
|
||||
GFP_KERNEL);
|
||||
if (codec->reg_cache == NULL)
|
||||
return -ENOMEM;
|
||||
codec->reg_cache_size = ARRAY_SIZE(uda1380_reg);
|
||||
codec->reg_cache_step = 1;
|
||||
uda1380_reset(codec);
|
||||
if (uda1380_codec == NULL) {
|
||||
dev_err(&pdev->dev, "Codec device not registered\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
uda1380_codec = codec;
|
||||
INIT_WORK(&uda1380_work, uda1380_flush_work);
|
||||
socdev->card->codec = uda1380_codec;
|
||||
codec = uda1380_codec;
|
||||
pdata = codec->dev->platform_data;
|
||||
|
||||
/* register pcms */
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
if (ret < 0) {
|
||||
pr_err("uda1380: failed to create pcms\n");
|
||||
dev_err(codec->dev, "failed to create pcms: %d\n", ret);
|
||||
goto pcm_err;
|
||||
}
|
||||
|
||||
/* power on device */
|
||||
uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
/* set clock input */
|
||||
switch (dac_clk) {
|
||||
switch (pdata->dac_clk) {
|
||||
case UDA1380_DAC_CLK_SYSCLK:
|
||||
uda1380_write(codec, UDA1380_CLK, 0);
|
||||
break;
|
||||
|
@ -716,13 +710,12 @@ static int uda1380_init(struct snd_soc_device *socdev, int dac_clk)
|
|||
break;
|
||||
}
|
||||
|
||||
/* uda1380 init */
|
||||
snd_soc_add_controls(codec, uda1380_snd_controls,
|
||||
ARRAY_SIZE(uda1380_snd_controls));
|
||||
uda1380_add_widgets(codec);
|
||||
ret = snd_soc_init_card(socdev);
|
||||
if (ret < 0) {
|
||||
pr_err("uda1380: failed to register card\n");
|
||||
dev_err(codec->dev, "failed to register card: %d\n", ret);
|
||||
goto card_err;
|
||||
}
|
||||
|
||||
|
@ -732,36 +725,164 @@ card_err:
|
|||
snd_soc_free_pcms(socdev);
|
||||
snd_soc_dapm_free(socdev);
|
||||
pcm_err:
|
||||
kfree(codec->reg_cache);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct snd_soc_device *uda1380_socdev;
|
||||
/* power down chip */
|
||||
static int uda1380_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
|
||||
if (codec->control_data)
|
||||
uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
|
||||
snd_soc_free_pcms(socdev);
|
||||
snd_soc_dapm_free(socdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_uda1380 = {
|
||||
.probe = uda1380_probe,
|
||||
.remove = uda1380_remove,
|
||||
.suspend = uda1380_suspend,
|
||||
.resume = uda1380_resume,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380);
|
||||
|
||||
static int uda1380_register(struct uda1380_priv *uda1380)
|
||||
{
|
||||
int ret, i;
|
||||
struct snd_soc_codec *codec = &uda1380->codec;
|
||||
struct uda1380_platform_data *pdata = codec->dev->platform_data;
|
||||
|
||||
if (uda1380_codec) {
|
||||
dev_err(codec->dev, "Another UDA1380 is registered\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!pdata || !pdata->gpio_power || !pdata->gpio_reset)
|
||||
return -EINVAL;
|
||||
|
||||
ret = gpio_request(pdata->gpio_power, "uda1380 power");
|
||||
if (ret)
|
||||
goto err_out;
|
||||
ret = gpio_request(pdata->gpio_reset, "uda1380 reset");
|
||||
if (ret)
|
||||
goto err_gpio;
|
||||
|
||||
gpio_direction_output(pdata->gpio_power, 1);
|
||||
|
||||
/* we may need to have the clock running here - pH5 */
|
||||
gpio_direction_output(pdata->gpio_reset, 1);
|
||||
udelay(5);
|
||||
gpio_set_value(pdata->gpio_reset, 0);
|
||||
|
||||
mutex_init(&codec->mutex);
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
|
||||
codec->private_data = uda1380;
|
||||
codec->name = "UDA1380";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->read = uda1380_read_reg_cache;
|
||||
codec->write = uda1380_write;
|
||||
codec->bias_level = SND_SOC_BIAS_OFF;
|
||||
codec->set_bias_level = uda1380_set_bias_level;
|
||||
codec->dai = uda1380_dai;
|
||||
codec->num_dai = ARRAY_SIZE(uda1380_dai);
|
||||
codec->reg_cache_size = ARRAY_SIZE(uda1380_reg);
|
||||
codec->reg_cache = &uda1380->reg_cache;
|
||||
codec->reg_cache_step = 1;
|
||||
|
||||
memcpy(codec->reg_cache, uda1380_reg, sizeof(uda1380_reg));
|
||||
|
||||
ret = uda1380_reset(codec);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to issue reset\n");
|
||||
goto err_reset;
|
||||
}
|
||||
|
||||
INIT_WORK(&uda1380->work, uda1380_flush_work);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(uda1380_dai); i++)
|
||||
uda1380_dai[i].dev = codec->dev;
|
||||
|
||||
uda1380_codec = codec;
|
||||
|
||||
ret = snd_soc_register_codec(codec);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to register codec: %d\n", ret);
|
||||
goto err_reset;
|
||||
}
|
||||
|
||||
ret = snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
|
||||
goto err_dai;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_dai:
|
||||
snd_soc_unregister_codec(codec);
|
||||
err_reset:
|
||||
gpio_set_value(pdata->gpio_power, 0);
|
||||
gpio_free(pdata->gpio_reset);
|
||||
err_gpio:
|
||||
gpio_free(pdata->gpio_power);
|
||||
err_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void uda1380_unregister(struct uda1380_priv *uda1380)
|
||||
{
|
||||
struct snd_soc_codec *codec = &uda1380->codec;
|
||||
struct uda1380_platform_data *pdata = codec->dev->platform_data;
|
||||
|
||||
snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
|
||||
snd_soc_unregister_codec(&uda1380->codec);
|
||||
|
||||
gpio_set_value(pdata->gpio_power, 0);
|
||||
gpio_free(pdata->gpio_reset);
|
||||
gpio_free(pdata->gpio_power);
|
||||
|
||||
kfree(uda1380);
|
||||
uda1380_codec = NULL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
|
||||
static int uda1380_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
static __devinit int uda1380_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct snd_soc_device *socdev = uda1380_socdev;
|
||||
struct uda1380_setup_data *setup = socdev->codec_data;
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
struct uda1380_priv *uda1380;
|
||||
struct snd_soc_codec *codec;
|
||||
int ret;
|
||||
|
||||
i2c_set_clientdata(i2c, codec);
|
||||
uda1380 = kzalloc(sizeof(struct uda1380_priv), GFP_KERNEL);
|
||||
if (uda1380 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
codec = &uda1380->codec;
|
||||
codec->hw_write = (hw_write_t)i2c_master_send;
|
||||
|
||||
i2c_set_clientdata(i2c, uda1380);
|
||||
codec->control_data = i2c;
|
||||
|
||||
ret = uda1380_init(socdev, setup->dac_clk);
|
||||
if (ret < 0)
|
||||
pr_err("uda1380: failed to initialise UDA1380\n");
|
||||
codec->dev = &i2c->dev;
|
||||
|
||||
ret = uda1380_register(uda1380);
|
||||
if (ret != 0)
|
||||
kfree(uda1380);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uda1380_i2c_remove(struct i2c_client *client)
|
||||
static int __devexit uda1380_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct snd_soc_codec *codec = i2c_get_clientdata(client);
|
||||
kfree(codec->reg_cache);
|
||||
struct uda1380_priv *uda1380 = i2c_get_clientdata(i2c);
|
||||
uda1380_unregister(uda1380);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -777,120 +898,28 @@ static struct i2c_driver uda1380_i2c_driver = {
|
|||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = uda1380_i2c_probe,
|
||||
.remove = uda1380_i2c_remove,
|
||||
.remove = __devexit_p(uda1380_i2c_remove),
|
||||
.id_table = uda1380_i2c_id,
|
||||
};
|
||||
|
||||
static int uda1380_add_i2c_device(struct platform_device *pdev,
|
||||
const struct uda1380_setup_data *setup)
|
||||
{
|
||||
struct i2c_board_info info;
|
||||
struct i2c_adapter *adapter;
|
||||
struct i2c_client *client;
|
||||
int ret;
|
||||
|
||||
ret = i2c_add_driver(&uda1380_i2c_driver);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "can't add i2c driver\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||
info.addr = setup->i2c_address;
|
||||
strlcpy(info.type, "uda1380", I2C_NAME_SIZE);
|
||||
|
||||
adapter = i2c_get_adapter(setup->i2c_bus);
|
||||
if (!adapter) {
|
||||
dev_err(&pdev->dev, "can't get i2c adapter %d\n",
|
||||
setup->i2c_bus);
|
||||
goto err_driver;
|
||||
}
|
||||
|
||||
client = i2c_new_device(adapter, &info);
|
||||
i2c_put_adapter(adapter);
|
||||
if (!client) {
|
||||
dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
|
||||
(unsigned int)info.addr);
|
||||
goto err_driver;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_driver:
|
||||
i2c_del_driver(&uda1380_i2c_driver);
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int uda1380_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct uda1380_setup_data *setup;
|
||||
struct snd_soc_codec *codec;
|
||||
int ret;
|
||||
|
||||
setup = socdev->codec_data;
|
||||
codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
|
||||
if (codec == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
socdev->card->codec = codec;
|
||||
mutex_init(&codec->mutex);
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
|
||||
uda1380_socdev = socdev;
|
||||
ret = -ENODEV;
|
||||
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
if (setup->i2c_address) {
|
||||
codec->hw_write = (hw_write_t)i2c_master_send;
|
||||
ret = uda1380_add_i2c_device(pdev, setup);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret != 0)
|
||||
kfree(codec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* power down chip */
|
||||
static int uda1380_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
|
||||
if (codec->control_data)
|
||||
uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
|
||||
snd_soc_free_pcms(socdev);
|
||||
snd_soc_dapm_free(socdev);
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
i2c_unregister_device(codec->control_data);
|
||||
i2c_del_driver(&uda1380_i2c_driver);
|
||||
#endif
|
||||
kfree(codec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_uda1380 = {
|
||||
.probe = uda1380_probe,
|
||||
.remove = uda1380_remove,
|
||||
.suspend = uda1380_suspend,
|
||||
.resume = uda1380_resume,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380);
|
||||
|
||||
static int __init uda1380_modinit(void)
|
||||
{
|
||||
return snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
|
||||
int ret;
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
ret = i2c_add_driver(&uda1380_i2c_driver);
|
||||
if (ret != 0)
|
||||
pr_err("Failed to register UDA1380 I2C driver: %d\n", ret);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
module_init(uda1380_modinit);
|
||||
|
||||
static void __exit uda1380_exit(void)
|
||||
{
|
||||
snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
i2c_del_driver(&uda1380_i2c_driver);
|
||||
#endif
|
||||
}
|
||||
module_exit(uda1380_exit);
|
||||
|
||||
|
|
|
@ -72,14 +72,6 @@
|
|||
#define R22_SKIP_DCFIL 0x0002
|
||||
#define R23_AGC_EN 0x0001
|
||||
|
||||
struct uda1380_setup_data {
|
||||
int i2c_bus;
|
||||
unsigned short i2c_address;
|
||||
int dac_clk;
|
||||
#define UDA1380_DAC_CLK_SYSCLK 0
|
||||
#define UDA1380_DAC_CLK_WSPLL 1
|
||||
};
|
||||
|
||||
#define UDA1380_DAI_DUPLEX 0 /* playback and capture on single DAI */
|
||||
#define UDA1380_DAI_PLAYBACK 1 /* playback DAI */
|
||||
#define UDA1380_DAI_CAPTURE 2 /* capture DAI */
|
||||
|
|
|
@ -406,7 +406,6 @@ static const char *wm8350_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
|
|||
static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" };
|
||||
static const char *wm8350_dacmutem[] = { "Normal", "Soft" };
|
||||
static const char *wm8350_dacmutes[] = { "Fast", "Slow" };
|
||||
static const char *wm8350_dacfilter[] = { "Normal", "Sloping" };
|
||||
static const char *wm8350_adcfilter[] = { "None", "High Pass" };
|
||||
static const char *wm8350_adchp[] = { "44.1kHz", "8kHz", "16kHz", "32kHz" };
|
||||
static const char *wm8350_lr[] = { "Left", "Right" };
|
||||
|
@ -416,7 +415,6 @@ static const struct soc_enum wm8350_enum[] = {
|
|||
SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 0, 4, wm8350_pol),
|
||||
SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 14, 2, wm8350_dacmutem),
|
||||
SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 13, 2, wm8350_dacmutes),
|
||||
SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 12, 2, wm8350_dacfilter),
|
||||
SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 15, 2, wm8350_adcfilter),
|
||||
SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 8, 4, wm8350_adchp),
|
||||
SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 0, 4, wm8350_pol),
|
||||
|
@ -444,10 +442,9 @@ static const struct snd_kcontrol_new wm8350_snd_controls[] = {
|
|||
0, 255, 0, dac_pcm_tlv),
|
||||
SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]),
|
||||
SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]),
|
||||
SOC_ENUM("Playback PCM Filter", wm8350_enum[4]),
|
||||
SOC_ENUM("Capture PCM Filter", wm8350_enum[5]),
|
||||
SOC_ENUM("Capture PCM HP Filter", wm8350_enum[6]),
|
||||
SOC_ENUM("Capture ADC Inversion", wm8350_enum[7]),
|
||||
SOC_ENUM("Capture PCM Filter", wm8350_enum[4]),
|
||||
SOC_ENUM("Capture PCM HP Filter", wm8350_enum[5]),
|
||||
SOC_ENUM("Capture ADC Inversion", wm8350_enum[6]),
|
||||
SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume",
|
||||
WM8350_ADC_DIGITAL_VOLUME_L,
|
||||
WM8350_ADC_DIGITAL_VOLUME_R,
|
||||
|
@ -993,6 +990,7 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_soc_dai *codec_dai)
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct wm8350 *wm8350 = codec->control_data;
|
||||
u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) &
|
||||
~WM8350_AIF_WL_MASK;
|
||||
|
||||
|
@ -1012,6 +1010,19 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
}
|
||||
|
||||
wm8350_codec_write(codec, WM8350_AI_FORMATING, iface);
|
||||
|
||||
/* The sloping stopband filter is recommended for use with
|
||||
* lower sample rates to improve performance.
|
||||
*/
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
if (params_rate(params) < 24000)
|
||||
wm8350_set_bits(wm8350, WM8350_DAC_MUTE_VOLUME,
|
||||
WM8350_DAC_SB_FILT);
|
||||
else
|
||||
wm8350_clear_bits(wm8350, WM8350_DAC_MUTE_VOLUME,
|
||||
WM8350_DAC_SB_FILT);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1660,6 +1671,21 @@ static int __devexit wm8350_codec_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm8350_codec_suspend(struct platform_device *pdev, pm_message_t m)
|
||||
{
|
||||
return snd_soc_suspend_device(&pdev->dev);
|
||||
}
|
||||
|
||||
static int wm8350_codec_resume(struct platform_device *pdev)
|
||||
{
|
||||
return snd_soc_resume_device(&pdev->dev);
|
||||
}
|
||||
#else
|
||||
#define wm8350_codec_suspend NULL
|
||||
#define wm8350_codec_resume NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver wm8350_codec_driver = {
|
||||
.driver = {
|
||||
.name = "wm8350-codec",
|
||||
|
@ -1667,6 +1693,8 @@ static struct platform_driver wm8350_codec_driver = {
|
|||
},
|
||||
.probe = wm8350_codec_probe,
|
||||
.remove = __devexit_p(wm8350_codec_remove),
|
||||
.suspend = wm8350_codec_suspend,
|
||||
.resume = wm8350_codec_resume,
|
||||
};
|
||||
|
||||
static __init int wm8350_init(void)
|
||||
|
|
|
@ -1553,6 +1553,21 @@ static int __exit wm8400_codec_remove(struct platform_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm8400_pdev_suspend(struct platform_device *pdev, pm_message_t msg)
|
||||
{
|
||||
return snd_soc_suspend_device(&pdev->dev);
|
||||
}
|
||||
|
||||
static int wm8400_pdev_resume(struct platform_device *pdev)
|
||||
{
|
||||
return snd_soc_resume_device(&pdev->dev);
|
||||
}
|
||||
#else
|
||||
#define wm8400_pdev_suspend NULL
|
||||
#define wm8400_pdev_resume NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver wm8400_codec_driver = {
|
||||
.driver = {
|
||||
.name = "wm8400-codec",
|
||||
|
@ -1560,6 +1575,8 @@ static struct platform_driver wm8400_codec_driver = {
|
|||
},
|
||||
.probe = wm8400_codec_probe,
|
||||
.remove = __exit_p(wm8400_codec_remove),
|
||||
.suspend = wm8400_pdev_suspend,
|
||||
.resume = wm8400_pdev_resume,
|
||||
};
|
||||
|
||||
static int __init wm8400_codec_init(void)
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include <linux/pm.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
|
@ -187,15 +189,22 @@ struct pll_state {
|
|||
unsigned int out;
|
||||
};
|
||||
|
||||
#define WM8580_NUM_SUPPLIES 3
|
||||
static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = {
|
||||
"AVDD",
|
||||
"DVDD",
|
||||
"PVDD",
|
||||
};
|
||||
|
||||
/* codec private data */
|
||||
struct wm8580_priv {
|
||||
struct snd_soc_codec codec;
|
||||
struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES];
|
||||
u16 reg_cache[WM8580_MAX_REGISTER + 1];
|
||||
struct pll_state a;
|
||||
struct pll_state b;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* read wm8580 register cache
|
||||
*/
|
||||
|
@ -922,11 +931,28 @@ static int wm8580_register(struct wm8580_priv *wm8580)
|
|||
|
||||
memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++)
|
||||
wm8580->supplies[i].supply = wm8580_supply_names[i];
|
||||
|
||||
ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8580->supplies),
|
||||
wm8580->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies),
|
||||
wm8580->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
|
||||
goto err_regulator_get;
|
||||
}
|
||||
|
||||
/* Get the codec into a known state */
|
||||
ret = wm8580_write(codec, WM8580_RESET, 0);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to reset codec: %d\n", ret);
|
||||
goto err;
|
||||
goto err_regulator_enable;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++)
|
||||
|
@ -939,7 +965,7 @@ static int wm8580_register(struct wm8580_priv *wm8580)
|
|||
ret = snd_soc_register_codec(codec);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to register codec: %d\n", ret);
|
||||
goto err;
|
||||
goto err_regulator_enable;
|
||||
}
|
||||
|
||||
ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
|
||||
|
@ -952,6 +978,10 @@ static int wm8580_register(struct wm8580_priv *wm8580)
|
|||
|
||||
err_codec:
|
||||
snd_soc_unregister_codec(codec);
|
||||
err_regulator_enable:
|
||||
regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
|
||||
err_regulator_get:
|
||||
regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
|
||||
err:
|
||||
kfree(wm8580);
|
||||
return ret;
|
||||
|
@ -962,6 +992,8 @@ static void wm8580_unregister(struct wm8580_priv *wm8580)
|
|||
wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF);
|
||||
snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
|
||||
snd_soc_unregister_codec(&wm8580->codec);
|
||||
regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
|
||||
regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
|
||||
kfree(wm8580);
|
||||
wm8580_codec = NULL;
|
||||
}
|
||||
|
@ -995,6 +1027,21 @@ static int wm8580_i2c_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm8580_i2c_suspend(struct i2c_client *client, pm_message_t msg)
|
||||
{
|
||||
return snd_soc_suspend_device(&client->dev);
|
||||
}
|
||||
|
||||
static int wm8580_i2c_resume(struct i2c_client *client)
|
||||
{
|
||||
return snd_soc_resume_device(&client->dev);
|
||||
}
|
||||
#else
|
||||
#define wm8580_i2c_suspend NULL
|
||||
#define wm8580_i2c_resume NULL
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id wm8580_i2c_id[] = {
|
||||
{ "wm8580", 0 },
|
||||
{ }
|
||||
|
@ -1008,6 +1055,8 @@ static struct i2c_driver wm8580_i2c_driver = {
|
|||
},
|
||||
.probe = wm8580_i2c_probe,
|
||||
.remove = wm8580_i2c_remove,
|
||||
.suspend = wm8580_i2c_suspend,
|
||||
.resume = wm8580_i2c_resume,
|
||||
.id_table = wm8580_i2c_id,
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -460,6 +460,7 @@ struct snd_soc_dai wm8731_dai = {
|
|||
};
|
||||
EXPORT_SYMBOL_GPL(wm8731_dai);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm8731_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
|
@ -488,6 +489,10 @@ static int wm8731_resume(struct platform_device *pdev)
|
|||
wm8731_set_bias_level(codec, codec->suspend_bias_level);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define wm8731_suspend NULL
|
||||
#define wm8731_resume NULL
|
||||
#endif
|
||||
|
||||
static int wm8731_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
@ -680,6 +685,21 @@ static int __devexit wm8731_spi_remove(struct spi_device *spi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm8731_spi_suspend(struct spi_device *spi, pm_message_t msg)
|
||||
{
|
||||
return snd_soc_suspend_device(&spi->dev);
|
||||
}
|
||||
|
||||
static int wm8731_spi_resume(struct spi_device *spi)
|
||||
{
|
||||
return snd_soc_resume_device(&spi->dev);
|
||||
}
|
||||
#else
|
||||
#define wm8731_spi_suspend NULL
|
||||
#define wm8731_spi_resume NULL
|
||||
#endif
|
||||
|
||||
static struct spi_driver wm8731_spi_driver = {
|
||||
.driver = {
|
||||
.name = "wm8731",
|
||||
|
@ -687,6 +707,8 @@ static struct spi_driver wm8731_spi_driver = {
|
|||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = wm8731_spi_probe,
|
||||
.suspend = wm8731_spi_suspend,
|
||||
.resume = wm8731_spi_resume,
|
||||
.remove = __devexit_p(wm8731_spi_remove),
|
||||
};
|
||||
#endif /* CONFIG_SPI_MASTER */
|
||||
|
@ -720,6 +742,21 @@ static __devexit int wm8731_i2c_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm8731_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
|
||||
{
|
||||
return snd_soc_suspend_device(&i2c->dev);
|
||||
}
|
||||
|
||||
static int wm8731_i2c_resume(struct i2c_client *i2c)
|
||||
{
|
||||
return snd_soc_resume_device(&i2c->dev);
|
||||
}
|
||||
#else
|
||||
#define wm8731_i2c_suspend NULL
|
||||
#define wm8731_i2c_resume NULL
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id wm8731_i2c_id[] = {
|
||||
{ "wm8731", 0 },
|
||||
{ }
|
||||
|
@ -733,6 +770,8 @@ static struct i2c_driver wm8731_i2c_driver = {
|
|||
},
|
||||
.probe = wm8731_i2c_probe,
|
||||
.remove = __devexit_p(wm8731_i2c_remove),
|
||||
.suspend = wm8731_i2c_suspend,
|
||||
.resume = wm8731_i2c_resume,
|
||||
.id_table = wm8731_i2c_id,
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -1766,6 +1766,21 @@ static int wm8753_i2c_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm8753_i2c_suspend(struct i2c_client *client, pm_message_t msg)
|
||||
{
|
||||
return snd_soc_suspend_device(&client->dev);
|
||||
}
|
||||
|
||||
static int wm8753_i2c_resume(struct i2c_client *client)
|
||||
{
|
||||
return snd_soc_resume_device(&client->dev);
|
||||
}
|
||||
#else
|
||||
#define wm8753_i2c_suspend NULL
|
||||
#define wm8753_i2c_resume NULL
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id wm8753_i2c_id[] = {
|
||||
{ "wm8753", 0 },
|
||||
{ }
|
||||
|
@ -1779,6 +1794,8 @@ static struct i2c_driver wm8753_i2c_driver = {
|
|||
},
|
||||
.probe = wm8753_i2c_probe,
|
||||
.remove = wm8753_i2c_remove,
|
||||
.suspend = wm8753_i2c_suspend,
|
||||
.resume = wm8753_i2c_resume,
|
||||
.id_table = wm8753_i2c_id,
|
||||
};
|
||||
#endif
|
||||
|
@ -1834,6 +1851,22 @@ static int __devexit wm8753_spi_remove(struct spi_device *spi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm8753_spi_suspend(struct spi_device *spi, pm_message_t msg)
|
||||
{
|
||||
return snd_soc_suspend_device(&spi->dev);
|
||||
}
|
||||
|
||||
static int wm8753_spi_resume(struct spi_device *spi)
|
||||
{
|
||||
return snd_soc_resume_device(&spi->dev);
|
||||
}
|
||||
|
||||
#else
|
||||
#define wm8753_spi_suspend NULL
|
||||
#define wm8753_spi_resume NULL
|
||||
#endif
|
||||
|
||||
static struct spi_driver wm8753_spi_driver = {
|
||||
.driver = {
|
||||
.name = "wm8753",
|
||||
|
@ -1842,6 +1875,8 @@ static struct spi_driver wm8753_spi_driver = {
|
|||
},
|
||||
.probe = wm8753_spi_probe,
|
||||
.remove = __devexit_p(wm8753_spi_remove),
|
||||
.suspend = wm8753_spi_suspend,
|
||||
.resume = wm8753_spi_resume,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -116,6 +116,7 @@
|
|||
#define WM8900_REG_CLOCKING2_DAC_CLKDIV 0x1c
|
||||
|
||||
#define WM8900_REG_DACCTRL_MUTE 0x004
|
||||
#define WM8900_REG_DACCTRL_DAC_SB_FILT 0x100
|
||||
#define WM8900_REG_DACCTRL_AIF_LRCLKRATE 0x400
|
||||
|
||||
#define WM8900_REG_AUDIO3_ADCLRC_DIR 0x0800
|
||||
|
@ -439,7 +440,6 @@ SOC_SINGLE("DAC Soft Mute Switch", WM8900_REG_DACCTRL, 6, 1, 1),
|
|||
SOC_ENUM("DAC Mute Rate", dac_mute_rate),
|
||||
SOC_SINGLE("DAC Mono Switch", WM8900_REG_DACCTRL, 9, 1, 0),
|
||||
SOC_ENUM("DAC Deemphasis", dac_deemphasis),
|
||||
SOC_SINGLE("DAC Sloping Stopband Filter Switch", WM8900_REG_DACCTRL, 8, 1, 0),
|
||||
SOC_SINGLE("DAC Sigma-Delta Modulator Clock Switch", WM8900_REG_DACCTRL,
|
||||
12, 1, 0),
|
||||
|
||||
|
@ -743,6 +743,17 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream,
|
|||
|
||||
wm8900_write(codec, WM8900_REG_AUDIO1, reg);
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
reg = wm8900_read(codec, WM8900_REG_DACCTRL);
|
||||
|
||||
if (params_rate(params) <= 24000)
|
||||
reg |= WM8900_REG_DACCTRL_DAC_SB_FILT;
|
||||
else
|
||||
reg &= ~WM8900_REG_DACCTRL_DAC_SB_FILT;
|
||||
|
||||
wm8900_write(codec, WM8900_REG_DACCTRL, reg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1388,6 +1399,21 @@ static __devexit int wm8900_i2c_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm8900_i2c_suspend(struct i2c_client *client, pm_message_t msg)
|
||||
{
|
||||
return snd_soc_suspend_device(&client->dev);
|
||||
}
|
||||
|
||||
static int wm8900_i2c_resume(struct i2c_client *client)
|
||||
{
|
||||
return snd_soc_resume_device(&client->dev);
|
||||
}
|
||||
#else
|
||||
#define wm8900_i2c_suspend NULL
|
||||
#define wm8900_i2c_resume NULL
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id wm8900_i2c_id[] = {
|
||||
{ "wm8900", 0 },
|
||||
{ }
|
||||
|
@ -1401,6 +1427,8 @@ static struct i2c_driver wm8900_i2c_driver = {
|
|||
},
|
||||
.probe = wm8900_i2c_probe,
|
||||
.remove = __devexit_p(wm8900_i2c_remove),
|
||||
.suspend = wm8900_i2c_suspend,
|
||||
.resume = wm8900_i2c_resume,
|
||||
.id_table = wm8900_i2c_id,
|
||||
};
|
||||
|
||||
|
|
|
@ -715,8 +715,6 @@ SOC_ENUM("DAC Soft Mute Rate", soft_mute),
|
|||
SOC_ENUM("DAC Mute Mode", mute_mode),
|
||||
SOC_SINGLE("DAC Mono Switch", WM8903_DAC_DIGITAL_1, 12, 1, 0),
|
||||
SOC_ENUM("DAC De-emphasis", dac_deemphasis),
|
||||
SOC_SINGLE("DAC Sloping Stopband Filter Switch",
|
||||
WM8903_DAC_DIGITAL_1, 11, 1, 0),
|
||||
SOC_ENUM("DAC Companding Mode", dac_companding),
|
||||
SOC_SINGLE("DAC Companding Switch", WM8903_AUDIO_INTERFACE_0, 1, 1, 0),
|
||||
|
||||
|
@ -1373,12 +1371,19 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
|
|||
u16 aif3 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_3);
|
||||
u16 clock0 = wm8903_read(codec, WM8903_CLOCK_RATES_0);
|
||||
u16 clock1 = wm8903_read(codec, WM8903_CLOCK_RATES_1);
|
||||
u16 dac_digital1 = wm8903_read(codec, WM8903_DAC_DIGITAL_1);
|
||||
|
||||
if (substream == wm8903->slave_substream) {
|
||||
dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Enable sloping stopband filter for low sample rates */
|
||||
if (fs <= 24000)
|
||||
dac_digital1 |= WM8903_DAC_SB_FILT;
|
||||
else
|
||||
dac_digital1 &= ~WM8903_DAC_SB_FILT;
|
||||
|
||||
/* Configure sample rate logic for DSP - choose nearest rate */
|
||||
dsp_config = 0;
|
||||
best_val = abs(sample_rates[dsp_config].rate - fs);
|
||||
|
@ -1503,6 +1508,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
|
|||
wm8903_write(codec, WM8903_AUDIO_INTERFACE_1, aif1);
|
||||
wm8903_write(codec, WM8903_AUDIO_INTERFACE_2, aif2);
|
||||
wm8903_write(codec, WM8903_AUDIO_INTERFACE_3, aif3);
|
||||
wm8903_write(codec, WM8903_DAC_DIGITAL_1, dac_digital1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1721,6 +1727,21 @@ static __devexit int wm8903_i2c_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm8903_i2c_suspend(struct i2c_client *client, pm_message_t msg)
|
||||
{
|
||||
return snd_soc_suspend_device(&client->dev);
|
||||
}
|
||||
|
||||
static int wm8903_i2c_resume(struct i2c_client *client)
|
||||
{
|
||||
return snd_soc_resume_device(&client->dev);
|
||||
}
|
||||
#else
|
||||
#define wm8903_i2c_suspend NULL
|
||||
#define wm8903_i2c_resume NULL
|
||||
#endif
|
||||
|
||||
/* i2c codec control layer */
|
||||
static const struct i2c_device_id wm8903_i2c_id[] = {
|
||||
{ "wm8903", 0 },
|
||||
|
@ -1735,6 +1756,8 @@ static struct i2c_driver wm8903_i2c_driver = {
|
|||
},
|
||||
.probe = wm8903_i2c_probe,
|
||||
.remove = __devexit_p(wm8903_i2c_remove),
|
||||
.suspend = wm8903_i2c_suspend,
|
||||
.resume = wm8903_i2c_resume,
|
||||
.id_table = wm8903_i2c_id,
|
||||
};
|
||||
|
||||
|
|
|
@ -916,6 +916,21 @@ static int __devexit wm8940_i2c_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm8940_i2c_suspend(struct i2c_client *client, pm_message_t msg)
|
||||
{
|
||||
return snd_soc_suspend_device(&client->dev);
|
||||
}
|
||||
|
||||
static int wm8940_i2c_resume(struct i2c_client *client)
|
||||
{
|
||||
return snd_soc_resume_device(&client->dev);
|
||||
}
|
||||
#else
|
||||
#define wm8940_i2c_suspend NULL
|
||||
#define wm8940_i2c_resume NULL
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id wm8940_i2c_id[] = {
|
||||
{ "wm8940", 0 },
|
||||
{ }
|
||||
|
@ -929,6 +944,8 @@ static struct i2c_driver wm8940_i2c_driver = {
|
|||
},
|
||||
.probe = wm8940_i2c_probe,
|
||||
.remove = __devexit_p(wm8940_i2c_remove),
|
||||
.suspend = wm8940_i2c_suspend,
|
||||
.resume = wm8940_i2c_resume,
|
||||
.id_table = wm8940_i2c_id,
|
||||
};
|
||||
|
||||
|
|
|
@ -927,6 +927,21 @@ static __devexit int wm8960_i2c_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm8960_i2c_suspend(struct i2c_client *client, pm_message_t msg)
|
||||
{
|
||||
return snd_soc_suspend_device(&client->dev);
|
||||
}
|
||||
|
||||
static int wm8960_i2c_resume(struct i2c_client *client)
|
||||
{
|
||||
return snd_soc_resume_device(&client->dev);
|
||||
}
|
||||
#else
|
||||
#define wm8960_i2c_suspend NULL
|
||||
#define wm8960_i2c_resume NULL
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id wm8960_i2c_id[] = {
|
||||
{ "wm8960", 0 },
|
||||
{ }
|
||||
|
@ -940,6 +955,8 @@ static struct i2c_driver wm8960_i2c_driver = {
|
|||
},
|
||||
.probe = wm8960_i2c_probe,
|
||||
.remove = __devexit_p(wm8960_i2c_remove),
|
||||
.suspend = wm8960_i2c_suspend,
|
||||
.resume = wm8960_i2c_resume,
|
||||
.id_table = wm8960_i2c_id,
|
||||
};
|
||||
|
||||
|
|
1326
sound/soc/codecs/wm8961.c
Normal file
1326
sound/soc/codecs/wm8961.c
Normal file
File diff suppressed because it is too large
Load diff
866
sound/soc/codecs/wm8961.h
Normal file
866
sound/soc/codecs/wm8961.h
Normal file
|
@ -0,0 +1,866 @@
|
|||
/*
|
||||
* wm8961.h -- WM8961 Soc Audio driver
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _WM8961_H
|
||||
#define _WM8961_H
|
||||
|
||||
#include <sound/soc.h>
|
||||
|
||||
extern struct snd_soc_codec_device soc_codec_dev_wm8961;
|
||||
extern struct snd_soc_dai wm8961_dai;
|
||||
|
||||
#define WM8961_BCLK 1
|
||||
#define WM8961_LRCLK 2
|
||||
|
||||
#define WM8961_BCLK_DIV_1 0
|
||||
#define WM8961_BCLK_DIV_1_5 1
|
||||
#define WM8961_BCLK_DIV_2 2
|
||||
#define WM8961_BCLK_DIV_3 3
|
||||
#define WM8961_BCLK_DIV_4 4
|
||||
#define WM8961_BCLK_DIV_5_5 5
|
||||
#define WM8961_BCLK_DIV_6 6
|
||||
#define WM8961_BCLK_DIV_8 7
|
||||
#define WM8961_BCLK_DIV_11 8
|
||||
#define WM8961_BCLK_DIV_12 9
|
||||
#define WM8961_BCLK_DIV_16 10
|
||||
#define WM8961_BCLK_DIV_24 11
|
||||
#define WM8961_BCLK_DIV_32 13
|
||||
|
||||
|
||||
/*
|
||||
* Register values.
|
||||
*/
|
||||
#define WM8961_LEFT_INPUT_VOLUME 0x00
|
||||
#define WM8961_RIGHT_INPUT_VOLUME 0x01
|
||||
#define WM8961_LOUT1_VOLUME 0x02
|
||||
#define WM8961_ROUT1_VOLUME 0x03
|
||||
#define WM8961_CLOCKING1 0x04
|
||||
#define WM8961_ADC_DAC_CONTROL_1 0x05
|
||||
#define WM8961_ADC_DAC_CONTROL_2 0x06
|
||||
#define WM8961_AUDIO_INTERFACE_0 0x07
|
||||
#define WM8961_CLOCKING2 0x08
|
||||
#define WM8961_AUDIO_INTERFACE_1 0x09
|
||||
#define WM8961_LEFT_DAC_VOLUME 0x0A
|
||||
#define WM8961_RIGHT_DAC_VOLUME 0x0B
|
||||
#define WM8961_AUDIO_INTERFACE_2 0x0E
|
||||
#define WM8961_SOFTWARE_RESET 0x0F
|
||||
#define WM8961_ALC1 0x11
|
||||
#define WM8961_ALC2 0x12
|
||||
#define WM8961_ALC3 0x13
|
||||
#define WM8961_NOISE_GATE 0x14
|
||||
#define WM8961_LEFT_ADC_VOLUME 0x15
|
||||
#define WM8961_RIGHT_ADC_VOLUME 0x16
|
||||
#define WM8961_ADDITIONAL_CONTROL_1 0x17
|
||||
#define WM8961_ADDITIONAL_CONTROL_2 0x18
|
||||
#define WM8961_PWR_MGMT_1 0x19
|
||||
#define WM8961_PWR_MGMT_2 0x1A
|
||||
#define WM8961_ADDITIONAL_CONTROL_3 0x1B
|
||||
#define WM8961_ANTI_POP 0x1C
|
||||
#define WM8961_CLOCKING_3 0x1E
|
||||
#define WM8961_ADCL_SIGNAL_PATH 0x20
|
||||
#define WM8961_ADCR_SIGNAL_PATH 0x21
|
||||
#define WM8961_LOUT2_VOLUME 0x28
|
||||
#define WM8961_ROUT2_VOLUME 0x29
|
||||
#define WM8961_PWR_MGMT_3 0x2F
|
||||
#define WM8961_ADDITIONAL_CONTROL_4 0x30
|
||||
#define WM8961_CLASS_D_CONTROL_1 0x31
|
||||
#define WM8961_CLASS_D_CONTROL_2 0x33
|
||||
#define WM8961_CLOCKING_4 0x38
|
||||
#define WM8961_DSP_SIDETONE_0 0x39
|
||||
#define WM8961_DSP_SIDETONE_1 0x3A
|
||||
#define WM8961_DC_SERVO_0 0x3C
|
||||
#define WM8961_DC_SERVO_1 0x3D
|
||||
#define WM8961_DC_SERVO_3 0x3F
|
||||
#define WM8961_DC_SERVO_5 0x41
|
||||
#define WM8961_ANALOGUE_PGA_BIAS 0x44
|
||||
#define WM8961_ANALOGUE_HP_0 0x45
|
||||
#define WM8961_ANALOGUE_HP_2 0x47
|
||||
#define WM8961_CHARGE_PUMP_1 0x48
|
||||
#define WM8961_CHARGE_PUMP_B 0x52
|
||||
#define WM8961_WRITE_SEQUENCER_1 0x57
|
||||
#define WM8961_WRITE_SEQUENCER_2 0x58
|
||||
#define WM8961_WRITE_SEQUENCER_3 0x59
|
||||
#define WM8961_WRITE_SEQUENCER_4 0x5A
|
||||
#define WM8961_WRITE_SEQUENCER_5 0x5B
|
||||
#define WM8961_WRITE_SEQUENCER_6 0x5C
|
||||
#define WM8961_WRITE_SEQUENCER_7 0x5D
|
||||
#define WM8961_GENERAL_TEST_1 0xFC
|
||||
|
||||
|
||||
/*
|
||||
* Field Definitions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* R0 (0x00) - Left Input volume
|
||||
*/
|
||||
#define WM8961_IPVU 0x0100 /* IPVU */
|
||||
#define WM8961_IPVU_MASK 0x0100 /* IPVU */
|
||||
#define WM8961_IPVU_SHIFT 8 /* IPVU */
|
||||
#define WM8961_IPVU_WIDTH 1 /* IPVU */
|
||||
#define WM8961_LINMUTE 0x0080 /* LINMUTE */
|
||||
#define WM8961_LINMUTE_MASK 0x0080 /* LINMUTE */
|
||||
#define WM8961_LINMUTE_SHIFT 7 /* LINMUTE */
|
||||
#define WM8961_LINMUTE_WIDTH 1 /* LINMUTE */
|
||||
#define WM8961_LIZC 0x0040 /* LIZC */
|
||||
#define WM8961_LIZC_MASK 0x0040 /* LIZC */
|
||||
#define WM8961_LIZC_SHIFT 6 /* LIZC */
|
||||
#define WM8961_LIZC_WIDTH 1 /* LIZC */
|
||||
#define WM8961_LINVOL_MASK 0x003F /* LINVOL - [5:0] */
|
||||
#define WM8961_LINVOL_SHIFT 0 /* LINVOL - [5:0] */
|
||||
#define WM8961_LINVOL_WIDTH 6 /* LINVOL - [5:0] */
|
||||
|
||||
/*
|
||||
* R1 (0x01) - Right Input volume
|
||||
*/
|
||||
#define WM8961_DEVICE_ID_MASK 0xF000 /* DEVICE_ID - [15:12] */
|
||||
#define WM8961_DEVICE_ID_SHIFT 12 /* DEVICE_ID - [15:12] */
|
||||
#define WM8961_DEVICE_ID_WIDTH 4 /* DEVICE_ID - [15:12] */
|
||||
#define WM8961_CHIP_REV_MASK 0x0E00 /* CHIP_REV - [11:9] */
|
||||
#define WM8961_CHIP_REV_SHIFT 9 /* CHIP_REV - [11:9] */
|
||||
#define WM8961_CHIP_REV_WIDTH 3 /* CHIP_REV - [11:9] */
|
||||
#define WM8961_IPVU 0x0100 /* IPVU */
|
||||
#define WM8961_IPVU_MASK 0x0100 /* IPVU */
|
||||
#define WM8961_IPVU_SHIFT 8 /* IPVU */
|
||||
#define WM8961_IPVU_WIDTH 1 /* IPVU */
|
||||
#define WM8961_RINMUTE 0x0080 /* RINMUTE */
|
||||
#define WM8961_RINMUTE_MASK 0x0080 /* RINMUTE */
|
||||
#define WM8961_RINMUTE_SHIFT 7 /* RINMUTE */
|
||||
#define WM8961_RINMUTE_WIDTH 1 /* RINMUTE */
|
||||
#define WM8961_RIZC 0x0040 /* RIZC */
|
||||
#define WM8961_RIZC_MASK 0x0040 /* RIZC */
|
||||
#define WM8961_RIZC_SHIFT 6 /* RIZC */
|
||||
#define WM8961_RIZC_WIDTH 1 /* RIZC */
|
||||
#define WM8961_RINVOL_MASK 0x003F /* RINVOL - [5:0] */
|
||||
#define WM8961_RINVOL_SHIFT 0 /* RINVOL - [5:0] */
|
||||
#define WM8961_RINVOL_WIDTH 6 /* RINVOL - [5:0] */
|
||||
|
||||
/*
|
||||
* R2 (0x02) - LOUT1 volume
|
||||
*/
|
||||
#define WM8961_OUT1VU 0x0100 /* OUT1VU */
|
||||
#define WM8961_OUT1VU_MASK 0x0100 /* OUT1VU */
|
||||
#define WM8961_OUT1VU_SHIFT 8 /* OUT1VU */
|
||||
#define WM8961_OUT1VU_WIDTH 1 /* OUT1VU */
|
||||
#define WM8961_LO1ZC 0x0080 /* LO1ZC */
|
||||
#define WM8961_LO1ZC_MASK 0x0080 /* LO1ZC */
|
||||
#define WM8961_LO1ZC_SHIFT 7 /* LO1ZC */
|
||||
#define WM8961_LO1ZC_WIDTH 1 /* LO1ZC */
|
||||
#define WM8961_LOUT1VOL_MASK 0x007F /* LOUT1VOL - [6:0] */
|
||||
#define WM8961_LOUT1VOL_SHIFT 0 /* LOUT1VOL - [6:0] */
|
||||
#define WM8961_LOUT1VOL_WIDTH 7 /* LOUT1VOL - [6:0] */
|
||||
|
||||
/*
|
||||
* R3 (0x03) - ROUT1 volume
|
||||
*/
|
||||
#define WM8961_OUT1VU 0x0100 /* OUT1VU */
|
||||
#define WM8961_OUT1VU_MASK 0x0100 /* OUT1VU */
|
||||
#define WM8961_OUT1VU_SHIFT 8 /* OUT1VU */
|
||||
#define WM8961_OUT1VU_WIDTH 1 /* OUT1VU */
|
||||
#define WM8961_RO1ZC 0x0080 /* RO1ZC */
|
||||
#define WM8961_RO1ZC_MASK 0x0080 /* RO1ZC */
|
||||
#define WM8961_RO1ZC_SHIFT 7 /* RO1ZC */
|
||||
#define WM8961_RO1ZC_WIDTH 1 /* RO1ZC */
|
||||
#define WM8961_ROUT1VOL_MASK 0x007F /* ROUT1VOL - [6:0] */
|
||||
#define WM8961_ROUT1VOL_SHIFT 0 /* ROUT1VOL - [6:0] */
|
||||
#define WM8961_ROUT1VOL_WIDTH 7 /* ROUT1VOL - [6:0] */
|
||||
|
||||
/*
|
||||
* R4 (0x04) - Clocking1
|
||||
*/
|
||||
#define WM8961_ADCDIV_MASK 0x01C0 /* ADCDIV - [8:6] */
|
||||
#define WM8961_ADCDIV_SHIFT 6 /* ADCDIV - [8:6] */
|
||||
#define WM8961_ADCDIV_WIDTH 3 /* ADCDIV - [8:6] */
|
||||
#define WM8961_DACDIV_MASK 0x0038 /* DACDIV - [5:3] */
|
||||
#define WM8961_DACDIV_SHIFT 3 /* DACDIV - [5:3] */
|
||||
#define WM8961_DACDIV_WIDTH 3 /* DACDIV - [5:3] */
|
||||
#define WM8961_MCLKDIV 0x0004 /* MCLKDIV */
|
||||
#define WM8961_MCLKDIV_MASK 0x0004 /* MCLKDIV */
|
||||
#define WM8961_MCLKDIV_SHIFT 2 /* MCLKDIV */
|
||||
#define WM8961_MCLKDIV_WIDTH 1 /* MCLKDIV */
|
||||
|
||||
/*
|
||||
* R5 (0x05) - ADC & DAC Control 1
|
||||
*/
|
||||
#define WM8961_ADCPOL_MASK 0x0060 /* ADCPOL - [6:5] */
|
||||
#define WM8961_ADCPOL_SHIFT 5 /* ADCPOL - [6:5] */
|
||||
#define WM8961_ADCPOL_WIDTH 2 /* ADCPOL - [6:5] */
|
||||
#define WM8961_DACMU 0x0008 /* DACMU */
|
||||
#define WM8961_DACMU_MASK 0x0008 /* DACMU */
|
||||
#define WM8961_DACMU_SHIFT 3 /* DACMU */
|
||||
#define WM8961_DACMU_WIDTH 1 /* DACMU */
|
||||
#define WM8961_DEEMPH_MASK 0x0006 /* DEEMPH - [2:1] */
|
||||
#define WM8961_DEEMPH_SHIFT 1 /* DEEMPH - [2:1] */
|
||||
#define WM8961_DEEMPH_WIDTH 2 /* DEEMPH - [2:1] */
|
||||
#define WM8961_ADCHPD 0x0001 /* ADCHPD */
|
||||
#define WM8961_ADCHPD_MASK 0x0001 /* ADCHPD */
|
||||
#define WM8961_ADCHPD_SHIFT 0 /* ADCHPD */
|
||||
#define WM8961_ADCHPD_WIDTH 1 /* ADCHPD */
|
||||
|
||||
/*
|
||||
* R6 (0x06) - ADC & DAC Control 2
|
||||
*/
|
||||
#define WM8961_ADC_HPF_CUT_MASK 0x0180 /* ADC_HPF_CUT - [8:7] */
|
||||
#define WM8961_ADC_HPF_CUT_SHIFT 7 /* ADC_HPF_CUT - [8:7] */
|
||||
#define WM8961_ADC_HPF_CUT_WIDTH 2 /* ADC_HPF_CUT - [8:7] */
|
||||
#define WM8961_DACPOL_MASK 0x0060 /* DACPOL - [6:5] */
|
||||
#define WM8961_DACPOL_SHIFT 5 /* DACPOL - [6:5] */
|
||||
#define WM8961_DACPOL_WIDTH 2 /* DACPOL - [6:5] */
|
||||
#define WM8961_DACSMM 0x0008 /* DACSMM */
|
||||
#define WM8961_DACSMM_MASK 0x0008 /* DACSMM */
|
||||
#define WM8961_DACSMM_SHIFT 3 /* DACSMM */
|
||||
#define WM8961_DACSMM_WIDTH 1 /* DACSMM */
|
||||
#define WM8961_DACMR 0x0004 /* DACMR */
|
||||
#define WM8961_DACMR_MASK 0x0004 /* DACMR */
|
||||
#define WM8961_DACMR_SHIFT 2 /* DACMR */
|
||||
#define WM8961_DACMR_WIDTH 1 /* DACMR */
|
||||
#define WM8961_DACSLOPE 0x0002 /* DACSLOPE */
|
||||
#define WM8961_DACSLOPE_MASK 0x0002 /* DACSLOPE */
|
||||
#define WM8961_DACSLOPE_SHIFT 1 /* DACSLOPE */
|
||||
#define WM8961_DACSLOPE_WIDTH 1 /* DACSLOPE */
|
||||
#define WM8961_DAC_OSR128 0x0001 /* DAC_OSR128 */
|
||||
#define WM8961_DAC_OSR128_MASK 0x0001 /* DAC_OSR128 */
|
||||
#define WM8961_DAC_OSR128_SHIFT 0 /* DAC_OSR128 */
|
||||
#define WM8961_DAC_OSR128_WIDTH 1 /* DAC_OSR128 */
|
||||
|
||||
/*
|
||||
* R7 (0x07) - Audio Interface 0
|
||||
*/
|
||||
#define WM8961_ALRSWAP 0x0100 /* ALRSWAP */
|
||||
#define WM8961_ALRSWAP_MASK 0x0100 /* ALRSWAP */
|
||||
#define WM8961_ALRSWAP_SHIFT 8 /* ALRSWAP */
|
||||
#define WM8961_ALRSWAP_WIDTH 1 /* ALRSWAP */
|
||||
#define WM8961_BCLKINV 0x0080 /* BCLKINV */
|
||||
#define WM8961_BCLKINV_MASK 0x0080 /* BCLKINV */
|
||||
#define WM8961_BCLKINV_SHIFT 7 /* BCLKINV */
|
||||
#define WM8961_BCLKINV_WIDTH 1 /* BCLKINV */
|
||||
#define WM8961_MS 0x0040 /* MS */
|
||||
#define WM8961_MS_MASK 0x0040 /* MS */
|
||||
#define WM8961_MS_SHIFT 6 /* MS */
|
||||
#define WM8961_MS_WIDTH 1 /* MS */
|
||||
#define WM8961_DLRSWAP 0x0020 /* DLRSWAP */
|
||||
#define WM8961_DLRSWAP_MASK 0x0020 /* DLRSWAP */
|
||||
#define WM8961_DLRSWAP_SHIFT 5 /* DLRSWAP */
|
||||
#define WM8961_DLRSWAP_WIDTH 1 /* DLRSWAP */
|
||||
#define WM8961_LRP 0x0010 /* LRP */
|
||||
#define WM8961_LRP_MASK 0x0010 /* LRP */
|
||||
#define WM8961_LRP_SHIFT 4 /* LRP */
|
||||
#define WM8961_LRP_WIDTH 1 /* LRP */
|
||||
#define WM8961_WL_MASK 0x000C /* WL - [3:2] */
|
||||
#define WM8961_WL_SHIFT 2 /* WL - [3:2] */
|
||||
#define WM8961_WL_WIDTH 2 /* WL - [3:2] */
|
||||
#define WM8961_FORMAT_MASK 0x0003 /* FORMAT - [1:0] */
|
||||
#define WM8961_FORMAT_SHIFT 0 /* FORMAT - [1:0] */
|
||||
#define WM8961_FORMAT_WIDTH 2 /* FORMAT - [1:0] */
|
||||
|
||||
/*
|
||||
* R8 (0x08) - Clocking2
|
||||
*/
|
||||
#define WM8961_DCLKDIV_MASK 0x01C0 /* DCLKDIV - [8:6] */
|
||||
#define WM8961_DCLKDIV_SHIFT 6 /* DCLKDIV - [8:6] */
|
||||
#define WM8961_DCLKDIV_WIDTH 3 /* DCLKDIV - [8:6] */
|
||||
#define WM8961_CLK_SYS_ENA 0x0020 /* CLK_SYS_ENA */
|
||||
#define WM8961_CLK_SYS_ENA_MASK 0x0020 /* CLK_SYS_ENA */
|
||||
#define WM8961_CLK_SYS_ENA_SHIFT 5 /* CLK_SYS_ENA */
|
||||
#define WM8961_CLK_SYS_ENA_WIDTH 1 /* CLK_SYS_ENA */
|
||||
#define WM8961_CLK_DSP_ENA 0x0010 /* CLK_DSP_ENA */
|
||||
#define WM8961_CLK_DSP_ENA_MASK 0x0010 /* CLK_DSP_ENA */
|
||||
#define WM8961_CLK_DSP_ENA_SHIFT 4 /* CLK_DSP_ENA */
|
||||
#define WM8961_CLK_DSP_ENA_WIDTH 1 /* CLK_DSP_ENA */
|
||||
#define WM8961_BCLKDIV_MASK 0x000F /* BCLKDIV - [3:0] */
|
||||
#define WM8961_BCLKDIV_SHIFT 0 /* BCLKDIV - [3:0] */
|
||||
#define WM8961_BCLKDIV_WIDTH 4 /* BCLKDIV - [3:0] */
|
||||
|
||||
/*
|
||||
* R9 (0x09) - Audio Interface 1
|
||||
*/
|
||||
#define WM8961_DACCOMP_MASK 0x0018 /* DACCOMP - [4:3] */
|
||||
#define WM8961_DACCOMP_SHIFT 3 /* DACCOMP - [4:3] */
|
||||
#define WM8961_DACCOMP_WIDTH 2 /* DACCOMP - [4:3] */
|
||||
#define WM8961_ADCCOMP_MASK 0x0006 /* ADCCOMP - [2:1] */
|
||||
#define WM8961_ADCCOMP_SHIFT 1 /* ADCCOMP - [2:1] */
|
||||
#define WM8961_ADCCOMP_WIDTH 2 /* ADCCOMP - [2:1] */
|
||||
#define WM8961_LOOPBACK 0x0001 /* LOOPBACK */
|
||||
#define WM8961_LOOPBACK_MASK 0x0001 /* LOOPBACK */
|
||||
#define WM8961_LOOPBACK_SHIFT 0 /* LOOPBACK */
|
||||
#define WM8961_LOOPBACK_WIDTH 1 /* LOOPBACK */
|
||||
|
||||
/*
|
||||
* R10 (0x0A) - Left DAC volume
|
||||
*/
|
||||
#define WM8961_DACVU 0x0100 /* DACVU */
|
||||
#define WM8961_DACVU_MASK 0x0100 /* DACVU */
|
||||
#define WM8961_DACVU_SHIFT 8 /* DACVU */
|
||||
#define WM8961_DACVU_WIDTH 1 /* DACVU */
|
||||
#define WM8961_LDACVOL_MASK 0x00FF /* LDACVOL - [7:0] */
|
||||
#define WM8961_LDACVOL_SHIFT 0 /* LDACVOL - [7:0] */
|
||||
#define WM8961_LDACVOL_WIDTH 8 /* LDACVOL - [7:0] */
|
||||
|
||||
/*
|
||||
* R11 (0x0B) - Right DAC volume
|
||||
*/
|
||||
#define WM8961_DACVU 0x0100 /* DACVU */
|
||||
#define WM8961_DACVU_MASK 0x0100 /* DACVU */
|
||||
#define WM8961_DACVU_SHIFT 8 /* DACVU */
|
||||
#define WM8961_DACVU_WIDTH 1 /* DACVU */
|
||||
#define WM8961_RDACVOL_MASK 0x00FF /* RDACVOL - [7:0] */
|
||||
#define WM8961_RDACVOL_SHIFT 0 /* RDACVOL - [7:0] */
|
||||
#define WM8961_RDACVOL_WIDTH 8 /* RDACVOL - [7:0] */
|
||||
|
||||
/*
|
||||
* R14 (0x0E) - Audio Interface 2
|
||||
*/
|
||||
#define WM8961_LRCLK_RATE_MASK 0x01FF /* LRCLK_RATE - [8:0] */
|
||||
#define WM8961_LRCLK_RATE_SHIFT 0 /* LRCLK_RATE - [8:0] */
|
||||
#define WM8961_LRCLK_RATE_WIDTH 9 /* LRCLK_RATE - [8:0] */
|
||||
|
||||
/*
|
||||
* R15 (0x0F) - Software Reset
|
||||
*/
|
||||
#define WM8961_SW_RST_DEV_ID1_MASK 0xFFFF /* SW_RST_DEV_ID1 - [15:0] */
|
||||
#define WM8961_SW_RST_DEV_ID1_SHIFT 0 /* SW_RST_DEV_ID1 - [15:0] */
|
||||
#define WM8961_SW_RST_DEV_ID1_WIDTH 16 /* SW_RST_DEV_ID1 - [15:0] */
|
||||
|
||||
/*
|
||||
* R17 (0x11) - ALC1
|
||||
*/
|
||||
#define WM8961_ALCSEL_MASK 0x0180 /* ALCSEL - [8:7] */
|
||||
#define WM8961_ALCSEL_SHIFT 7 /* ALCSEL - [8:7] */
|
||||
#define WM8961_ALCSEL_WIDTH 2 /* ALCSEL - [8:7] */
|
||||
#define WM8961_MAXGAIN_MASK 0x0070 /* MAXGAIN - [6:4] */
|
||||
#define WM8961_MAXGAIN_SHIFT 4 /* MAXGAIN - [6:4] */
|
||||
#define WM8961_MAXGAIN_WIDTH 3 /* MAXGAIN - [6:4] */
|
||||
#define WM8961_ALCL_MASK 0x000F /* ALCL - [3:0] */
|
||||
#define WM8961_ALCL_SHIFT 0 /* ALCL - [3:0] */
|
||||
#define WM8961_ALCL_WIDTH 4 /* ALCL - [3:0] */
|
||||
|
||||
/*
|
||||
* R18 (0x12) - ALC2
|
||||
*/
|
||||
#define WM8961_ALCZC 0x0080 /* ALCZC */
|
||||
#define WM8961_ALCZC_MASK 0x0080 /* ALCZC */
|
||||
#define WM8961_ALCZC_SHIFT 7 /* ALCZC */
|
||||
#define WM8961_ALCZC_WIDTH 1 /* ALCZC */
|
||||
#define WM8961_MINGAIN_MASK 0x0070 /* MINGAIN - [6:4] */
|
||||
#define WM8961_MINGAIN_SHIFT 4 /* MINGAIN - [6:4] */
|
||||
#define WM8961_MINGAIN_WIDTH 3 /* MINGAIN - [6:4] */
|
||||
#define WM8961_HLD_MASK 0x000F /* HLD - [3:0] */
|
||||
#define WM8961_HLD_SHIFT 0 /* HLD - [3:0] */
|
||||
#define WM8961_HLD_WIDTH 4 /* HLD - [3:0] */
|
||||
|
||||
/*
|
||||
* R19 (0x13) - ALC3
|
||||
*/
|
||||
#define WM8961_ALCMODE 0x0100 /* ALCMODE */
|
||||
#define WM8961_ALCMODE_MASK 0x0100 /* ALCMODE */
|
||||
#define WM8961_ALCMODE_SHIFT 8 /* ALCMODE */
|
||||
#define WM8961_ALCMODE_WIDTH 1 /* ALCMODE */
|
||||
#define WM8961_DCY_MASK 0x00F0 /* DCY - [7:4] */
|
||||
#define WM8961_DCY_SHIFT 4 /* DCY - [7:4] */
|
||||
#define WM8961_DCY_WIDTH 4 /* DCY - [7:4] */
|
||||
#define WM8961_ATK_MASK 0x000F /* ATK - [3:0] */
|
||||
#define WM8961_ATK_SHIFT 0 /* ATK - [3:0] */
|
||||
#define WM8961_ATK_WIDTH 4 /* ATK - [3:0] */
|
||||
|
||||
/*
|
||||
* R20 (0x14) - Noise Gate
|
||||
*/
|
||||
#define WM8961_NGTH_MASK 0x00F8 /* NGTH - [7:3] */
|
||||
#define WM8961_NGTH_SHIFT 3 /* NGTH - [7:3] */
|
||||
#define WM8961_NGTH_WIDTH 5 /* NGTH - [7:3] */
|
||||
#define WM8961_NGG 0x0002 /* NGG */
|
||||
#define WM8961_NGG_MASK 0x0002 /* NGG */
|
||||
#define WM8961_NGG_SHIFT 1 /* NGG */
|
||||
#define WM8961_NGG_WIDTH 1 /* NGG */
|
||||
#define WM8961_NGAT 0x0001 /* NGAT */
|
||||
#define WM8961_NGAT_MASK 0x0001 /* NGAT */
|
||||
#define WM8961_NGAT_SHIFT 0 /* NGAT */
|
||||
#define WM8961_NGAT_WIDTH 1 /* NGAT */
|
||||
|
||||
/*
|
||||
* R21 (0x15) - Left ADC volume
|
||||
*/
|
||||
#define WM8961_ADCVU 0x0100 /* ADCVU */
|
||||
#define WM8961_ADCVU_MASK 0x0100 /* ADCVU */
|
||||
#define WM8961_ADCVU_SHIFT 8 /* ADCVU */
|
||||
#define WM8961_ADCVU_WIDTH 1 /* ADCVU */
|
||||
#define WM8961_LADCVOL_MASK 0x00FF /* LADCVOL - [7:0] */
|
||||
#define WM8961_LADCVOL_SHIFT 0 /* LADCVOL - [7:0] */
|
||||
#define WM8961_LADCVOL_WIDTH 8 /* LADCVOL - [7:0] */
|
||||
|
||||
/*
|
||||
* R22 (0x16) - Right ADC volume
|
||||
*/
|
||||
#define WM8961_ADCVU 0x0100 /* ADCVU */
|
||||
#define WM8961_ADCVU_MASK 0x0100 /* ADCVU */
|
||||
#define WM8961_ADCVU_SHIFT 8 /* ADCVU */
|
||||
#define WM8961_ADCVU_WIDTH 1 /* ADCVU */
|
||||
#define WM8961_RADCVOL_MASK 0x00FF /* RADCVOL - [7:0] */
|
||||
#define WM8961_RADCVOL_SHIFT 0 /* RADCVOL - [7:0] */
|
||||
#define WM8961_RADCVOL_WIDTH 8 /* RADCVOL - [7:0] */
|
||||
|
||||
/*
|
||||
* R23 (0x17) - Additional control(1)
|
||||
*/
|
||||
#define WM8961_TSDEN 0x0100 /* TSDEN */
|
||||
#define WM8961_TSDEN_MASK 0x0100 /* TSDEN */
|
||||
#define WM8961_TSDEN_SHIFT 8 /* TSDEN */
|
||||
#define WM8961_TSDEN_WIDTH 1 /* TSDEN */
|
||||
#define WM8961_DMONOMIX 0x0010 /* DMONOMIX */
|
||||
#define WM8961_DMONOMIX_MASK 0x0010 /* DMONOMIX */
|
||||
#define WM8961_DMONOMIX_SHIFT 4 /* DMONOMIX */
|
||||
#define WM8961_DMONOMIX_WIDTH 1 /* DMONOMIX */
|
||||
#define WM8961_TOEN 0x0001 /* TOEN */
|
||||
#define WM8961_TOEN_MASK 0x0001 /* TOEN */
|
||||
#define WM8961_TOEN_SHIFT 0 /* TOEN */
|
||||
#define WM8961_TOEN_WIDTH 1 /* TOEN */
|
||||
|
||||
/*
|
||||
* R24 (0x18) - Additional control(2)
|
||||
*/
|
||||
#define WM8961_TRIS 0x0008 /* TRIS */
|
||||
#define WM8961_TRIS_MASK 0x0008 /* TRIS */
|
||||
#define WM8961_TRIS_SHIFT 3 /* TRIS */
|
||||
#define WM8961_TRIS_WIDTH 1 /* TRIS */
|
||||
|
||||
/*
|
||||
* R25 (0x19) - Pwr Mgmt (1)
|
||||
*/
|
||||
#define WM8961_VMIDSEL_MASK 0x0180 /* VMIDSEL - [8:7] */
|
||||
#define WM8961_VMIDSEL_SHIFT 7 /* VMIDSEL - [8:7] */
|
||||
#define WM8961_VMIDSEL_WIDTH 2 /* VMIDSEL - [8:7] */
|
||||
#define WM8961_VREF 0x0040 /* VREF */
|
||||
#define WM8961_VREF_MASK 0x0040 /* VREF */
|
||||
#define WM8961_VREF_SHIFT 6 /* VREF */
|
||||
#define WM8961_VREF_WIDTH 1 /* VREF */
|
||||
#define WM8961_AINL 0x0020 /* AINL */
|
||||
#define WM8961_AINL_MASK 0x0020 /* AINL */
|
||||
#define WM8961_AINL_SHIFT 5 /* AINL */
|
||||
#define WM8961_AINL_WIDTH 1 /* AINL */
|
||||
#define WM8961_AINR 0x0010 /* AINR */
|
||||
#define WM8961_AINR_MASK 0x0010 /* AINR */
|
||||
#define WM8961_AINR_SHIFT 4 /* AINR */
|
||||
#define WM8961_AINR_WIDTH 1 /* AINR */
|
||||
#define WM8961_ADCL 0x0008 /* ADCL */
|
||||
#define WM8961_ADCL_MASK 0x0008 /* ADCL */
|
||||
#define WM8961_ADCL_SHIFT 3 /* ADCL */
|
||||
#define WM8961_ADCL_WIDTH 1 /* ADCL */
|
||||
#define WM8961_ADCR 0x0004 /* ADCR */
|
||||
#define WM8961_ADCR_MASK 0x0004 /* ADCR */
|
||||
#define WM8961_ADCR_SHIFT 2 /* ADCR */
|
||||
#define WM8961_ADCR_WIDTH 1 /* ADCR */
|
||||
#define WM8961_MICB 0x0002 /* MICB */
|
||||
#define WM8961_MICB_MASK 0x0002 /* MICB */
|
||||
#define WM8961_MICB_SHIFT 1 /* MICB */
|
||||
#define WM8961_MICB_WIDTH 1 /* MICB */
|
||||
|
||||
/*
|
||||
* R26 (0x1A) - Pwr Mgmt (2)
|
||||
*/
|
||||
#define WM8961_DACL 0x0100 /* DACL */
|
||||
#define WM8961_DACL_MASK 0x0100 /* DACL */
|
||||
#define WM8961_DACL_SHIFT 8 /* DACL */
|
||||
#define WM8961_DACL_WIDTH 1 /* DACL */
|
||||
#define WM8961_DACR 0x0080 /* DACR */
|
||||
#define WM8961_DACR_MASK 0x0080 /* DACR */
|
||||
#define WM8961_DACR_SHIFT 7 /* DACR */
|
||||
#define WM8961_DACR_WIDTH 1 /* DACR */
|
||||
#define WM8961_LOUT1_PGA 0x0040 /* LOUT1_PGA */
|
||||
#define WM8961_LOUT1_PGA_MASK 0x0040 /* LOUT1_PGA */
|
||||
#define WM8961_LOUT1_PGA_SHIFT 6 /* LOUT1_PGA */
|
||||
#define WM8961_LOUT1_PGA_WIDTH 1 /* LOUT1_PGA */
|
||||
#define WM8961_ROUT1_PGA 0x0020 /* ROUT1_PGA */
|
||||
#define WM8961_ROUT1_PGA_MASK 0x0020 /* ROUT1_PGA */
|
||||
#define WM8961_ROUT1_PGA_SHIFT 5 /* ROUT1_PGA */
|
||||
#define WM8961_ROUT1_PGA_WIDTH 1 /* ROUT1_PGA */
|
||||
#define WM8961_SPKL_PGA 0x0010 /* SPKL_PGA */
|
||||
#define WM8961_SPKL_PGA_MASK 0x0010 /* SPKL_PGA */
|
||||
#define WM8961_SPKL_PGA_SHIFT 4 /* SPKL_PGA */
|
||||
#define WM8961_SPKL_PGA_WIDTH 1 /* SPKL_PGA */
|
||||
#define WM8961_SPKR_PGA 0x0008 /* SPKR_PGA */
|
||||
#define WM8961_SPKR_PGA_MASK 0x0008 /* SPKR_PGA */
|
||||
#define WM8961_SPKR_PGA_SHIFT 3 /* SPKR_PGA */
|
||||
#define WM8961_SPKR_PGA_WIDTH 1 /* SPKR_PGA */
|
||||
|
||||
/*
|
||||
* R27 (0x1B) - Additional Control (3)
|
||||
*/
|
||||
#define WM8961_SAMPLE_RATE_MASK 0x0007 /* SAMPLE_RATE - [2:0] */
|
||||
#define WM8961_SAMPLE_RATE_SHIFT 0 /* SAMPLE_RATE - [2:0] */
|
||||
#define WM8961_SAMPLE_RATE_WIDTH 3 /* SAMPLE_RATE - [2:0] */
|
||||
|
||||
/*
|
||||
* R28 (0x1C) - Anti-pop
|
||||
*/
|
||||
#define WM8961_BUFDCOPEN 0x0010 /* BUFDCOPEN */
|
||||
#define WM8961_BUFDCOPEN_MASK 0x0010 /* BUFDCOPEN */
|
||||
#define WM8961_BUFDCOPEN_SHIFT 4 /* BUFDCOPEN */
|
||||
#define WM8961_BUFDCOPEN_WIDTH 1 /* BUFDCOPEN */
|
||||
#define WM8961_BUFIOEN 0x0008 /* BUFIOEN */
|
||||
#define WM8961_BUFIOEN_MASK 0x0008 /* BUFIOEN */
|
||||
#define WM8961_BUFIOEN_SHIFT 3 /* BUFIOEN */
|
||||
#define WM8961_BUFIOEN_WIDTH 1 /* BUFIOEN */
|
||||
#define WM8961_SOFT_ST 0x0004 /* SOFT_ST */
|
||||
#define WM8961_SOFT_ST_MASK 0x0004 /* SOFT_ST */
|
||||
#define WM8961_SOFT_ST_SHIFT 2 /* SOFT_ST */
|
||||
#define WM8961_SOFT_ST_WIDTH 1 /* SOFT_ST */
|
||||
|
||||
/*
|
||||
* R30 (0x1E) - Clocking 3
|
||||
*/
|
||||
#define WM8961_CLK_TO_DIV_MASK 0x0180 /* CLK_TO_DIV - [8:7] */
|
||||
#define WM8961_CLK_TO_DIV_SHIFT 7 /* CLK_TO_DIV - [8:7] */
|
||||
#define WM8961_CLK_TO_DIV_WIDTH 2 /* CLK_TO_DIV - [8:7] */
|
||||
#define WM8961_CLK_256K_DIV_MASK 0x007E /* CLK_256K_DIV - [6:1] */
|
||||
#define WM8961_CLK_256K_DIV_SHIFT 1 /* CLK_256K_DIV - [6:1] */
|
||||
#define WM8961_CLK_256K_DIV_WIDTH 6 /* CLK_256K_DIV - [6:1] */
|
||||
#define WM8961_MANUAL_MODE 0x0001 /* MANUAL_MODE */
|
||||
#define WM8961_MANUAL_MODE_MASK 0x0001 /* MANUAL_MODE */
|
||||
#define WM8961_MANUAL_MODE_SHIFT 0 /* MANUAL_MODE */
|
||||
#define WM8961_MANUAL_MODE_WIDTH 1 /* MANUAL_MODE */
|
||||
|
||||
/*
|
||||
* R32 (0x20) - ADCL signal path
|
||||
*/
|
||||
#define WM8961_LMICBOOST_MASK 0x0030 /* LMICBOOST - [5:4] */
|
||||
#define WM8961_LMICBOOST_SHIFT 4 /* LMICBOOST - [5:4] */
|
||||
#define WM8961_LMICBOOST_WIDTH 2 /* LMICBOOST - [5:4] */
|
||||
|
||||
/*
|
||||
* R33 (0x21) - ADCR signal path
|
||||
*/
|
||||
#define WM8961_RMICBOOST_MASK 0x0030 /* RMICBOOST - [5:4] */
|
||||
#define WM8961_RMICBOOST_SHIFT 4 /* RMICBOOST - [5:4] */
|
||||
#define WM8961_RMICBOOST_WIDTH 2 /* RMICBOOST - [5:4] */
|
||||
|
||||
/*
|
||||
* R40 (0x28) - LOUT2 volume
|
||||
*/
|
||||
#define WM8961_SPKVU 0x0100 /* SPKVU */
|
||||
#define WM8961_SPKVU_MASK 0x0100 /* SPKVU */
|
||||
#define WM8961_SPKVU_SHIFT 8 /* SPKVU */
|
||||
#define WM8961_SPKVU_WIDTH 1 /* SPKVU */
|
||||
#define WM8961_SPKLZC 0x0080 /* SPKLZC */
|
||||
#define WM8961_SPKLZC_MASK 0x0080 /* SPKLZC */
|
||||
#define WM8961_SPKLZC_SHIFT 7 /* SPKLZC */
|
||||
#define WM8961_SPKLZC_WIDTH 1 /* SPKLZC */
|
||||
#define WM8961_SPKLVOL_MASK 0x007F /* SPKLVOL - [6:0] */
|
||||
#define WM8961_SPKLVOL_SHIFT 0 /* SPKLVOL - [6:0] */
|
||||
#define WM8961_SPKLVOL_WIDTH 7 /* SPKLVOL - [6:0] */
|
||||
|
||||
/*
|
||||
* R41 (0x29) - ROUT2 volume
|
||||
*/
|
||||
#define WM8961_SPKVU 0x0100 /* SPKVU */
|
||||
#define WM8961_SPKVU_MASK 0x0100 /* SPKVU */
|
||||
#define WM8961_SPKVU_SHIFT 8 /* SPKVU */
|
||||
#define WM8961_SPKVU_WIDTH 1 /* SPKVU */
|
||||
#define WM8961_SPKRZC 0x0080 /* SPKRZC */
|
||||
#define WM8961_SPKRZC_MASK 0x0080 /* SPKRZC */
|
||||
#define WM8961_SPKRZC_SHIFT 7 /* SPKRZC */
|
||||
#define WM8961_SPKRZC_WIDTH 1 /* SPKRZC */
|
||||
#define WM8961_SPKRVOL_MASK 0x007F /* SPKRVOL - [6:0] */
|
||||
#define WM8961_SPKRVOL_SHIFT 0 /* SPKRVOL - [6:0] */
|
||||
#define WM8961_SPKRVOL_WIDTH 7 /* SPKRVOL - [6:0] */
|
||||
|
||||
/*
|
||||
* R47 (0x2F) - Pwr Mgmt (3)
|
||||
*/
|
||||
#define WM8961_TEMP_SHUT 0x0002 /* TEMP_SHUT */
|
||||
#define WM8961_TEMP_SHUT_MASK 0x0002 /* TEMP_SHUT */
|
||||
#define WM8961_TEMP_SHUT_SHIFT 1 /* TEMP_SHUT */
|
||||
#define WM8961_TEMP_SHUT_WIDTH 1 /* TEMP_SHUT */
|
||||
#define WM8961_TEMP_WARN 0x0001 /* TEMP_WARN */
|
||||
#define WM8961_TEMP_WARN_MASK 0x0001 /* TEMP_WARN */
|
||||
#define WM8961_TEMP_WARN_SHIFT 0 /* TEMP_WARN */
|
||||
#define WM8961_TEMP_WARN_WIDTH 1 /* TEMP_WARN */
|
||||
|
||||
/*
|
||||
* R48 (0x30) - Additional Control (4)
|
||||
*/
|
||||
#define WM8961_TSENSEN 0x0002 /* TSENSEN */
|
||||
#define WM8961_TSENSEN_MASK 0x0002 /* TSENSEN */
|
||||
#define WM8961_TSENSEN_SHIFT 1 /* TSENSEN */
|
||||
#define WM8961_TSENSEN_WIDTH 1 /* TSENSEN */
|
||||
#define WM8961_MBSEL 0x0001 /* MBSEL */
|
||||
#define WM8961_MBSEL_MASK 0x0001 /* MBSEL */
|
||||
#define WM8961_MBSEL_SHIFT 0 /* MBSEL */
|
||||
#define WM8961_MBSEL_WIDTH 1 /* MBSEL */
|
||||
|
||||
/*
|
||||
* R49 (0x31) - Class D Control 1
|
||||
*/
|
||||
#define WM8961_SPKR_ENA 0x0080 /* SPKR_ENA */
|
||||
#define WM8961_SPKR_ENA_MASK 0x0080 /* SPKR_ENA */
|
||||
#define WM8961_SPKR_ENA_SHIFT 7 /* SPKR_ENA */
|
||||
#define WM8961_SPKR_ENA_WIDTH 1 /* SPKR_ENA */
|
||||
#define WM8961_SPKL_ENA 0x0040 /* SPKL_ENA */
|
||||
#define WM8961_SPKL_ENA_MASK 0x0040 /* SPKL_ENA */
|
||||
#define WM8961_SPKL_ENA_SHIFT 6 /* SPKL_ENA */
|
||||
#define WM8961_SPKL_ENA_WIDTH 1 /* SPKL_ENA */
|
||||
|
||||
/*
|
||||
* R51 (0x33) - Class D Control 2
|
||||
*/
|
||||
#define WM8961_CLASSD_ACGAIN_MASK 0x0007 /* CLASSD_ACGAIN - [2:0] */
|
||||
#define WM8961_CLASSD_ACGAIN_SHIFT 0 /* CLASSD_ACGAIN - [2:0] */
|
||||
#define WM8961_CLASSD_ACGAIN_WIDTH 3 /* CLASSD_ACGAIN - [2:0] */
|
||||
|
||||
/*
|
||||
* R56 (0x38) - Clocking 4
|
||||
*/
|
||||
#define WM8961_CLK_DCS_DIV_MASK 0x01E0 /* CLK_DCS_DIV - [8:5] */
|
||||
#define WM8961_CLK_DCS_DIV_SHIFT 5 /* CLK_DCS_DIV - [8:5] */
|
||||
#define WM8961_CLK_DCS_DIV_WIDTH 4 /* CLK_DCS_DIV - [8:5] */
|
||||
#define WM8961_CLK_SYS_RATE_MASK 0x001E /* CLK_SYS_RATE - [4:1] */
|
||||
#define WM8961_CLK_SYS_RATE_SHIFT 1 /* CLK_SYS_RATE - [4:1] */
|
||||
#define WM8961_CLK_SYS_RATE_WIDTH 4 /* CLK_SYS_RATE - [4:1] */
|
||||
|
||||
/*
|
||||
* R57 (0x39) - DSP Sidetone 0
|
||||
*/
|
||||
#define WM8961_ADCR_DAC_SVOL_MASK 0x00F0 /* ADCR_DAC_SVOL - [7:4] */
|
||||
#define WM8961_ADCR_DAC_SVOL_SHIFT 4 /* ADCR_DAC_SVOL - [7:4] */
|
||||
#define WM8961_ADCR_DAC_SVOL_WIDTH 4 /* ADCR_DAC_SVOL - [7:4] */
|
||||
#define WM8961_ADC_TO_DACR_MASK 0x000C /* ADC_TO_DACR - [3:2] */
|
||||
#define WM8961_ADC_TO_DACR_SHIFT 2 /* ADC_TO_DACR - [3:2] */
|
||||
#define WM8961_ADC_TO_DACR_WIDTH 2 /* ADC_TO_DACR - [3:2] */
|
||||
|
||||
/*
|
||||
* R58 (0x3A) - DSP Sidetone 1
|
||||
*/
|
||||
#define WM8961_ADCL_DAC_SVOL_MASK 0x00F0 /* ADCL_DAC_SVOL - [7:4] */
|
||||
#define WM8961_ADCL_DAC_SVOL_SHIFT 4 /* ADCL_DAC_SVOL - [7:4] */
|
||||
#define WM8961_ADCL_DAC_SVOL_WIDTH 4 /* ADCL_DAC_SVOL - [7:4] */
|
||||
#define WM8961_ADC_TO_DACL_MASK 0x000C /* ADC_TO_DACL - [3:2] */
|
||||
#define WM8961_ADC_TO_DACL_SHIFT 2 /* ADC_TO_DACL - [3:2] */
|
||||
#define WM8961_ADC_TO_DACL_WIDTH 2 /* ADC_TO_DACL - [3:2] */
|
||||
|
||||
/*
|
||||
* R60 (0x3C) - DC Servo 0
|
||||
*/
|
||||
#define WM8961_DCS_ENA_CHAN_INL 0x0080 /* DCS_ENA_CHAN_INL */
|
||||
#define WM8961_DCS_ENA_CHAN_INL_MASK 0x0080 /* DCS_ENA_CHAN_INL */
|
||||
#define WM8961_DCS_ENA_CHAN_INL_SHIFT 7 /* DCS_ENA_CHAN_INL */
|
||||
#define WM8961_DCS_ENA_CHAN_INL_WIDTH 1 /* DCS_ENA_CHAN_INL */
|
||||
#define WM8961_DCS_TRIG_STARTUP_INL 0x0040 /* DCS_TRIG_STARTUP_INL */
|
||||
#define WM8961_DCS_TRIG_STARTUP_INL_MASK 0x0040 /* DCS_TRIG_STARTUP_INL */
|
||||
#define WM8961_DCS_TRIG_STARTUP_INL_SHIFT 6 /* DCS_TRIG_STARTUP_INL */
|
||||
#define WM8961_DCS_TRIG_STARTUP_INL_WIDTH 1 /* DCS_TRIG_STARTUP_INL */
|
||||
#define WM8961_DCS_TRIG_SERIES_INL 0x0010 /* DCS_TRIG_SERIES_INL */
|
||||
#define WM8961_DCS_TRIG_SERIES_INL_MASK 0x0010 /* DCS_TRIG_SERIES_INL */
|
||||
#define WM8961_DCS_TRIG_SERIES_INL_SHIFT 4 /* DCS_TRIG_SERIES_INL */
|
||||
#define WM8961_DCS_TRIG_SERIES_INL_WIDTH 1 /* DCS_TRIG_SERIES_INL */
|
||||
#define WM8961_DCS_ENA_CHAN_INR 0x0008 /* DCS_ENA_CHAN_INR */
|
||||
#define WM8961_DCS_ENA_CHAN_INR_MASK 0x0008 /* DCS_ENA_CHAN_INR */
|
||||
#define WM8961_DCS_ENA_CHAN_INR_SHIFT 3 /* DCS_ENA_CHAN_INR */
|
||||
#define WM8961_DCS_ENA_CHAN_INR_WIDTH 1 /* DCS_ENA_CHAN_INR */
|
||||
#define WM8961_DCS_TRIG_STARTUP_INR 0x0004 /* DCS_TRIG_STARTUP_INR */
|
||||
#define WM8961_DCS_TRIG_STARTUP_INR_MASK 0x0004 /* DCS_TRIG_STARTUP_INR */
|
||||
#define WM8961_DCS_TRIG_STARTUP_INR_SHIFT 2 /* DCS_TRIG_STARTUP_INR */
|
||||
#define WM8961_DCS_TRIG_STARTUP_INR_WIDTH 1 /* DCS_TRIG_STARTUP_INR */
|
||||
#define WM8961_DCS_TRIG_SERIES_INR 0x0001 /* DCS_TRIG_SERIES_INR */
|
||||
#define WM8961_DCS_TRIG_SERIES_INR_MASK 0x0001 /* DCS_TRIG_SERIES_INR */
|
||||
#define WM8961_DCS_TRIG_SERIES_INR_SHIFT 0 /* DCS_TRIG_SERIES_INR */
|
||||
#define WM8961_DCS_TRIG_SERIES_INR_WIDTH 1 /* DCS_TRIG_SERIES_INR */
|
||||
|
||||
/*
|
||||
* R61 (0x3D) - DC Servo 1
|
||||
*/
|
||||
#define WM8961_DCS_ENA_CHAN_HPL 0x0080 /* DCS_ENA_CHAN_HPL */
|
||||
#define WM8961_DCS_ENA_CHAN_HPL_MASK 0x0080 /* DCS_ENA_CHAN_HPL */
|
||||
#define WM8961_DCS_ENA_CHAN_HPL_SHIFT 7 /* DCS_ENA_CHAN_HPL */
|
||||
#define WM8961_DCS_ENA_CHAN_HPL_WIDTH 1 /* DCS_ENA_CHAN_HPL */
|
||||
#define WM8961_DCS_TRIG_STARTUP_HPL 0x0040 /* DCS_TRIG_STARTUP_HPL */
|
||||
#define WM8961_DCS_TRIG_STARTUP_HPL_MASK 0x0040 /* DCS_TRIG_STARTUP_HPL */
|
||||
#define WM8961_DCS_TRIG_STARTUP_HPL_SHIFT 6 /* DCS_TRIG_STARTUP_HPL */
|
||||
#define WM8961_DCS_TRIG_STARTUP_HPL_WIDTH 1 /* DCS_TRIG_STARTUP_HPL */
|
||||
#define WM8961_DCS_TRIG_SERIES_HPL 0x0010 /* DCS_TRIG_SERIES_HPL */
|
||||
#define WM8961_DCS_TRIG_SERIES_HPL_MASK 0x0010 /* DCS_TRIG_SERIES_HPL */
|
||||
#define WM8961_DCS_TRIG_SERIES_HPL_SHIFT 4 /* DCS_TRIG_SERIES_HPL */
|
||||
#define WM8961_DCS_TRIG_SERIES_HPL_WIDTH 1 /* DCS_TRIG_SERIES_HPL */
|
||||
#define WM8961_DCS_ENA_CHAN_HPR 0x0008 /* DCS_ENA_CHAN_HPR */
|
||||
#define WM8961_DCS_ENA_CHAN_HPR_MASK 0x0008 /* DCS_ENA_CHAN_HPR */
|
||||
#define WM8961_DCS_ENA_CHAN_HPR_SHIFT 3 /* DCS_ENA_CHAN_HPR */
|
||||
#define WM8961_DCS_ENA_CHAN_HPR_WIDTH 1 /* DCS_ENA_CHAN_HPR */
|
||||
#define WM8961_DCS_TRIG_STARTUP_HPR 0x0004 /* DCS_TRIG_STARTUP_HPR */
|
||||
#define WM8961_DCS_TRIG_STARTUP_HPR_MASK 0x0004 /* DCS_TRIG_STARTUP_HPR */
|
||||
#define WM8961_DCS_TRIG_STARTUP_HPR_SHIFT 2 /* DCS_TRIG_STARTUP_HPR */
|
||||
#define WM8961_DCS_TRIG_STARTUP_HPR_WIDTH 1 /* DCS_TRIG_STARTUP_HPR */
|
||||
#define WM8961_DCS_TRIG_SERIES_HPR 0x0001 /* DCS_TRIG_SERIES_HPR */
|
||||
#define WM8961_DCS_TRIG_SERIES_HPR_MASK 0x0001 /* DCS_TRIG_SERIES_HPR */
|
||||
#define WM8961_DCS_TRIG_SERIES_HPR_SHIFT 0 /* DCS_TRIG_SERIES_HPR */
|
||||
#define WM8961_DCS_TRIG_SERIES_HPR_WIDTH 1 /* DCS_TRIG_SERIES_HPR */
|
||||
|
||||
/*
|
||||
* R63 (0x3F) - DC Servo 3
|
||||
*/
|
||||
#define WM8961_DCS_FILT_BW_SERIES_MASK 0x0030 /* DCS_FILT_BW_SERIES - [5:4] */
|
||||
#define WM8961_DCS_FILT_BW_SERIES_SHIFT 4 /* DCS_FILT_BW_SERIES - [5:4] */
|
||||
#define WM8961_DCS_FILT_BW_SERIES_WIDTH 2 /* DCS_FILT_BW_SERIES - [5:4] */
|
||||
|
||||
/*
|
||||
* R65 (0x41) - DC Servo 5
|
||||
*/
|
||||
#define WM8961_DCS_SERIES_NO_HP_MASK 0x007F /* DCS_SERIES_NO_HP - [6:0] */
|
||||
#define WM8961_DCS_SERIES_NO_HP_SHIFT 0 /* DCS_SERIES_NO_HP - [6:0] */
|
||||
#define WM8961_DCS_SERIES_NO_HP_WIDTH 7 /* DCS_SERIES_NO_HP - [6:0] */
|
||||
|
||||
/*
|
||||
* R68 (0x44) - Analogue PGA Bias
|
||||
*/
|
||||
#define WM8961_HP_PGAS_BIAS_MASK 0x0007 /* HP_PGAS_BIAS - [2:0] */
|
||||
#define WM8961_HP_PGAS_BIAS_SHIFT 0 /* HP_PGAS_BIAS - [2:0] */
|
||||
#define WM8961_HP_PGAS_BIAS_WIDTH 3 /* HP_PGAS_BIAS - [2:0] */
|
||||
|
||||
/*
|
||||
* R69 (0x45) - Analogue HP 0
|
||||
*/
|
||||
#define WM8961_HPL_RMV_SHORT 0x0080 /* HPL_RMV_SHORT */
|
||||
#define WM8961_HPL_RMV_SHORT_MASK 0x0080 /* HPL_RMV_SHORT */
|
||||
#define WM8961_HPL_RMV_SHORT_SHIFT 7 /* HPL_RMV_SHORT */
|
||||
#define WM8961_HPL_RMV_SHORT_WIDTH 1 /* HPL_RMV_SHORT */
|
||||
#define WM8961_HPL_ENA_OUTP 0x0040 /* HPL_ENA_OUTP */
|
||||
#define WM8961_HPL_ENA_OUTP_MASK 0x0040 /* HPL_ENA_OUTP */
|
||||
#define WM8961_HPL_ENA_OUTP_SHIFT 6 /* HPL_ENA_OUTP */
|
||||
#define WM8961_HPL_ENA_OUTP_WIDTH 1 /* HPL_ENA_OUTP */
|
||||
#define WM8961_HPL_ENA_DLY 0x0020 /* HPL_ENA_DLY */
|
||||
#define WM8961_HPL_ENA_DLY_MASK 0x0020 /* HPL_ENA_DLY */
|
||||
#define WM8961_HPL_ENA_DLY_SHIFT 5 /* HPL_ENA_DLY */
|
||||
#define WM8961_HPL_ENA_DLY_WIDTH 1 /* HPL_ENA_DLY */
|
||||
#define WM8961_HPL_ENA 0x0010 /* HPL_ENA */
|
||||
#define WM8961_HPL_ENA_MASK 0x0010 /* HPL_ENA */
|
||||
#define WM8961_HPL_ENA_SHIFT 4 /* HPL_ENA */
|
||||
#define WM8961_HPL_ENA_WIDTH 1 /* HPL_ENA */
|
||||
#define WM8961_HPR_RMV_SHORT 0x0008 /* HPR_RMV_SHORT */
|
||||
#define WM8961_HPR_RMV_SHORT_MASK 0x0008 /* HPR_RMV_SHORT */
|
||||
#define WM8961_HPR_RMV_SHORT_SHIFT 3 /* HPR_RMV_SHORT */
|
||||
#define WM8961_HPR_RMV_SHORT_WIDTH 1 /* HPR_RMV_SHORT */
|
||||
#define WM8961_HPR_ENA_OUTP 0x0004 /* HPR_ENA_OUTP */
|
||||
#define WM8961_HPR_ENA_OUTP_MASK 0x0004 /* HPR_ENA_OUTP */
|
||||
#define WM8961_HPR_ENA_OUTP_SHIFT 2 /* HPR_ENA_OUTP */
|
||||
#define WM8961_HPR_ENA_OUTP_WIDTH 1 /* HPR_ENA_OUTP */
|
||||
#define WM8961_HPR_ENA_DLY 0x0002 /* HPR_ENA_DLY */
|
||||
#define WM8961_HPR_ENA_DLY_MASK 0x0002 /* HPR_ENA_DLY */
|
||||
#define WM8961_HPR_ENA_DLY_SHIFT 1 /* HPR_ENA_DLY */
|
||||
#define WM8961_HPR_ENA_DLY_WIDTH 1 /* HPR_ENA_DLY */
|
||||
#define WM8961_HPR_ENA 0x0001 /* HPR_ENA */
|
||||
#define WM8961_HPR_ENA_MASK 0x0001 /* HPR_ENA */
|
||||
#define WM8961_HPR_ENA_SHIFT 0 /* HPR_ENA */
|
||||
#define WM8961_HPR_ENA_WIDTH 1 /* HPR_ENA */
|
||||
|
||||
/*
|
||||
* R71 (0x47) - Analogue HP 2
|
||||
*/
|
||||
#define WM8961_HPL_VOL_MASK 0x01C0 /* HPL_VOL - [8:6] */
|
||||
#define WM8961_HPL_VOL_SHIFT 6 /* HPL_VOL - [8:6] */
|
||||
#define WM8961_HPL_VOL_WIDTH 3 /* HPL_VOL - [8:6] */
|
||||
#define WM8961_HPR_VOL_MASK 0x0038 /* HPR_VOL - [5:3] */
|
||||
#define WM8961_HPR_VOL_SHIFT 3 /* HPR_VOL - [5:3] */
|
||||
#define WM8961_HPR_VOL_WIDTH 3 /* HPR_VOL - [5:3] */
|
||||
#define WM8961_HP_BIAS_BOOST_MASK 0x0007 /* HP_BIAS_BOOST - [2:0] */
|
||||
#define WM8961_HP_BIAS_BOOST_SHIFT 0 /* HP_BIAS_BOOST - [2:0] */
|
||||
#define WM8961_HP_BIAS_BOOST_WIDTH 3 /* HP_BIAS_BOOST - [2:0] */
|
||||
|
||||
/*
|
||||
* R72 (0x48) - Charge Pump 1
|
||||
*/
|
||||
#define WM8961_CP_ENA 0x0001 /* CP_ENA */
|
||||
#define WM8961_CP_ENA_MASK 0x0001 /* CP_ENA */
|
||||
#define WM8961_CP_ENA_SHIFT 0 /* CP_ENA */
|
||||
#define WM8961_CP_ENA_WIDTH 1 /* CP_ENA */
|
||||
|
||||
/*
|
||||
* R82 (0x52) - Charge Pump B
|
||||
*/
|
||||
#define WM8961_CP_DYN_PWR_MASK 0x0003 /* CP_DYN_PWR - [1:0] */
|
||||
#define WM8961_CP_DYN_PWR_SHIFT 0 /* CP_DYN_PWR - [1:0] */
|
||||
#define WM8961_CP_DYN_PWR_WIDTH 2 /* CP_DYN_PWR - [1:0] */
|
||||
|
||||
/*
|
||||
* R87 (0x57) - Write Sequencer 1
|
||||
*/
|
||||
#define WM8961_WSEQ_ENA 0x0020 /* WSEQ_ENA */
|
||||
#define WM8961_WSEQ_ENA_MASK 0x0020 /* WSEQ_ENA */
|
||||
#define WM8961_WSEQ_ENA_SHIFT 5 /* WSEQ_ENA */
|
||||
#define WM8961_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */
|
||||
#define WM8961_WSEQ_WRITE_INDEX_MASK 0x001F /* WSEQ_WRITE_INDEX - [4:0] */
|
||||
#define WM8961_WSEQ_WRITE_INDEX_SHIFT 0 /* WSEQ_WRITE_INDEX - [4:0] */
|
||||
#define WM8961_WSEQ_WRITE_INDEX_WIDTH 5 /* WSEQ_WRITE_INDEX - [4:0] */
|
||||
|
||||
/*
|
||||
* R88 (0x58) - Write Sequencer 2
|
||||
*/
|
||||
#define WM8961_WSEQ_EOS 0x0100 /* WSEQ_EOS */
|
||||
#define WM8961_WSEQ_EOS_MASK 0x0100 /* WSEQ_EOS */
|
||||
#define WM8961_WSEQ_EOS_SHIFT 8 /* WSEQ_EOS */
|
||||
#define WM8961_WSEQ_EOS_WIDTH 1 /* WSEQ_EOS */
|
||||
#define WM8961_WSEQ_ADDR_MASK 0x00FF /* WSEQ_ADDR - [7:0] */
|
||||
#define WM8961_WSEQ_ADDR_SHIFT 0 /* WSEQ_ADDR - [7:0] */
|
||||
#define WM8961_WSEQ_ADDR_WIDTH 8 /* WSEQ_ADDR - [7:0] */
|
||||
|
||||
/*
|
||||
* R89 (0x59) - Write Sequencer 3
|
||||
*/
|
||||
#define WM8961_WSEQ_DATA_MASK 0x00FF /* WSEQ_DATA - [7:0] */
|
||||
#define WM8961_WSEQ_DATA_SHIFT 0 /* WSEQ_DATA - [7:0] */
|
||||
#define WM8961_WSEQ_DATA_WIDTH 8 /* WSEQ_DATA - [7:0] */
|
||||
|
||||
/*
|
||||
* R90 (0x5A) - Write Sequencer 4
|
||||
*/
|
||||
#define WM8961_WSEQ_ABORT 0x0100 /* WSEQ_ABORT */
|
||||
#define WM8961_WSEQ_ABORT_MASK 0x0100 /* WSEQ_ABORT */
|
||||
#define WM8961_WSEQ_ABORT_SHIFT 8 /* WSEQ_ABORT */
|
||||
#define WM8961_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */
|
||||
#define WM8961_WSEQ_START 0x0080 /* WSEQ_START */
|
||||
#define WM8961_WSEQ_START_MASK 0x0080 /* WSEQ_START */
|
||||
#define WM8961_WSEQ_START_SHIFT 7 /* WSEQ_START */
|
||||
#define WM8961_WSEQ_START_WIDTH 1 /* WSEQ_START */
|
||||
#define WM8961_WSEQ_START_INDEX_MASK 0x003F /* WSEQ_START_INDEX - [5:0] */
|
||||
#define WM8961_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [5:0] */
|
||||
#define WM8961_WSEQ_START_INDEX_WIDTH 6 /* WSEQ_START_INDEX - [5:0] */
|
||||
|
||||
/*
|
||||
* R91 (0x5B) - Write Sequencer 5
|
||||
*/
|
||||
#define WM8961_WSEQ_DATA_WIDTH_MASK 0x0070 /* WSEQ_DATA_WIDTH - [6:4] */
|
||||
#define WM8961_WSEQ_DATA_WIDTH_SHIFT 4 /* WSEQ_DATA_WIDTH - [6:4] */
|
||||
#define WM8961_WSEQ_DATA_WIDTH_WIDTH 3 /* WSEQ_DATA_WIDTH - [6:4] */
|
||||
#define WM8961_WSEQ_DATA_START_MASK 0x000F /* WSEQ_DATA_START - [3:0] */
|
||||
#define WM8961_WSEQ_DATA_START_SHIFT 0 /* WSEQ_DATA_START - [3:0] */
|
||||
#define WM8961_WSEQ_DATA_START_WIDTH 4 /* WSEQ_DATA_START - [3:0] */
|
||||
|
||||
/*
|
||||
* R92 (0x5C) - Write Sequencer 6
|
||||
*/
|
||||
#define WM8961_WSEQ_DELAY_MASK 0x000F /* WSEQ_DELAY - [3:0] */
|
||||
#define WM8961_WSEQ_DELAY_SHIFT 0 /* WSEQ_DELAY - [3:0] */
|
||||
#define WM8961_WSEQ_DELAY_WIDTH 4 /* WSEQ_DELAY - [3:0] */
|
||||
|
||||
/*
|
||||
* R93 (0x5D) - Write Sequencer 7
|
||||
*/
|
||||
#define WM8961_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */
|
||||
#define WM8961_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */
|
||||
#define WM8961_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */
|
||||
#define WM8961_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */
|
||||
|
||||
/*
|
||||
* R252 (0xFC) - General test 1
|
||||
*/
|
||||
#define WM8961_ARA_ENA 0x0002 /* ARA_ENA */
|
||||
#define WM8961_ARA_ENA_MASK 0x0002 /* ARA_ENA */
|
||||
#define WM8961_ARA_ENA_SHIFT 1 /* ARA_ENA */
|
||||
#define WM8961_ARA_ENA_WIDTH 1 /* ARA_ENA */
|
||||
#define WM8961_AUTO_INC 0x0001 /* AUTO_INC */
|
||||
#define WM8961_AUTO_INC_MASK 0x0001 /* AUTO_INC */
|
||||
#define WM8961_AUTO_INC_SHIFT 0 /* AUTO_INC */
|
||||
#define WM8961_AUTO_INC_WIDTH 1 /* AUTO_INC */
|
||||
|
||||
#endif
|
|
@ -981,6 +981,21 @@ static int wm8988_i2c_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm8988_i2c_suspend(struct i2c_client *client, pm_message_t msg)
|
||||
{
|
||||
return snd_soc_suspend_device(&client->dev);
|
||||
}
|
||||
|
||||
static int wm8988_i2c_resume(struct i2c_client *client)
|
||||
{
|
||||
return snd_soc_resume_device(&client->dev);
|
||||
}
|
||||
#else
|
||||
#define wm8988_i2c_suspend NULL
|
||||
#define wm8988_i2c_resume NULL
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id wm8988_i2c_id[] = {
|
||||
{ "wm8988", 0 },
|
||||
{ }
|
||||
|
@ -994,6 +1009,8 @@ static struct i2c_driver wm8988_i2c_driver = {
|
|||
},
|
||||
.probe = wm8988_i2c_probe,
|
||||
.remove = wm8988_i2c_remove,
|
||||
.suspend = wm8988_i2c_suspend,
|
||||
.resume = wm8988_i2c_resume,
|
||||
.id_table = wm8988_i2c_id,
|
||||
};
|
||||
#endif
|
||||
|
@ -1051,6 +1068,21 @@ static int __devexit wm8988_spi_remove(struct spi_device *spi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm8988_spi_suspend(struct spi_device *spi, pm_message_t msg)
|
||||
{
|
||||
return snd_soc_suspend_device(&spi->dev);
|
||||
}
|
||||
|
||||
static int wm8988_spi_resume(struct spi_device *spi)
|
||||
{
|
||||
return snd_soc_resume_device(&spi->dev);
|
||||
}
|
||||
#else
|
||||
#define wm8988_spi_suspend NULL
|
||||
#define wm8988_spi_resume NULL
|
||||
#endif
|
||||
|
||||
static struct spi_driver wm8988_spi_driver = {
|
||||
.driver = {
|
||||
.name = "wm8988",
|
||||
|
@ -1059,6 +1091,8 @@ static struct spi_driver wm8988_spi_driver = {
|
|||
},
|
||||
.probe = wm8988_spi_probe,
|
||||
.remove = __devexit_p(wm8988_spi_remove),
|
||||
.suspend = wm8988_spi_suspend,
|
||||
.resume = wm8988_spi_resume,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1492,6 +1492,21 @@ static __devexit int wm9081_i2c_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm9081_i2c_suspend(struct i2c_client *client, pm_message_t msg)
|
||||
{
|
||||
return snd_soc_suspend_device(&client->dev);
|
||||
}
|
||||
|
||||
static int wm9081_i2c_resume(struct i2c_client *client)
|
||||
{
|
||||
return snd_soc_resume_device(&client->dev);
|
||||
}
|
||||
#else
|
||||
#define wm9081_i2c_suspend NULL
|
||||
#define wm9081_i2c_resume NULL
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id wm9081_i2c_id[] = {
|
||||
{ "wm9081", 0 },
|
||||
{ }
|
||||
|
@ -1505,6 +1520,8 @@ static struct i2c_driver wm9081_i2c_driver = {
|
|||
},
|
||||
.probe = wm9081_i2c_probe,
|
||||
.remove = __devexit_p(wm9081_i2c_remove),
|
||||
.suspend = wm9081_i2c_suspend,
|
||||
.resume = wm9081_i2c_resume,
|
||||
.id_table = wm9081_i2c_id,
|
||||
};
|
||||
|
||||
|
|
|
@ -72,4 +72,11 @@ config SND_OMAP_SOC_OMAP3_BEAGLE
|
|||
help
|
||||
Say Y if you want to add support for SoC audio on the Beagleboard.
|
||||
|
||||
config SND_OMAP_SOC_ZOOM2
|
||||
tristate "SoC Audio support for Zoom2"
|
||||
depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_ZOOM2
|
||||
select SND_OMAP_SOC_MCBSP
|
||||
select SND_SOC_TWL4030
|
||||
help
|
||||
Say Y if you want to add support for Soc audio on Zoom2 board.
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ snd-soc-omap3evm-objs := omap3evm.o
|
|||
snd-soc-sdp3430-objs := sdp3430.o
|
||||
snd-soc-omap3pandora-objs := omap3pandora.o
|
||||
snd-soc-omap3beagle-objs := omap3beagle.o
|
||||
snd-soc-zoom2-objs := zoom2.o
|
||||
|
||||
obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
|
||||
obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
|
||||
|
@ -23,3 +24,4 @@ obj-$(CONFIG_MACH_OMAP3EVM) += snd-soc-omap3evm.o
|
|||
obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
|
||||
obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
|
||||
obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
|
||||
obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o
|
||||
|
|
|
@ -96,7 +96,7 @@ static int sdp3430_hw_voice_params(struct snd_pcm_substream *substream,
|
|||
ret = snd_soc_dai_set_fmt(codec_dai,
|
||||
SND_SOC_DAIFMT_DSP_A |
|
||||
SND_SOC_DAIFMT_IB_NF |
|
||||
SND_SOC_DAIFMT_CBS_CFM);
|
||||
SND_SOC_DAIFMT_CBM_CFM);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "can't set codec DAI configuration\n");
|
||||
return ret;
|
||||
|
|
301
sound/soc/omap/zoom2.c
Normal file
301
sound/soc/omap/zoom2.c
Normal file
|
@ -0,0 +1,301 @@
|
|||
/*
|
||||
* zoom2.c -- SoC audio for Zoom2
|
||||
*
|
||||
* Author: Misael Lopez Cruz <x0052729@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/mcbsp.h>
|
||||
|
||||
#include "omap-mcbsp.h"
|
||||
#include "omap-pcm.h"
|
||||
#include "../codecs/twl4030.h"
|
||||
|
||||
#define ZOOM2_HEADSET_MUX_GPIO (OMAP_MAX_GPIO_LINES + 15)
|
||||
|
||||
static int zoom2_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||
int ret;
|
||||
|
||||
/* Set codec DAI configuration */
|
||||
ret = snd_soc_dai_set_fmt(codec_dai,
|
||||
SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_NF |
|
||||
SND_SOC_DAIFMT_CBM_CFM);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "can't set codec DAI configuration\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set cpu DAI configuration */
|
||||
ret = snd_soc_dai_set_fmt(cpu_dai,
|
||||
SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_NF |
|
||||
SND_SOC_DAIFMT_CBM_CFM);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "can't set cpu DAI configuration\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set the codec system clock for DAC and ADC */
|
||||
ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
|
||||
SND_SOC_CLOCK_IN);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "can't set codec system clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_ops zoom2_ops = {
|
||||
.hw_params = zoom2_hw_params,
|
||||
};
|
||||
|
||||
static int zoom2_hw_voice_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||
int ret;
|
||||
|
||||
/* Set codec DAI configuration */
|
||||
ret = snd_soc_dai_set_fmt(codec_dai,
|
||||
SND_SOC_DAIFMT_DSP_A |
|
||||
SND_SOC_DAIFMT_IB_NF |
|
||||
SND_SOC_DAIFMT_CBM_CFM);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "can't set codec DAI configuration\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set cpu DAI configuration */
|
||||
ret = snd_soc_dai_set_fmt(cpu_dai,
|
||||
SND_SOC_DAIFMT_DSP_A |
|
||||
SND_SOC_DAIFMT_IB_NF |
|
||||
SND_SOC_DAIFMT_CBM_CFM);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "can't set cpu DAI configuration\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set the codec system clock for DAC and ADC */
|
||||
ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
|
||||
SND_SOC_CLOCK_IN);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "can't set codec system clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_ops zoom2_voice_ops = {
|
||||
.hw_params = zoom2_hw_voice_params,
|
||||
};
|
||||
|
||||
/* Zoom2 machine DAPM */
|
||||
static const struct snd_soc_dapm_widget zoom2_twl4030_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_MIC("Ext Mic", NULL),
|
||||
SND_SOC_DAPM_SPK("Ext Spk", NULL),
|
||||
SND_SOC_DAPM_MIC("Headset Mic", NULL),
|
||||
SND_SOC_DAPM_HP("Headset Stereophone", NULL),
|
||||
SND_SOC_DAPM_LINE("Aux In", NULL),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route audio_map[] = {
|
||||
/* External Mics: MAINMIC, SUBMIC with bias*/
|
||||
{"MAINMIC", NULL, "Mic Bias 1"},
|
||||
{"SUBMIC", NULL, "Mic Bias 2"},
|
||||
{"Mic Bias 1", NULL, "Ext Mic"},
|
||||
{"Mic Bias 2", NULL, "Ext Mic"},
|
||||
|
||||
/* External Speakers: HFL, HFR */
|
||||
{"Ext Spk", NULL, "HFL"},
|
||||
{"Ext Spk", NULL, "HFR"},
|
||||
|
||||
/* Headset Stereophone: HSOL, HSOR */
|
||||
{"Headset Stereophone", NULL, "HSOL"},
|
||||
{"Headset Stereophone", NULL, "HSOR"},
|
||||
|
||||
/* Headset Mic: HSMIC with bias */
|
||||
{"HSMIC", NULL, "Headset Mic Bias"},
|
||||
{"Headset Mic Bias", NULL, "Headset Mic"},
|
||||
|
||||
/* Aux In: AUXL, AUXR */
|
||||
{"Aux In", NULL, "AUXL"},
|
||||
{"Aux In", NULL, "AUXR"},
|
||||
};
|
||||
|
||||
static int zoom2_twl4030_init(struct snd_soc_codec *codec)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Add Zoom2 specific widgets */
|
||||
ret = snd_soc_dapm_new_controls(codec, zoom2_twl4030_dapm_widgets,
|
||||
ARRAY_SIZE(zoom2_twl4030_dapm_widgets));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Set up Zoom2 specific audio path audio_map */
|
||||
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
|
||||
|
||||
/* Zoom2 connected pins */
|
||||
snd_soc_dapm_enable_pin(codec, "Ext Mic");
|
||||
snd_soc_dapm_enable_pin(codec, "Ext Spk");
|
||||
snd_soc_dapm_enable_pin(codec, "Headset Mic");
|
||||
snd_soc_dapm_enable_pin(codec, "Headset Stereophone");
|
||||
snd_soc_dapm_enable_pin(codec, "Aux In");
|
||||
|
||||
/* TWL4030 not connected pins */
|
||||
snd_soc_dapm_nc_pin(codec, "CARKITMIC");
|
||||
snd_soc_dapm_nc_pin(codec, "DIGIMIC0");
|
||||
snd_soc_dapm_nc_pin(codec, "DIGIMIC1");
|
||||
|
||||
snd_soc_dapm_nc_pin(codec, "OUTL");
|
||||
snd_soc_dapm_nc_pin(codec, "OUTR");
|
||||
snd_soc_dapm_nc_pin(codec, "EARPIECE");
|
||||
snd_soc_dapm_nc_pin(codec, "PREDRIVEL");
|
||||
snd_soc_dapm_nc_pin(codec, "PREDRIVER");
|
||||
snd_soc_dapm_nc_pin(codec, "CARKITL");
|
||||
snd_soc_dapm_nc_pin(codec, "CARKITR");
|
||||
|
||||
ret = snd_soc_dapm_sync(codec);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int zoom2_twl4030_voice_init(struct snd_soc_codec *codec)
|
||||
{
|
||||
unsigned short reg;
|
||||
|
||||
/* Enable voice interface */
|
||||
reg = codec->read(codec, TWL4030_REG_VOICE_IF);
|
||||
reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN;
|
||||
codec->write(codec, TWL4030_REG_VOICE_IF, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Digital audio interface glue - connects codec <--> CPU */
|
||||
static struct snd_soc_dai_link zoom2_dai[] = {
|
||||
{
|
||||
.name = "TWL4030 I2S",
|
||||
.stream_name = "TWL4030 Audio",
|
||||
.cpu_dai = &omap_mcbsp_dai[0],
|
||||
.codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
|
||||
.init = zoom2_twl4030_init,
|
||||
.ops = &zoom2_ops,
|
||||
},
|
||||
{
|
||||
.name = "TWL4030 PCM",
|
||||
.stream_name = "TWL4030 Voice",
|
||||
.cpu_dai = &omap_mcbsp_dai[1],
|
||||
.codec_dai = &twl4030_dai[TWL4030_DAI_VOICE],
|
||||
.init = zoom2_twl4030_voice_init,
|
||||
.ops = &zoom2_voice_ops,
|
||||
},
|
||||
};
|
||||
|
||||
/* Audio machine driver */
|
||||
static struct snd_soc_card snd_soc_zoom2 = {
|
||||
.name = "Zoom2",
|
||||
.platform = &omap_soc_platform,
|
||||
.dai_link = zoom2_dai,
|
||||
.num_links = ARRAY_SIZE(zoom2_dai),
|
||||
};
|
||||
|
||||
/* twl4030 setup */
|
||||
static struct twl4030_setup_data twl4030_setup = {
|
||||
.ramp_delay_value = 2, /* 81 ms */
|
||||
.sysclk = 26000,
|
||||
};
|
||||
|
||||
/* Audio subsystem */
|
||||
static struct snd_soc_device zoom2_snd_devdata = {
|
||||
.card = &snd_soc_zoom2,
|
||||
.codec_dev = &soc_codec_dev_twl4030,
|
||||
.codec_data = &twl4030_setup,
|
||||
};
|
||||
|
||||
static struct platform_device *zoom2_snd_device;
|
||||
|
||||
static int __init zoom2_soc_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!machine_is_omap_zoom2()) {
|
||||
pr_debug("Not Zoom2!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
printk(KERN_INFO "Zoom2 SoC init\n");
|
||||
|
||||
zoom2_snd_device = platform_device_alloc("soc-audio", -1);
|
||||
if (!zoom2_snd_device) {
|
||||
printk(KERN_ERR "Platform device allocation failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
platform_set_drvdata(zoom2_snd_device, &zoom2_snd_devdata);
|
||||
zoom2_snd_devdata.dev = &zoom2_snd_device->dev;
|
||||
*(unsigned int *)zoom2_dai[0].cpu_dai->private_data = 1; /* McBSP2 */
|
||||
*(unsigned int *)zoom2_dai[1].cpu_dai->private_data = 2; /* McBSP3 */
|
||||
|
||||
ret = platform_device_add(zoom2_snd_device);
|
||||
if (ret)
|
||||
goto err1;
|
||||
|
||||
BUG_ON(gpio_request(ZOOM2_HEADSET_MUX_GPIO, "hs_mux") < 0);
|
||||
gpio_direction_output(ZOOM2_HEADSET_MUX_GPIO, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
err1:
|
||||
printk(KERN_ERR "Unable to add platform device\n");
|
||||
platform_device_put(zoom2_snd_device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
module_init(zoom2_soc_init);
|
||||
|
||||
static void __exit zoom2_soc_exit(void)
|
||||
{
|
||||
gpio_free(ZOOM2_HEADSET_MUX_GPIO);
|
||||
|
||||
platform_device_unregister(zoom2_snd_device);
|
||||
}
|
||||
module_exit(zoom2_soc_exit);
|
||||
|
||||
MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
|
||||
MODULE_DESCRIPTION("ALSA SoC Zoom2");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -20,12 +20,14 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/uda1380.h>
|
||||
|
||||
#include <mach/magician.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
@ -447,34 +449,47 @@ static struct snd_soc_card snd_soc_card_magician = {
|
|||
.platform = &pxa2xx_soc_platform,
|
||||
};
|
||||
|
||||
/* magician audio private data */
|
||||
static struct uda1380_setup_data magician_uda1380_setup = {
|
||||
.i2c_address = 0x18,
|
||||
.dac_clk = UDA1380_DAC_CLK_WSPLL,
|
||||
};
|
||||
|
||||
/* magician audio subsystem */
|
||||
static struct snd_soc_device magician_snd_devdata = {
|
||||
.card = &snd_soc_card_magician,
|
||||
.codec_dev = &soc_codec_dev_uda1380,
|
||||
.codec_data = &magician_uda1380_setup,
|
||||
};
|
||||
|
||||
static struct platform_device *magician_snd_device;
|
||||
|
||||
/*
|
||||
* FIXME: move into magician board file once merged into the pxa tree
|
||||
*/
|
||||
static struct uda1380_platform_data uda1380_info = {
|
||||
.gpio_power = EGPIO_MAGICIAN_CODEC_POWER,
|
||||
.gpio_reset = EGPIO_MAGICIAN_CODEC_RESET,
|
||||
.dac_clk = UDA1380_DAC_CLK_WSPLL,
|
||||
};
|
||||
|
||||
static struct i2c_board_info i2c_board_info[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("uda1380", 0x18),
|
||||
.platform_data = &uda1380_info,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init magician_init(void)
|
||||
{
|
||||
int ret;
|
||||
struct i2c_adapter *adapter;
|
||||
struct i2c_client *client;
|
||||
|
||||
if (!machine_is_magician())
|
||||
return -ENODEV;
|
||||
|
||||
ret = gpio_request(EGPIO_MAGICIAN_CODEC_POWER, "CODEC_POWER");
|
||||
if (ret)
|
||||
goto err_request_power;
|
||||
ret = gpio_request(EGPIO_MAGICIAN_CODEC_RESET, "CODEC_RESET");
|
||||
if (ret)
|
||||
goto err_request_reset;
|
||||
adapter = i2c_get_adapter(0);
|
||||
if (!adapter)
|
||||
return -ENODEV;
|
||||
client = i2c_new_device(adapter, i2c_board_info);
|
||||
i2c_put_adapter(adapter);
|
||||
if (!client)
|
||||
return -ENODEV;
|
||||
|
||||
ret = gpio_request(EGPIO_MAGICIAN_SPK_POWER, "SPK_POWER");
|
||||
if (ret)
|
||||
goto err_request_spk;
|
||||
|
@ -491,14 +506,8 @@ static int __init magician_init(void)
|
|||
if (ret)
|
||||
goto err_request_in_sel1;
|
||||
|
||||
gpio_set_value(EGPIO_MAGICIAN_CODEC_POWER, 1);
|
||||
gpio_set_value(EGPIO_MAGICIAN_IN_SEL0, 0);
|
||||
|
||||
/* we may need to have the clock running here - pH5 */
|
||||
gpio_set_value(EGPIO_MAGICIAN_CODEC_RESET, 1);
|
||||
udelay(5);
|
||||
gpio_set_value(EGPIO_MAGICIAN_CODEC_RESET, 0);
|
||||
|
||||
magician_snd_device = platform_device_alloc("soc-audio", -1);
|
||||
if (!magician_snd_device) {
|
||||
ret = -ENOMEM;
|
||||
|
@ -526,10 +535,6 @@ err_request_mic:
|
|||
err_request_ep:
|
||||
gpio_free(EGPIO_MAGICIAN_SPK_POWER);
|
||||
err_request_spk:
|
||||
gpio_free(EGPIO_MAGICIAN_CODEC_RESET);
|
||||
err_request_reset:
|
||||
gpio_free(EGPIO_MAGICIAN_CODEC_POWER);
|
||||
err_request_power:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -540,15 +545,12 @@ static void __exit magician_exit(void)
|
|||
gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, 0);
|
||||
gpio_set_value(EGPIO_MAGICIAN_EP_POWER, 0);
|
||||
gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, 0);
|
||||
gpio_set_value(EGPIO_MAGICIAN_CODEC_POWER, 0);
|
||||
|
||||
gpio_free(EGPIO_MAGICIAN_IN_SEL1);
|
||||
gpio_free(EGPIO_MAGICIAN_IN_SEL0);
|
||||
gpio_free(EGPIO_MAGICIAN_MIC_POWER);
|
||||
gpio_free(EGPIO_MAGICIAN_EP_POWER);
|
||||
gpio_free(EGPIO_MAGICIAN_SPK_POWER);
|
||||
gpio_free(EGPIO_MAGICIAN_CODEC_RESET);
|
||||
gpio_free(EGPIO_MAGICIAN_CODEC_POWER);
|
||||
}
|
||||
|
||||
module_init(magician_init);
|
||||
|
|
|
@ -457,31 +457,27 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
ssp_write_reg(ssp, SSCR0, sscr0);
|
||||
ssp_write_reg(ssp, SSCR1, sscr1);
|
||||
ssp_write_reg(ssp, SSPSP, sspsp);
|
||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
case SND_SOC_DAIFMT_NB_NF:
|
||||
sspsp |= SSPSP_SFRMP;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_NB_IF:
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_IF:
|
||||
sspsp |= SSPSP_SCMODE(2);
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_NF:
|
||||
sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
sscr0 |= SSCR0_PSP;
|
||||
sscr1 |= SSCR1_RWOT | SSCR1_TRAIL;
|
||||
|
||||
/* See hw_params() */
|
||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
case SND_SOC_DAIFMT_NB_NF:
|
||||
sspsp |= SSPSP_SFRMP;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_NB_IF:
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_IF:
|
||||
sspsp |= SSPSP_SCMODE(2);
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_NF:
|
||||
sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
|
@ -489,22 +485,6 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
|
|||
case SND_SOC_DAIFMT_DSP_B:
|
||||
sscr0 |= SSCR0_MOD | SSCR0_PSP;
|
||||
sscr1 |= SSCR1_TRAIL | SSCR1_RWOT;
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
case SND_SOC_DAIFMT_NB_NF:
|
||||
sspsp |= SSPSP_SFRMP;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_NB_IF:
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_IF:
|
||||
sspsp |= SSPSP_SCMODE(2);
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_NF:
|
||||
sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -788,6 +788,45 @@ static int soc_resume(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_suspend_device: Notify core of device suspend
|
||||
*
|
||||
* @dev: Device being suspended.
|
||||
*
|
||||
* In order to ensure that the entire audio subsystem is suspended in a
|
||||
* coordinated fashion ASoC devices should suspend themselves when
|
||||
* called by ASoC. When the standard kernel suspend process asks the
|
||||
* device to suspend it should call this function to initiate a suspend
|
||||
* of the entire ASoC card.
|
||||
*
|
||||
* \note Currently this function is stubbed out.
|
||||
*/
|
||||
int snd_soc_suspend_device(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_suspend_device);
|
||||
|
||||
/**
|
||||
* snd_soc_resume_device: Notify core of device resume
|
||||
*
|
||||
* @dev: Device being resumed.
|
||||
*
|
||||
* In order to ensure that the entire audio subsystem is resumed in a
|
||||
* coordinated fashion ASoC devices should resume themselves when called
|
||||
* by ASoC. When the standard kernel resume process asks the device
|
||||
* to resume it should call this function. Once all the components of
|
||||
* the card have notified that they are ready to be resumed the card
|
||||
* will be resumed.
|
||||
*
|
||||
* \note Currently this function is stubbed out.
|
||||
*/
|
||||
int snd_soc_resume_device(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_resume_device);
|
||||
|
||||
#else
|
||||
#define soc_suspend NULL
|
||||
#define soc_resume NULL
|
||||
|
@ -981,6 +1020,21 @@ static int soc_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void soc_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_card *card = socdev->card;
|
||||
|
||||
if (!card->instantiated)
|
||||
return;
|
||||
|
||||
/* Flush out pmdown_time work - we actually do want to run it
|
||||
* now, we're shutting down so no imminent restart. */
|
||||
run_delayed_work(&card->delayed_work);
|
||||
|
||||
snd_soc_dapm_shutdown(socdev);
|
||||
}
|
||||
|
||||
/* ASoC platform driver */
|
||||
static struct platform_driver soc_driver = {
|
||||
.driver = {
|
||||
|
@ -991,6 +1045,7 @@ static struct platform_driver soc_driver = {
|
|||
.remove = soc_remove,
|
||||
.suspend = soc_suspend,
|
||||
.resume = soc_resume,
|
||||
.shutdown = soc_shutdown,
|
||||
};
|
||||
|
||||
/* create a new pcm */
|
||||
|
@ -1264,10 +1319,10 @@ EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec);
|
|||
* Returns 1 for change else 0.
|
||||
*/
|
||||
int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
|
||||
unsigned short mask, unsigned short value)
|
||||
unsigned int mask, unsigned int value)
|
||||
{
|
||||
int change;
|
||||
unsigned short old, new;
|
||||
unsigned int old, new;
|
||||
|
||||
mutex_lock(&io_mutex);
|
||||
old = snd_soc_read(codec, reg);
|
||||
|
@ -1294,10 +1349,10 @@ EXPORT_SYMBOL_GPL(snd_soc_update_bits);
|
|||
* Returns 1 for change else 0.
|
||||
*/
|
||||
int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
|
||||
unsigned short mask, unsigned short value)
|
||||
unsigned int mask, unsigned int value)
|
||||
{
|
||||
int change;
|
||||
unsigned short old, new;
|
||||
unsigned int old, new;
|
||||
|
||||
mutex_lock(&io_mutex);
|
||||
old = snd_soc_read(codec, reg);
|
||||
|
@ -1586,7 +1641,7 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
|
|||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||
unsigned short val, bitmask;
|
||||
unsigned int val, bitmask;
|
||||
|
||||
for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
|
||||
;
|
||||
|
@ -1615,8 +1670,8 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
|
|||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||
unsigned short val;
|
||||
unsigned short mask, bitmask;
|
||||
unsigned int val;
|
||||
unsigned int mask, bitmask;
|
||||
|
||||
for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
|
||||
;
|
||||
|
@ -1652,7 +1707,7 @@ int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol,
|
|||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||
unsigned short reg_val, val, mux;
|
||||
unsigned int reg_val, val, mux;
|
||||
|
||||
reg_val = snd_soc_read(codec, e->reg);
|
||||
val = (reg_val >> e->shift_l) & e->mask;
|
||||
|
@ -1691,8 +1746,8 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
|
|||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||
unsigned short val;
|
||||
unsigned short mask;
|
||||
unsigned int val;
|
||||
unsigned int mask;
|
||||
|
||||
if (ucontrol->value.enumerated.item[0] > e->max - 1)
|
||||
return -EINVAL;
|
||||
|
@ -1852,7 +1907,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
|
|||
int max = mc->max;
|
||||
unsigned int mask = (1 << fls(max)) - 1;
|
||||
unsigned int invert = mc->invert;
|
||||
unsigned short val, val2, val_mask;
|
||||
unsigned int val, val2, val_mask;
|
||||
|
||||
val = (ucontrol->value.integer.value[0] & mask);
|
||||
if (invert)
|
||||
|
@ -1918,7 +1973,7 @@ int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
|
|||
unsigned int reg2 = mc->rreg;
|
||||
unsigned int shift = mc->shift;
|
||||
int max = mc->max;
|
||||
unsigned int mask = (1<<fls(max))-1;
|
||||
unsigned int mask = (1 << fls(max)) - 1;
|
||||
unsigned int invert = mc->invert;
|
||||
|
||||
ucontrol->value.integer.value[0] =
|
||||
|
@ -1958,7 +2013,7 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
|
|||
unsigned int mask = (1 << fls(max)) - 1;
|
||||
unsigned int invert = mc->invert;
|
||||
int err;
|
||||
unsigned short val, val2, val_mask;
|
||||
unsigned int val, val2, val_mask;
|
||||
|
||||
val_mask = mask << shift;
|
||||
val = (ucontrol->value.integer.value[0] & mask);
|
||||
|
@ -2050,7 +2105,7 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
|
|||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
unsigned int reg = mc->reg;
|
||||
int min = mc->min;
|
||||
unsigned short val;
|
||||
unsigned int val;
|
||||
|
||||
val = (ucontrol->value.integer.value[0]+min) & 0xff;
|
||||
val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8;
|
||||
|
|
|
@ -52,19 +52,37 @@
|
|||
|
||||
/* dapm power sequences - make this per codec in the future */
|
||||
static int dapm_up_seq[] = {
|
||||
snd_soc_dapm_pre, snd_soc_dapm_supply, snd_soc_dapm_micbias,
|
||||
snd_soc_dapm_mic, snd_soc_dapm_mux, snd_soc_dapm_value_mux,
|
||||
snd_soc_dapm_dac, snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl,
|
||||
snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
|
||||
snd_soc_dapm_post
|
||||
[snd_soc_dapm_pre] = 0,
|
||||
[snd_soc_dapm_supply] = 1,
|
||||
[snd_soc_dapm_micbias] = 2,
|
||||
[snd_soc_dapm_mic] = 3,
|
||||
[snd_soc_dapm_mux] = 4,
|
||||
[snd_soc_dapm_value_mux] = 4,
|
||||
[snd_soc_dapm_dac] = 5,
|
||||
[snd_soc_dapm_mixer] = 6,
|
||||
[snd_soc_dapm_mixer_named_ctl] = 6,
|
||||
[snd_soc_dapm_pga] = 7,
|
||||
[snd_soc_dapm_adc] = 8,
|
||||
[snd_soc_dapm_hp] = 9,
|
||||
[snd_soc_dapm_spk] = 10,
|
||||
[snd_soc_dapm_post] = 11,
|
||||
};
|
||||
|
||||
static int dapm_down_seq[] = {
|
||||
snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
|
||||
snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer,
|
||||
snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias,
|
||||
snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_supply,
|
||||
snd_soc_dapm_post
|
||||
[snd_soc_dapm_pre] = 0,
|
||||
[snd_soc_dapm_adc] = 1,
|
||||
[snd_soc_dapm_hp] = 2,
|
||||
[snd_soc_dapm_spk] = 3,
|
||||
[snd_soc_dapm_pga] = 4,
|
||||
[snd_soc_dapm_mixer_named_ctl] = 5,
|
||||
[snd_soc_dapm_mixer] = 5,
|
||||
[snd_soc_dapm_dac] = 6,
|
||||
[snd_soc_dapm_mic] = 7,
|
||||
[snd_soc_dapm_micbias] = 8,
|
||||
[snd_soc_dapm_mux] = 9,
|
||||
[snd_soc_dapm_value_mux] = 9,
|
||||
[snd_soc_dapm_supply] = 10,
|
||||
[snd_soc_dapm_post] = 11,
|
||||
};
|
||||
|
||||
static void pop_wait(u32 pop_time)
|
||||
|
@ -268,7 +286,7 @@ static int dapm_connect_mixer(struct snd_soc_codec *codec,
|
|||
static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
|
||||
{
|
||||
int change, power;
|
||||
unsigned short old, new;
|
||||
unsigned int old, new;
|
||||
struct snd_soc_codec *codec = widget->codec;
|
||||
|
||||
/* check for valid widgets */
|
||||
|
@ -689,55 +707,213 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
|
|||
return power;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan a single DAPM widget for a complete audio path and update the
|
||||
* power status appropriately.
|
||||
*/
|
||||
static int dapm_power_widget(struct snd_soc_codec *codec, int event,
|
||||
struct snd_soc_dapm_widget *w)
|
||||
static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
|
||||
struct snd_soc_dapm_widget *b,
|
||||
int sort[])
|
||||
{
|
||||
int ret;
|
||||
if (sort[a->id] != sort[b->id])
|
||||
return sort[a->id] - sort[b->id];
|
||||
if (a->reg != b->reg)
|
||||
return a->reg - b->reg;
|
||||
|
||||
switch (w->id) {
|
||||
case snd_soc_dapm_pre:
|
||||
if (!w->event)
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (event == SND_SOC_DAPM_STREAM_START) {
|
||||
ret = w->event(w,
|
||||
NULL, SND_SOC_DAPM_PRE_PMU);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else if (event == SND_SOC_DAPM_STREAM_STOP) {
|
||||
ret = w->event(w,
|
||||
NULL, SND_SOC_DAPM_PRE_PMD);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* Insert a widget in order into a DAPM power sequence. */
|
||||
static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget,
|
||||
struct list_head *list,
|
||||
int sort[])
|
||||
{
|
||||
struct snd_soc_dapm_widget *w;
|
||||
|
||||
list_for_each_entry(w, list, power_list)
|
||||
if (dapm_seq_compare(new_widget, w, sort) < 0) {
|
||||
list_add_tail(&new_widget->power_list, &w->power_list);
|
||||
return;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case snd_soc_dapm_post:
|
||||
if (!w->event)
|
||||
return 0;
|
||||
list_add_tail(&new_widget->power_list, list);
|
||||
}
|
||||
|
||||
if (event == SND_SOC_DAPM_STREAM_START) {
|
||||
/* Apply the coalesced changes from a DAPM sequence */
|
||||
static void dapm_seq_run_coalesced(struct snd_soc_codec *codec,
|
||||
struct list_head *pending)
|
||||
{
|
||||
struct snd_soc_dapm_widget *w;
|
||||
int reg, power, ret;
|
||||
unsigned int value = 0;
|
||||
unsigned int mask = 0;
|
||||
unsigned int cur_mask;
|
||||
|
||||
reg = list_first_entry(pending, struct snd_soc_dapm_widget,
|
||||
power_list)->reg;
|
||||
|
||||
list_for_each_entry(w, pending, power_list) {
|
||||
cur_mask = 1 << w->shift;
|
||||
BUG_ON(reg != w->reg);
|
||||
|
||||
if (w->invert)
|
||||
power = !w->power;
|
||||
else
|
||||
power = w->power;
|
||||
|
||||
mask |= cur_mask;
|
||||
if (power)
|
||||
value |= cur_mask;
|
||||
|
||||
pop_dbg(codec->pop_time,
|
||||
"pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n",
|
||||
w->name, reg, value, mask);
|
||||
|
||||
/* power up pre event */
|
||||
if (w->power && w->event &&
|
||||
(w->event_flags & SND_SOC_DAPM_PRE_PMU)) {
|
||||
pop_dbg(codec->pop_time, "pop test : %s PRE_PMU\n",
|
||||
w->name);
|
||||
ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
|
||||
if (ret < 0)
|
||||
pr_err("%s: pre event failed: %d\n",
|
||||
w->name, ret);
|
||||
}
|
||||
|
||||
/* power down pre event */
|
||||
if (!w->power && w->event &&
|
||||
(w->event_flags & SND_SOC_DAPM_PRE_PMD)) {
|
||||
pop_dbg(codec->pop_time, "pop test : %s PRE_PMD\n",
|
||||
w->name);
|
||||
ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
|
||||
if (ret < 0)
|
||||
pr_err("%s: pre event failed: %d\n",
|
||||
w->name, ret);
|
||||
}
|
||||
|
||||
/* Lower PGA volume to reduce pops */
|
||||
if (w->id == snd_soc_dapm_pga && !w->power)
|
||||
dapm_set_pga(w, w->power);
|
||||
}
|
||||
|
||||
if (reg >= 0) {
|
||||
pop_dbg(codec->pop_time,
|
||||
"pop test : Applying 0x%x/0x%x to %x in %dms\n",
|
||||
value, mask, reg, codec->pop_time);
|
||||
pop_wait(codec->pop_time);
|
||||
snd_soc_update_bits(codec, reg, mask, value);
|
||||
}
|
||||
|
||||
list_for_each_entry(w, pending, power_list) {
|
||||
/* Raise PGA volume to reduce pops */
|
||||
if (w->id == snd_soc_dapm_pga && w->power)
|
||||
dapm_set_pga(w, w->power);
|
||||
|
||||
/* power up post event */
|
||||
if (w->power && w->event &&
|
||||
(w->event_flags & SND_SOC_DAPM_POST_PMU)) {
|
||||
pop_dbg(codec->pop_time, "pop test : %s POST_PMU\n",
|
||||
w->name);
|
||||
ret = w->event(w,
|
||||
NULL, SND_SOC_DAPM_POST_PMU);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else if (event == SND_SOC_DAPM_STREAM_STOP) {
|
||||
ret = w->event(w,
|
||||
NULL, SND_SOC_DAPM_POST_PMD);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
pr_err("%s: post event failed: %d\n",
|
||||
w->name, ret);
|
||||
}
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return dapm_generic_apply_power(w);
|
||||
/* power down post event */
|
||||
if (!w->power && w->event &&
|
||||
(w->event_flags & SND_SOC_DAPM_POST_PMD)) {
|
||||
pop_dbg(codec->pop_time, "pop test : %s POST_PMD\n",
|
||||
w->name);
|
||||
ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
|
||||
if (ret < 0)
|
||||
pr_err("%s: post event failed: %d\n",
|
||||
w->name, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Apply a DAPM power sequence.
|
||||
*
|
||||
* We walk over a pre-sorted list of widgets to apply power to. In
|
||||
* order to minimise the number of writes to the device required
|
||||
* multiple widgets will be updated in a single write where possible.
|
||||
* Currently anything that requires more than a single write is not
|
||||
* handled.
|
||||
*/
|
||||
static void dapm_seq_run(struct snd_soc_codec *codec, struct list_head *list,
|
||||
int event, int sort[])
|
||||
{
|
||||
struct snd_soc_dapm_widget *w, *n;
|
||||
LIST_HEAD(pending);
|
||||
int cur_sort = -1;
|
||||
int cur_reg = SND_SOC_NOPM;
|
||||
int ret;
|
||||
|
||||
list_for_each_entry_safe(w, n, list, power_list) {
|
||||
ret = 0;
|
||||
|
||||
/* Do we need to apply any queued changes? */
|
||||
if (sort[w->id] != cur_sort || w->reg != cur_reg) {
|
||||
if (!list_empty(&pending))
|
||||
dapm_seq_run_coalesced(codec, &pending);
|
||||
|
||||
INIT_LIST_HEAD(&pending);
|
||||
cur_sort = -1;
|
||||
cur_reg = SND_SOC_NOPM;
|
||||
}
|
||||
|
||||
switch (w->id) {
|
||||
case snd_soc_dapm_pre:
|
||||
if (!w->event)
|
||||
list_for_each_entry_safe_continue(w, n, list,
|
||||
power_list);
|
||||
|
||||
if (event == SND_SOC_DAPM_STREAM_START)
|
||||
ret = w->event(w,
|
||||
NULL, SND_SOC_DAPM_PRE_PMU);
|
||||
else if (event == SND_SOC_DAPM_STREAM_STOP)
|
||||
ret = w->event(w,
|
||||
NULL, SND_SOC_DAPM_PRE_PMD);
|
||||
break;
|
||||
|
||||
case snd_soc_dapm_post:
|
||||
if (!w->event)
|
||||
list_for_each_entry_safe_continue(w, n, list,
|
||||
power_list);
|
||||
|
||||
if (event == SND_SOC_DAPM_STREAM_START)
|
||||
ret = w->event(w,
|
||||
NULL, SND_SOC_DAPM_POST_PMU);
|
||||
else if (event == SND_SOC_DAPM_STREAM_STOP)
|
||||
ret = w->event(w,
|
||||
NULL, SND_SOC_DAPM_POST_PMD);
|
||||
break;
|
||||
|
||||
case snd_soc_dapm_input:
|
||||
case snd_soc_dapm_output:
|
||||
case snd_soc_dapm_hp:
|
||||
case snd_soc_dapm_mic:
|
||||
case snd_soc_dapm_line:
|
||||
case snd_soc_dapm_spk:
|
||||
/* No register support currently */
|
||||
ret = dapm_generic_apply_power(w);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Queue it up for application */
|
||||
cur_sort = sort[w->id];
|
||||
cur_reg = w->reg;
|
||||
list_move(&w->power_list, &pending);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
pr_err("Failed to apply widget power: %d\n",
|
||||
ret);
|
||||
}
|
||||
|
||||
if (!list_empty(&pending))
|
||||
dapm_seq_run_coalesced(codec, &pending);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan each dapm widget for complete audio path.
|
||||
* A complete path is a route that has valid endpoints i.e.:-
|
||||
|
@ -751,23 +927,22 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
|
|||
{
|
||||
struct snd_soc_device *socdev = codec->socdev;
|
||||
struct snd_soc_dapm_widget *w;
|
||||
LIST_HEAD(up_list);
|
||||
LIST_HEAD(down_list);
|
||||
int ret = 0;
|
||||
int i, power;
|
||||
int power;
|
||||
int sys_power = 0;
|
||||
|
||||
INIT_LIST_HEAD(&codec->up_list);
|
||||
INIT_LIST_HEAD(&codec->down_list);
|
||||
|
||||
/* Check which widgets we need to power and store them in
|
||||
* lists indicating if they should be powered up or down.
|
||||
*/
|
||||
list_for_each_entry(w, &codec->dapm_widgets, list) {
|
||||
switch (w->id) {
|
||||
case snd_soc_dapm_pre:
|
||||
list_add_tail(&codec->down_list, &w->power_list);
|
||||
dapm_seq_insert(w, &down_list, dapm_down_seq);
|
||||
break;
|
||||
case snd_soc_dapm_post:
|
||||
list_add_tail(&codec->up_list, &w->power_list);
|
||||
dapm_seq_insert(w, &up_list, dapm_up_seq);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -782,10 +957,9 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
|
|||
continue;
|
||||
|
||||
if (power)
|
||||
list_add_tail(&w->power_list, &codec->up_list);
|
||||
dapm_seq_insert(w, &up_list, dapm_up_seq);
|
||||
else
|
||||
list_add_tail(&w->power_list,
|
||||
&codec->down_list);
|
||||
dapm_seq_insert(w, &down_list, dapm_down_seq);
|
||||
|
||||
w->power = power;
|
||||
break;
|
||||
|
@ -802,32 +976,10 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
|
|||
}
|
||||
|
||||
/* Power down widgets first; try to avoid amplifying pops. */
|
||||
for (i = 0; i < ARRAY_SIZE(dapm_down_seq); i++) {
|
||||
list_for_each_entry(w, &codec->down_list, power_list) {
|
||||
/* is widget in stream order */
|
||||
if (w->id != dapm_down_seq[i])
|
||||
continue;
|
||||
|
||||
ret = dapm_power_widget(codec, event, w);
|
||||
if (ret != 0)
|
||||
pr_err("Failed to power down %s: %d\n",
|
||||
w->name, ret);
|
||||
}
|
||||
}
|
||||
dapm_seq_run(codec, &down_list, event, dapm_down_seq);
|
||||
|
||||
/* Now power up. */
|
||||
for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) {
|
||||
list_for_each_entry(w, &codec->up_list, power_list) {
|
||||
/* is widget in stream order */
|
||||
if (w->id != dapm_up_seq[i])
|
||||
continue;
|
||||
|
||||
ret = dapm_power_widget(codec, event, w);
|
||||
if (ret != 0)
|
||||
pr_err("Failed to power up %s: %d\n",
|
||||
w->name, ret);
|
||||
}
|
||||
}
|
||||
dapm_seq_run(codec, &up_list, event, dapm_up_seq);
|
||||
|
||||
/* If we just powered the last thing off drop to standby bias */
|
||||
if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) {
|
||||
|
@ -1372,7 +1524,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
|
|||
int max = mc->max;
|
||||
unsigned int mask = (1 << fls(max)) - 1;
|
||||
unsigned int invert = mc->invert;
|
||||
unsigned short val, val2, val_mask;
|
||||
unsigned int val, val2, val_mask;
|
||||
int ret;
|
||||
|
||||
val = (ucontrol->value.integer.value[0] & mask);
|
||||
|
@ -1436,7 +1588,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
|
|||
{
|
||||
struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
|
||||
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||
unsigned short val, bitmask;
|
||||
unsigned int val, bitmask;
|
||||
|
||||
for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
|
||||
;
|
||||
|
@ -1464,8 +1616,8 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
|
|||
{
|
||||
struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
|
||||
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||
unsigned short val, mux;
|
||||
unsigned short mask, bitmask;
|
||||
unsigned int val, mux;
|
||||
unsigned int mask, bitmask;
|
||||
int ret = 0;
|
||||
|
||||
for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
|
||||
|
@ -1523,7 +1675,7 @@ int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
|
|||
{
|
||||
struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
|
||||
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||
unsigned short reg_val, val, mux;
|
||||
unsigned int reg_val, val, mux;
|
||||
|
||||
reg_val = snd_soc_read(widget->codec, e->reg);
|
||||
val = (reg_val >> e->shift_l) & e->mask;
|
||||
|
@ -1563,8 +1715,8 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
|
|||
{
|
||||
struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
|
||||
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||
unsigned short val, mux;
|
||||
unsigned short mask;
|
||||
unsigned int val, mux;
|
||||
unsigned int mask;
|
||||
int ret = 0;
|
||||
|
||||
if (ucontrol->value.enumerated.item[0] > e->max - 1)
|
||||
|
@ -1880,6 +2032,35 @@ void snd_soc_dapm_free(struct snd_soc_device *socdev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
|
||||
|
||||
/*
|
||||
* snd_soc_dapm_shutdown - callback for system shutdown
|
||||
*/
|
||||
void snd_soc_dapm_shutdown(struct snd_soc_device *socdev)
|
||||
{
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
struct snd_soc_dapm_widget *w;
|
||||
LIST_HEAD(down_list);
|
||||
int powerdown = 0;
|
||||
|
||||
list_for_each_entry(w, &codec->dapm_widgets, list) {
|
||||
if (w->power) {
|
||||
dapm_seq_insert(w, &down_list, dapm_down_seq);
|
||||
powerdown = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* If there were no widgets to power down we're already in
|
||||
* standby.
|
||||
*/
|
||||
if (powerdown) {
|
||||
snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_PREPARE);
|
||||
dapm_seq_run(codec, &down_list, 0, dapm_down_seq);
|
||||
snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_STANDBY);
|
||||
}
|
||||
|
||||
snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_OFF);
|
||||
}
|
||||
|
||||
/* Module information */
|
||||
MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
|
||||
MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
|
||||
|
|
Loading…
Reference in a new issue