Creation of Cybook 2416 (actually Gen4) repository
This commit is contained in:
43
sound/soc/codecs/Kconfig
Normal file
43
sound/soc/codecs/Kconfig
Normal file
@@ -0,0 +1,43 @@
|
||||
config SND_SOC_AC97_CODEC
|
||||
tristate
|
||||
depends on SND_SOC
|
||||
|
||||
config SND_SOC_WM8580
|
||||
tristate
|
||||
depends on SND_SOC
|
||||
|
||||
config SND_SOC_WM8731
|
||||
tristate
|
||||
depends on SND_SOC
|
||||
|
||||
config SND_SOC_WM8750
|
||||
tristate
|
||||
depends on SND_SOC
|
||||
|
||||
config SND_SOC_WM8753
|
||||
tristate
|
||||
depends on SND_SOC
|
||||
|
||||
config SND_SOC_WM8772
|
||||
tristate
|
||||
depends on SND_SOC
|
||||
|
||||
config SND_SOC_WM8990
|
||||
tristate
|
||||
depends on SND_SOC
|
||||
|
||||
config SND_SOC_WM9712
|
||||
tristate
|
||||
depends on SND_SOC
|
||||
|
||||
config SND_SOC_WM9713
|
||||
tristate
|
||||
depends on SND_SOC
|
||||
|
||||
config SND_SOC_RT5627
|
||||
tristate
|
||||
depends on SND_SOC
|
||||
|
||||
config SND_SOC_RT5624
|
||||
tristate
|
||||
depends on SND_SOC
|
||||
46
sound/soc/codecs/Makefile
Normal file
46
sound/soc/codecs/Makefile
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
snd-soc-rt5627-objs := rt5627.o
|
||||
snd-soc-rt5624-objs := rt5624.o
|
||||
snd-soc-ac97-objs := ac97.o
|
||||
snd-soc-wm8580-objs := wm8580.o
|
||||
snd-soc-wm8731-objs := wm8731.o
|
||||
snd-soc-wm8750-objs := wm8750.o
|
||||
snd-soc-wm8753-objs := wm8753.o
|
||||
snd-soc-wm8772-objs := wm8772.o
|
||||
snd-soc-wm8900-objs := wm8900.o
|
||||
snd-soc-wm8950-objs := wm8950.o
|
||||
snd-soc-wm8951-objs := wm8951.o
|
||||
snd-soc-wm8956-objs := wm8956.o
|
||||
snd-soc-wm8960-objs := wm8960.o
|
||||
snd-soc-wm8971-objs := wm8971.o
|
||||
snd-soc-wm8974-objs := wm8974.o
|
||||
snd-soc-wm8976-objs := wm8976.o
|
||||
snd-soc-wm8978-objs := wm8978.o
|
||||
snd-soc-wm8980-objs := wm8980.o
|
||||
snd-soc-wm8990-objs := wm8990.o
|
||||
snd-soc-wm8991-objs := wm8991.o
|
||||
snd-soc-wm9712-objs := wm9712.o
|
||||
snd-soc-wm9713-objs := wm9713.o
|
||||
|
||||
|
||||
obj-$(CONFIG_SND_SOC_RT5627) += snd-soc-rt5627.o
|
||||
obj-$(CONFIG_SND_SOC_RT5624) += snd-soc-rt5624.o
|
||||
obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
|
||||
obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o
|
||||
obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
|
||||
obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
|
||||
obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
|
||||
obj-$(CONFIG_SND_SOC_WM8772) += snd-soc-wm8772.o
|
||||
obj-$(CONFIG_SND_SOC_WM8950) += snd-soc-wm8950.o
|
||||
obj-$(CONFIG_SND_SOC_WM8951) += snd-soc-wm8951.o
|
||||
obj-$(CONFIG_SND_SOC_WM8956) += snd-soc-wm8956.o
|
||||
obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o
|
||||
obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o
|
||||
obj-$(CONFIG_SND_SOC_WM8974) += snd-soc-wm8974.o
|
||||
obj-$(CONFIG_SND_SOC_WM8976) += snd-soc-wm8976.o
|
||||
obj-$(CONFIG_SND_SOC_WM8978) += snd-soc-wm8978.o
|
||||
obj-$(CONFIG_SND_SOC_WM8980) += snd-soc-wm8980.o
|
||||
obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o
|
||||
obj-$(CONFIG_SND_SOC_WM8991) += snd-soc-wm8991.o
|
||||
obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
|
||||
obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o
|
||||
158
sound/soc/codecs/ac97.c
Normal file
158
sound/soc/codecs/ac97.c
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* ac97.c -- ALSA Soc AC97 codec support
|
||||
*
|
||||
* Copyright 2005 Wolfson Microelectronics PLC.
|
||||
* Author: Liam Girdwood
|
||||
* liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Revision history
|
||||
* 17th Oct 2005 Initial version.
|
||||
*
|
||||
* Generic AC97 support.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/ac97_codec.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
#define AC97_VERSION "0.6"
|
||||
|
||||
static int ac97_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_device *socdev = rtd->socdev;
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
|
||||
int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
|
||||
AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
|
||||
return snd_ac97_set_rate(codec->ac97, reg, runtime->rate);
|
||||
}
|
||||
|
||||
#define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
|
||||
SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
|
||||
|
||||
struct snd_soc_codec_dai ac97_dai = {
|
||||
.name = "AC97 HiFi",
|
||||
.type = SND_SOC_DAI_AC97,
|
||||
.playback = {
|
||||
.stream_name = "AC97 Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = STD_AC97_RATES,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
|
||||
.capture = {
|
||||
.stream_name = "AC97 Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = STD_AC97_RATES,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
|
||||
.ops = {
|
||||
.prepare = ac97_prepare,},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(ac97_dai);
|
||||
|
||||
static unsigned int ac97_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
return soc_ac97_ops.read(codec->ac97, reg);
|
||||
}
|
||||
|
||||
static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int val)
|
||||
{
|
||||
soc_ac97_ops.write(codec->ac97, reg, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ac97_soc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec;
|
||||
struct snd_ac97_bus *ac97_bus;
|
||||
struct snd_ac97_template ac97_template;
|
||||
int ret = 0;
|
||||
|
||||
printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION);
|
||||
|
||||
socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
|
||||
if (socdev->codec == NULL)
|
||||
return -ENOMEM;
|
||||
codec = socdev->codec;
|
||||
mutex_init(&codec->mutex);
|
||||
|
||||
codec->name = "AC97";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->dai = &ac97_dai;
|
||||
codec->num_dai = 1;
|
||||
codec->write = ac97_write;
|
||||
codec->read = ac97_read;
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
|
||||
/* register pcms */
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
if(ret < 0)
|
||||
goto err;
|
||||
|
||||
/* add codec as bus device for standard ac97 */
|
||||
ret = snd_ac97_bus(codec->card, 0, &soc_ac97_ops, NULL, &ac97_bus);
|
||||
if(ret < 0)
|
||||
goto bus_err;
|
||||
|
||||
memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
|
||||
ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97);
|
||||
if(ret < 0)
|
||||
goto bus_err;
|
||||
|
||||
ret = snd_soc_register_card(socdev);
|
||||
if (ret < 0)
|
||||
goto bus_err;
|
||||
return 0;
|
||||
|
||||
bus_err:
|
||||
snd_soc_free_pcms(socdev);
|
||||
|
||||
err:
|
||||
kfree(socdev->codec->reg_cache);
|
||||
kfree(socdev->codec);
|
||||
socdev->codec = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ac97_soc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
|
||||
if(codec == NULL)
|
||||
return 0;
|
||||
|
||||
snd_soc_free_pcms(socdev);
|
||||
kfree(socdev->codec->reg_cache);
|
||||
kfree(socdev->codec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_ac97= {
|
||||
.probe = ac97_soc_probe,
|
||||
.remove = ac97_soc_remove,
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL_GPL(soc_codec_dev_ac97);
|
||||
|
||||
MODULE_DESCRIPTION("Soc Generic AC97 driver");
|
||||
MODULE_AUTHOR("Liam Girdwood");
|
||||
MODULE_LICENSE("GPL");
|
||||
19
sound/soc/codecs/ac97.h
Normal file
19
sound/soc/codecs/ac97.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* linux/sound/codecs/ac97.h -- ALSA SoC Layer
|
||||
*
|
||||
* Author: Liam Girdwood
|
||||
* Created: Dec 1st 2005
|
||||
* Copyright: Wolfson Microelectronics. PLC.
|
||||
*
|
||||
* 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 __LINUX_SND_SOC_AC97_H
|
||||
#define __LINUX_SND_SOC_AC97_H
|
||||
|
||||
extern struct snd_soc_codec_device soc_codec_dev_ac97;
|
||||
extern struct snd_soc_codec_dai ac97_dai;
|
||||
|
||||
#endif
|
||||
3204
sound/soc/codecs/rt5624.c
Normal file
3204
sound/soc/codecs/rt5624.c
Normal file
File diff suppressed because it is too large
Load Diff
609
sound/soc/codecs/rt5624.h
Normal file
609
sound/soc/codecs/rt5624.h
Normal file
@@ -0,0 +1,609 @@
|
||||
/*
|
||||
* rt5624.h -- audio driver for RT5624
|
||||
*
|
||||
* Copyright 2008 Realtek Microelectronics
|
||||
*
|
||||
* Author: flove <flove@realtek.com>
|
||||
*
|
||||
* Based on WM8753.h
|
||||
*
|
||||
* 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 _RT5624_H
|
||||
#define _RT5624_H
|
||||
|
||||
|
||||
//Index of Codec Register definition
|
||||
#define RT5624_RESET 0X00 //RESET CODEC TO DEFAULT
|
||||
#define RT5624_SPK_OUT_VOL 0X02 //SPEAKER OUT VOLUME
|
||||
#define RT5624_HP_OUT_VOL 0X04 //HEADPHONE OUTPUT VOLUME
|
||||
#define RT5624_PHONEIN_MONO_OUT_VOL 0X08 //PHONE INPUT/MONO OUTPUT VOLUME
|
||||
#define RT5624_LINE_IN_VOL 0X0A //LINE IN VOLUME
|
||||
#define RT5624_STEREO_DAC_VOL 0X0C //STEREO DAC VOLUME
|
||||
#define RT5624_MIC_VOL 0X0E //MICROPHONE VOLUME
|
||||
#define RT5624_MIC_ROUTING_CTRL 0X10 //MIC ROUTING CONTROL
|
||||
#define RT5624_ADC_REC_GAIN 0X12 //ADC RECORD GAIN
|
||||
#define RT5624_ADC_REC_MIXER 0X14 //ADC RECORD MIXER CONTROL
|
||||
#define RT5624_VOICE_DAC_OUT_VOL 0X18 //VOICE DAC OUTPUT VOLUME
|
||||
#define RT5624_OUTPUT_MIXER_CTRL 0X1C //OUTPUT MIXER CONTROL
|
||||
#define RT5624_MIC_CTRL 0X22 //MICROPHONE CONTROL
|
||||
#define RT5624_PD_CTRL_STAT 0X26 //POWER DOWN CONTROL/STATUS
|
||||
#define RT5624_MAIN_SDP_CTRL 0X34 //MAIN SERIAL DATA PORT CONTROL(STEREO I2S)
|
||||
#define RT5624_EXTEND_SDP_CTRL 0X36 //EXTEND SERIAL DATA PORT CONTROL(VOICE I2S/PCM)
|
||||
#define RT5624_PWR_MANAG_ADD1 0X3A //POWER MANAGMENT ADDITION 1
|
||||
#define RT5624_PWR_MANAG_ADD2 0X3C //POWER MANAGMENT ADDITION 2
|
||||
#define RT5624_PWR_MANAG_ADD3 0X3E //POWER MANAGMENT ADDITION 3
|
||||
#define RT5624_GEN_CTRL_REG1 0X40 //GENERAL PURPOSE CONTROL REGISTER 1
|
||||
#define RT5624_GEN_CTRL_REG2 0X42 //GENERAL PURPOSE CONTROL REGISTER 2
|
||||
#define RT5624_PLL_CTRL 0X44 //PLL CONTROL
|
||||
#define RT5624_GPIO_PIN_CONFIG 0X4C //GPIO PIN CONFIGURATION
|
||||
#define RT5624_GPIO_PIN_POLARITY 0X4E //GPIO PIN POLARITY
|
||||
#define RT5624_GPIO_PIN_STICKY 0X50 //GPIO PIN STICKY
|
||||
#define RT5624_GPIO_PIN_WAKEUP 0X52 //GPIO PIN WAKE UP
|
||||
#define RT5624_GPIO_PIN_STATUS 0X54 //GPIO PIN STATUS
|
||||
#define RT5624_GPIO_PIN_SHARING 0X56 //GPIO PIN SHARING
|
||||
#define RT5624_OVER_TEMP_CURR_STATUS 0X58 //OVER TEMPERATURE AND CURRENT STATUS
|
||||
#define RT5624_GPIO_OUT_CTRL 0X5C //GPIO OUTPUT PIN CONTRL
|
||||
#define RT5624_MISC_CTRL 0X5E //MISC CONTROL
|
||||
#define RT5624_STEREO_DAC_CLK_CTRL1 0X60 //STEREO DAC CLOCK CONTROL 1
|
||||
#define RT5624_STEREO_DAC_CLK_CTRL2 0X62 //STEREO DAC CLOCK CONTROL 2
|
||||
#define RT5624_VOICE_DAC_PCMCLK_CTRL1 0X64 //VOICE/PCM DAC CLOCK CONTROL 1
|
||||
#define RT5624_VOICE_DAC_PCMCLK_CTRL2 0X66 //VOICE/PCM DAC CLOCK CONTROL 2
|
||||
#define RT5624_PSEDUEO_SPATIAL_CTRL 0X68 //PSEDUEO STEREO /SPATIAL EFFECT BLOCK CONTROL
|
||||
#define RT5624_INDEX_ADDRESS 0X6A //INDEX ADDRESS
|
||||
#define RT5624_INDEX_DATA 0X6C //INDEX DATA
|
||||
#define RT5624_EQ_STATUS 0X6E //EQ STATUS
|
||||
#define RT5624_VENDOR_ID1 0x7C //VENDOR ID1
|
||||
#define RT5624_VENDOR_ID2 0x7E //VENDOR ID2
|
||||
|
||||
//*************************************************************************************************
|
||||
//Bit define of Codec Register
|
||||
//*************************************************************************************************
|
||||
//global definition
|
||||
#define RT_L_MUTE (0x1<<15) //Mute Left Control
|
||||
#define RT_L_ZC (0x1<<14) //Mute Left Zero-Cross Detector Control
|
||||
#define RT_R_MUTE (0x1<<7) //Mute Right Control
|
||||
#define RT_R_ZC (0x1<<6) //Mute Right Zero-Cross Detector Control
|
||||
#define RT_M_HP_MIXER (0x1<<15) //Mute source to HP Mixer
|
||||
#define RT_M_SPK_MIXER (0x1<<14) //Mute source to Speaker Mixer
|
||||
#define RT_M_MONO_MIXER (0x1<<13) //Mute source to Mono Mixer
|
||||
|
||||
//Phone Input/MONO Output Volume(0x08)
|
||||
#define M_PHONEIN_TO_HP_MIXER (0x1<<15) //Mute Phone In volume to HP mixer
|
||||
#define M_PHONEIN_TO_SPK_MIXER (0x1<<14) //Mute Phone In volume to speaker mixer
|
||||
#define M_MONO_OUT_VOL (0x1<<7) //Mute Mono output volume
|
||||
|
||||
|
||||
//Mic Routing Control(0x10)
|
||||
#define M_MIC1_TO_HP_MIXER (0x1<<15) //Mute MIC1 to HP mixer
|
||||
#define M_MIC1_TO_SPK_MIXER (0x1<<14) //Mute MiC1 to SPK mixer
|
||||
#define M_MIC1_TO_MONO_MIXER (0x1<<13) //Mute MIC1 to MONO mixer
|
||||
#define MIC1_DIFF_INPUT_CTRL (0x1<<12) //MIC1 different input control
|
||||
#define M_MIC2_TO_HP_MIXER (0x1<<7) //Mute MIC2 to HP mixer
|
||||
#define M_MIC2_TO_SPK_MIXER (0x1<<6) //Mute MiC2 to SPK mixer
|
||||
#define M_MIC2_TO_MONO_MIXER (0x1<<5) //Mute MIC2 to MONO mixer
|
||||
#define MIC2_DIFF_INPUT_CTRL (0x1<<4) //MIC2 different input control
|
||||
|
||||
//ADC Record Gain(0x12)
|
||||
#define M_ADC_L_TO_HP_MIXER (0x1<<15) //Mute left of ADC to HP Mixer
|
||||
#define M_ADC_R_TO_HP_MIXER (0x1<<14) //Mute right of ADC to HP Mixer
|
||||
#define M_ADC_L_TO_MONO_MIXER (0x1<<13) //Mute left of ADC to MONO Mixer
|
||||
#define M_ADC_R_TO_MONO_MIXER (0x1<<12) //Mute right of ADC to MONO Mixer
|
||||
#define ADC_L_GAIN_MASK (0x1f<<7) //ADC Record Gain Left channel Mask
|
||||
#define ADC_L_ZC_DET (0x1<<6) //ADC Zero-Cross Detector Control
|
||||
#define ADC_R_ZC_DET (0x1<<5) //ADC Zero-Cross Detector Control
|
||||
#define ADC_R_GAIN_MASK (0x1f<<0) //ADC Record Gain Right channel Mask
|
||||
|
||||
//Voice DAC Output Volume(0x18)
|
||||
#define M_V_DAC_TO_HP_MIXER (0x1<<15)
|
||||
#define M_V_DAC_TO_SPK_MIXER (0x1<<14)
|
||||
#define M_V_DAC_TO_MONO_MIXER (0x1<<13)
|
||||
|
||||
//Output Mixer Control(0x1C)
|
||||
#define SPKL_INPUT_SEL_MASK (0x3<<14)
|
||||
#define SPKL_INPUT_SEL_MONO (0x3<<14)
|
||||
#define SPKL_INPUT_SEL_SPK (0x2<<14)
|
||||
#define SPKL_INPUT_SEL_HPL (0x1<<14)
|
||||
#define SPKL_INPUT_SEL_VMID (0x0<<14)
|
||||
|
||||
#define SPK_OUT_SEL_CLASS_D (0x1<<13)
|
||||
#define SPK_OUT_SEL_CLASS_AB (0x0<<13)
|
||||
|
||||
#define SPKR_INPUT_SEL_MASK (0x3<<11)
|
||||
#define SPKR_INPUT_SEL_MONO_MIXER (0x3<<11)
|
||||
#define SPKR_INPUT_SEL_SPK_MIXER (0x2<<11)
|
||||
#define SPKR_INPUT_SEL_HPR_MIXER (0x1<<11)
|
||||
#define SPKR_INPUT_SEL_VMID (0x0<<11)
|
||||
|
||||
#define HPL_INPUT_SEL_HPL_MIXER (0x1<<9)
|
||||
#define HPR_INPUT_SEL_HPR_MIXER (0x1<<8)
|
||||
|
||||
#define MONO_INPUT_SEL_MASK (0x3<<6)
|
||||
#define MONO_INPUT_SEL_MONO_MIXER (0x3<<6)
|
||||
#define MONO_INPUT_SEL_SPK_MIXER (0x2<<6)
|
||||
#define MONO_INPUT_SEL_HP_MIXER (0x1<<6)
|
||||
#define MONO_INPUT_SEL_VMID (0x0<<6)
|
||||
|
||||
//Micphone Control define(0x22)
|
||||
#define MIC1 1
|
||||
#define MIC2 2
|
||||
#define MIC_BIAS_90_PRECNET_AVDD 1
|
||||
#define MIC_BIAS_75_PRECNET_AVDD 2
|
||||
|
||||
#define MIC1_BOOST_CONTROL_MASK (0x3<<10)
|
||||
#define MIC1_BOOST_CONTROL_BYPASS (0x0<<10)
|
||||
#define MIC1_BOOST_CONTROL_20DB (0x1<<10)
|
||||
#define MIC1_BOOST_CONTROL_30DB (0x2<<10)
|
||||
#define MIC1_BOOST_CONTROL_40DB (0x3<<10)
|
||||
|
||||
#define MIC2_BOOST_CONTROL_MASK (0x3<<8)
|
||||
#define MIC2_BOOST_CONTROL_BYPASS (0x0<<8)
|
||||
#define MIC2_BOOST_CONTROL_20DB (0x1<<8)
|
||||
#define MIC2_BOOST_CONTROL_30DB (0x2<<8)
|
||||
#define MIC2_BOOST_CONTROL_40DB (0x3<<8)
|
||||
|
||||
#define MIC1_BIAS_VOLT_CTRL_MASK (0x1<<5)
|
||||
#define MIC1_BIAS_VOLT_CTRL_90P (0x0<<5)
|
||||
#define MIC1_BIAS_VOLT_CTRL_75P (0x1<<5)
|
||||
|
||||
#define MIC2_BIAS_VOLT_CTRL_MASK (0x1<<4)
|
||||
#define MIC2_BIAS_VOLT_CTRL_90P (0x0<<4)
|
||||
#define MIC2_BIAS_VOLT_CTRL_75P (0x1<<4)
|
||||
|
||||
//PowerDown control of register(0x26)
|
||||
//power management bits
|
||||
#define RT_PWR_PR7 (0x1<<15) //write this bit to power down the Speaker Amplifier
|
||||
#define RT_PWR_PR6 (0x1<<14) //write this bit to power down the Headphone Out and MonoOut
|
||||
#define RT_PWR_PR5 (0x1<<13) //write this bit to power down the internal clock(without PLL)
|
||||
#define RT_PWR_PR3 (0x1<<11) //write this bit to power down the mixer(vref/vrefout out off)
|
||||
#define RT_PWR_PR2 (0x1<<10) //write this bit to power down the mixer(vref/vrefout still on)
|
||||
#define RT_PWR_PR1 (0x1<<9) //write this bit to power down the dac
|
||||
#define RT_PWR_PR0 (0x1<<8) //write this bit to power down the adc
|
||||
#define RT_PWR_REF (0x1<<3) //read only
|
||||
#define RT_PWR_ANL (0x1<<2) //read only
|
||||
#define RT_PWR_DAC (0x1<<1) //read only
|
||||
#define RT_PWR_ADC (0x1) //read only
|
||||
|
||||
|
||||
//Main Serial Data Port Control(0x34)
|
||||
#define MAIN_I2S_MODE_SEL (0x1<<15) //0:Master mode 1:Slave mode
|
||||
#define MAIN_I2S_SADLRCK_CTRL (0x1<<14) //0:Disable,ADC and DAC use the same fs,1:Enable
|
||||
#define MAIN_I2S_BCLK_POLARITY (0x1<<12) //0:Normal 1:Invert
|
||||
#define MAIN_I2S_DA_CLK_SOUR (0x1<<11) //0:from DA Filter,1:from DA Sigma Delta Clock Divider
|
||||
|
||||
//I2S DA SIGMA delta clock divider
|
||||
#define MAIN_I2S_CLK_DIV_MASK (0x7<<8)
|
||||
#define MAIN_I2S_CLK_DIV_2 (0x0<<8)
|
||||
#define MAIN_I2S_CLK_DIV_4 (0x1<<8)
|
||||
#define MAIN_I2S_CLK_DIV_8 (0x2<<8)
|
||||
#define MAIN_I2S_CLK_DIV_16 (0x3<<8)
|
||||
#define MAIN_I2S_CLK_DIV_32 (0x4<<8)
|
||||
#define MAIN_I2S_CLK_DIV_64 (0x5<<8)
|
||||
|
||||
#define MAIN_I2S_PCM_MODE (0x1<<6) //PCM 0:mode A ,1:mode B
|
||||
//Non PCM 0:Normal SADLRCK/SDALRCK,1:Invert SADLRCK/SDALRCK
|
||||
//Data Length Slection
|
||||
#define MAIN_I2S_DL_MASK (0x3<<2) //main i2s Data Length mask
|
||||
#define MAIN_I2S_DL_16 (0x0<<2) //16 bits
|
||||
#define MAIN_I2S_DL_20 (0x1<<2) //20 bits
|
||||
#define MAIN_I2S_DL_24 (0x2<<2) //24 bits
|
||||
#define MAIN_I2S_DL_32 (0x3<<2) //32 bits
|
||||
|
||||
//PCM Data Format Selection
|
||||
#define MAIN_I2S_DF_MASK (0x3) //main i2s Data Format mask
|
||||
#define MAIN_I2S_DF_I2S (0x0) //I2S FORMAT
|
||||
#define MAIN_I2S_DF_RIGHT (0x1) //RIGHT JUSTIFIED format
|
||||
#define MAIN_I2S_DF_LEFT (0x2) //LEFT JUSTIFIED format
|
||||
#define MAIN_I2S_DF_PCM (0x3) //PCM format
|
||||
|
||||
//Extend Serial Data Port Control(0x36)
|
||||
#define EXT_I2S_FUNC_ENABLE (0x1<<15) //Enable PCM interface on GPIO 1,3,4,5 0:GPIO function,1:Voice PCM interface
|
||||
#define EXT_I2S_MODE_SEL (0x1<<14) //0:Master ,1:Slave
|
||||
#define EXT_I2S_VOICE_ADC_EN (0x1<<8) //ADC_L=Stereo, ADC_R=Voice
|
||||
#define EXT_I2S_BCLK_POLARITY (0x1<<7) //0:Normal 1:Invert
|
||||
#define EXT_I2S_PCM_MODE (0x1<<6) //PCM 0:mode A ,1:mode B
|
||||
//Non PCM 0:Normal SADLRCK/SDALRCK,1:Invert SADLRCK/SDALRCK
|
||||
//Data Length Slection
|
||||
#define EXT_I2S_DL_MASK (0x3<<2) //Extend i2s Data Length mask
|
||||
#define EXT_I2S_DL_32 (0x3<<2) //32 bits
|
||||
#define EXT_I2S_DL_24 (0x2<<2) //24 bits
|
||||
#define EXT_I2S_DL_20 (0x1<<2) //20 bits
|
||||
#define EXT_I2S_DL_16 (0x0<<2) //16 bits
|
||||
|
||||
//Voice Data Format
|
||||
#define EXT_I2S_DF_MASK (0x3) //Extend i2s Data Format mask
|
||||
#define EXT_I2S_DF_I2S (0x0) //I2S FORMAT
|
||||
#define EXT_I2S_DF_RIGHT (0x1) //RIGHT JUSTIFIED format
|
||||
#define EXT_I2S_DF_LEFT (0x2) //LEFT JUSTIFIED format
|
||||
#define EXT_I2S_DF_PCM (0x3) //PCM format
|
||||
|
||||
//Power managment addition 1 (0x3A),0:Disable,1:Enable
|
||||
#define PWR_HI_R_LOAD_MONO (0x1<<15)
|
||||
#define PWR_HI_R_LOAD_HP (0x1<<14)
|
||||
#define PWR_ZC_DET_PD (0x1<<13)
|
||||
#define PWR_MAIN_I2S (0x1<<11)
|
||||
#define PWR_MIC_BIAS1_DET (0x1<<5)
|
||||
#define PWR_MIC_BIAS2_DET (0x1<<4)
|
||||
#define PWR_MIC_BIAS1 (0x1<<3)
|
||||
#define PWR_MIC_BIAS2 (0x1<<2)
|
||||
#define PWR_MAIN_BIAS (0x1<<1)
|
||||
#define PWR_DAC_REF (0x1)
|
||||
|
||||
|
||||
//Power managment addition 2(0x3C),0:Disable,1:Enable
|
||||
#define EN_THREMAL_SHUTDOWN (0x1<<15)
|
||||
#define PWR_CLASS_AB (0x1<<14)
|
||||
#define PWR_MIXER_VREF (0x1<<13)
|
||||
#define PWR_PLL (0x1<<12)
|
||||
#define PWR_VOICE_CLOCK (0x1<<10)
|
||||
#define PWR_L_DAC_CLK (0x1<<9)
|
||||
#define PWR_R_DAC_CLK (0x1<<8)
|
||||
#define PWR_L_ADC_CLK_GAIN (0x1<<7)
|
||||
#define PWR_R_ADC_CLK_GAIN (0x1<<6)
|
||||
#define PWR_L_HP_MIXER (0x1<<5)
|
||||
#define PWR_R_HP_MIXER (0x1<<4)
|
||||
#define PWR_SPK_MIXER (0x1<<3)
|
||||
#define PWR_MONO_MIXER (0x1<<2)
|
||||
#define PWR_L_ADC_REC_MIXER (0x1<<1)
|
||||
#define PWR_R_ADC_REC_MIXER (0x1)
|
||||
|
||||
|
||||
//Power managment addition 3(0x3E),0:Disable,1:Enable
|
||||
#define PWR_MONO_VOL (0x1<<14)
|
||||
#define PWR_SPK_LN_OUT (0x1<<13)
|
||||
#define PWR_SPK_RN_OUT (0x1<<12)
|
||||
#define PWR_HP_L_OUT (0x1<<11)
|
||||
#define PWR_HP_R_OUT (0x1<<10)
|
||||
#define PWR_SPK_L_OUT (0x1<<9)
|
||||
#define PWR_SPK_R_OUT (0x1<<8)
|
||||
#define PWR_LINE_IN_L (0x1<<7)
|
||||
#define PWR_LINE_IN_R (0x1<<6)
|
||||
#define PWR_PHONE_MIXER (0x1<<5)
|
||||
#define PWR_PHONE_VOL (0x1<<4)
|
||||
#define PWR_MIC1_VOL_CTRL (0x1<<3)
|
||||
#define PWR_MIC2_VOL_CTRL (0x1<<2)
|
||||
#define PWR_MIC1_BOOST (0x1<<1)
|
||||
#define PWR_MIC2_BOOST (0x1)
|
||||
|
||||
//General Purpose Control Register 1(0x40)
|
||||
#define GP_CLK_FROM_PLL (0x1<<15) //Clock source from PLL output
|
||||
#define GP_CLK_FROM_MCLK (0x0<<15) //Clock source from MCLK output
|
||||
|
||||
#define GP_HP_AMP_CTRL_MASK (0x3<<8)
|
||||
#define GP_HP_AMP_CTRL_RATIO_100 (0x0<<8) //1.00 Vdd
|
||||
#define GP_HP_AMP_CTRL_RATIO_125 (0x1<<8) //1.25 Vdd
|
||||
#define GP_HP_AMP_CTRL_RATIO_150 (0x2<<8) //1.50 Vdd
|
||||
|
||||
#define GP_SPK_D_AMP_CTRL_MASK (0x3<<6)
|
||||
#define GP_SPK_D_AMP_CTRL_RATIO_175 (0x0<<6) //1.75 Vdd
|
||||
#define GP_SPK_D_AMP_CTRL_RATIO_150 (0x1<<6) //1.50 Vdd
|
||||
#define GP_SPK_D_AMP_CTRL_RATIO_125 (0x2<<6) //1.25 Vdd
|
||||
#define GP_SPK_D_AMP_CTRL_RATIO_100 (0x3<<6) //1.00 Vdd
|
||||
|
||||
#define GP_SPK_AB_AMP_CTRL_MASK (0x7<<3)
|
||||
#define GP_SPK_AB_AMP_CTRL_RATIO_225 (0x0<<3) //2.25 Vdd
|
||||
#define GP_SPK_AB_AMP_CTRL_RATIO_200 (0x1<<3) //2.00 Vdd
|
||||
#define GP_SPK_AB_AMP_CTRL_RATIO_175 (0x2<<3) //1.75 Vdd
|
||||
#define GP_SPK_AB_AMP_CTRL_RATIO_150 (0x3<<3) //1.50 Vdd
|
||||
#define GP_SPK_AB_AMP_CTRL_RATIO_125 (0x4<<3) //1.25 Vdd
|
||||
#define GP_SPK_AB_AMP_CTRL_RATIO_100 (0x5<<3) //1.00 Vdd
|
||||
|
||||
//General Purpose Control Register 2(0x42)
|
||||
#define GP2_VOICE_TO_DIG_PATH_EN (0x1<<15)
|
||||
#define GP2_CLASS_AB_SEL_DIFF (0x0<<13) //Differential Mode of Class AB
|
||||
#define GP2_CLASS_D_SEL_SINGLE (0x1<<13) //Single End mode of Class AB
|
||||
#define GP2_PLL_PRE_DIV_1 (0x0<<0) //PLL pre-Divider 1
|
||||
#define GP2_PLL_PRE_DIV_2 (0x1<<0) //PLL pre-Divider 2
|
||||
|
||||
//PLL Control(0x44)
|
||||
#define PLL_M_CODE_MASK 0xF //PLL M code mask
|
||||
#define PLL_K_CODE_MASK (0x7<<4) //PLL K code mask
|
||||
#define PLL_BYPASS_N (0x1<<7) //bypass PLL N code
|
||||
#define PLL_N_CODE_MASK (0xFF<<8) //PLL N code mask
|
||||
|
||||
#define PLL_CTRL_M_VAL(m) ((m)&0xf)
|
||||
#define PLL_CTRL_K_VAL(k) (((k)&0x7)<<4)
|
||||
#define PLL_CTRL_N_VAL(n) (((n)&0xff)<<8)
|
||||
|
||||
|
||||
//GPIO Pin Configuration(0x4C)
|
||||
#define GPIO_1 (0x1<<1)
|
||||
#define GPIO_2 (0x1<<2)
|
||||
#define GPIO_3 (0x1<<3)
|
||||
#define GPIO_4 (0x1<<4)
|
||||
#define GPIO_5 (0x1<<5)
|
||||
|
||||
|
||||
////INTERRUPT CONTROL(0x5E)
|
||||
#define DISABLE_FAST_VREG (0x1<<15)
|
||||
|
||||
#define AVC_TARTGET_SEL_MASK (0x3<<12)
|
||||
#define AVC_TARTGET_SEL_NONE (0x0<<12)
|
||||
#define AVC_TARTGET_SEL_R (0x1<<12)
|
||||
#define AVC_TARTGET_SEL_L (0x2<<12)
|
||||
#define AVC_TARTGET_SEL_BOTH (0x3<<12)
|
||||
|
||||
//Stereo DAC Clock Control 1(0x60)
|
||||
#define STEREO_SCLK_DIV1_MASK (0xF<<12)
|
||||
#define STEREO_SCLK_DIV1_1 (0x0<<12)
|
||||
#define STEREO_SCLK_DIV1_2 (0x1<<12)
|
||||
#define STEREO_SCLK_DIV1_3 (0x2<<12)
|
||||
#define STEREO_SCLK_DIV1_4 (0x3<<12)
|
||||
#define STEREO_SCLK_DIV1_5 (0x4<<12)
|
||||
#define STEREO_SCLK_DIV1_6 (0x5<<12)
|
||||
#define STEREO_SCLK_DIV1_7 (0x6<<12)
|
||||
#define STEREO_SCLK_DIV1_8 (0x7<<12)
|
||||
#define STEREO_SCLK_DIV1_9 (0x8<<12)
|
||||
#define STEREO_SCLK_DIV1_10 (0x9<<12)
|
||||
#define STEREO_SCLK_DIV1_11 (0xA<<12)
|
||||
#define STEREO_SCLK_DIV1_12 (0xB<<12)
|
||||
#define STEREO_SCLK_DIV1_13 (0xC<<12)
|
||||
#define STEREO_SCLK_DIV1_14 (0xD<<12)
|
||||
#define STEREO_SCLK_DIV1_15 (0xE<<12)
|
||||
#define STEREO_SCLK_DIV1_16 (0xF<<12)
|
||||
|
||||
#define STEREO_SCLK_DIV2_MASK (0x7<<8)
|
||||
#define STEREO_SCLK_DIV2_2 (0x0<<8)
|
||||
#define STEREO_SCLK_DIV2_4 (0x1<<8)
|
||||
#define STEREO_SCLK_DIV2_8 (0x2<<8)
|
||||
#define STEREO_SCLK_DIV2_16 (0x3<<8)
|
||||
#define STEREO_SCLK_DIV2_32 (0x4<<8)
|
||||
|
||||
#define STEREO_AD_WCLK_DIV1_MASK (0xF<<4)
|
||||
#define STEREO_AD_WCLK_DIV1_1 (0x0<<4)
|
||||
#define STEREO_AD_WCLK_DIV1_2 (0x1<<4)
|
||||
#define STEREO_AD_WCLK_DIV1_3 (0x2<<4)
|
||||
#define STEREO_AD_WCLK_DIV1_4 (0x3<<4)
|
||||
#define STEREO_AD_WCLK_DIV1_5 (0x4<<4)
|
||||
#define STEREO_AD_WCLK_DIV1_6 (0x5<<4)
|
||||
#define STEREO_AD_WCLK_DIV1_7 (0x6<<4)
|
||||
#define STEREO_AD_WCLK_DIV1_8 (0x7<<4)
|
||||
#define STEREO_AD_WCLK_DIV1_9 (0x8<<4)
|
||||
#define STEREO_AD_WCLK_DIV1_10 (0x9<<4)
|
||||
#define STEREO_AD_WCLK_DIV1_11 (0xA<<4)
|
||||
#define STEREO_AD_WCLK_DIV1_12 (0xB<<4)
|
||||
#define STEREO_AD_WCLK_DIV1_13 (0xC<<4)
|
||||
#define STEREO_AD_WCLK_DIV1_14 (0xD<<4)
|
||||
#define STEREO_AD_WCLK_DIV1_15 (0xE<<4)
|
||||
#define STEREO_AD_WCLK_DIV1_16 (0xF<<4)
|
||||
|
||||
#define STEREO_AD_WCLK_DIV2_MASK (0x7<<1)
|
||||
#define STEREO_AD_WCLK_DIV2_2 (0x0<<1)
|
||||
#define STEREO_AD_WCLK_DIV2_4 (0x1<<1)
|
||||
#define STEREO_AD_WCLK_DIV2_8 (0x2<<1)
|
||||
#define STEREO_AD_WCLK_DIV2_16 (0x3<<1)
|
||||
#define STEREO_AD_WCLK_DIV2_32 (0x4<<1)
|
||||
|
||||
#define STEREO_DA_WCLK_DIV_MASK (1)
|
||||
#define STEREO_DA_WCLK_DIV_32 (0)
|
||||
#define STEREO_DA_WCLK_DIV_64 (1)
|
||||
|
||||
//Stereo DAC Clock Control 2(0x62)
|
||||
#define STEREO_DA_FILTER_DIV1_MASK (0xF<<12)
|
||||
#define STEREO_DA_FILTER_DIV1_1 (0x0<<12)
|
||||
#define STEREO_DA_FILTER_DIV1_2 (0x1<<12)
|
||||
#define STEREO_DA_FILTER_DIV1_3 (0x2<<12)
|
||||
#define STEREO_DA_FILTER_DIV1_4 (0x3<<12)
|
||||
#define STEREO_DA_FILTER_DIV1_5 (0x4<<12)
|
||||
#define STEREO_DA_FILTER_DIV1_6 (0x5<<12)
|
||||
#define STEREO_DA_FILTER_DIV1_7 (0x6<<12)
|
||||
#define STEREO_DA_FILTER_DIV1_8 (0x7<<12)
|
||||
#define STEREO_DA_FILTER_DIV1_9 (0x8<<12)
|
||||
#define STEREO_DA_FILTER_DIV1_10 (0x9<<12)
|
||||
#define STEREO_DA_FILTER_DIV1_11 (0xA<<12)
|
||||
#define STEREO_DA_FILTER_DIV1_12 (0xB<<12)
|
||||
#define STEREO_DA_FILTER_DIV1_13 (0xC<<12)
|
||||
#define STEREO_DA_FILTER_DIV1_14 (0xD<<12)
|
||||
#define STEREO_DA_FILTER_DIV1_15 (0xE<<12)
|
||||
#define STEREO_DA_FILTER_DIV1_16 (0xF<<12)
|
||||
|
||||
#define STEREO_DA_FILTER_DIV2_MASK (0x7<<9)
|
||||
#define STEREO_DA_FILTER_DIV2_2 (0x0<<9)
|
||||
#define STEREO_DA_FILTER_DIV2_4 (0x1<<9)
|
||||
#define STEREO_DA_FILTER_DIV2_8 (0x2<<9)
|
||||
#define STEREO_DA_FILTER_DIV2_16 (0x3<<9)
|
||||
#define STEREO_DA_FILTER_DIV2_32 (0x4<<9)
|
||||
|
||||
#define STEREO_AD_FILTER_DIV1_MASK (0xF<<4)
|
||||
#define STEREO_AD_FILTER_DIV1_1 (0x0<<4)
|
||||
#define STEREO_AD_FILTER_DIV1_2 (0x1<<4)
|
||||
#define STEREO_AD_FILTER_DIV1_3 (0x2<<4)
|
||||
#define STEREO_AD_FILTER_DIV1_4 (0x3<<4)
|
||||
#define STEREO_AD_FILTER_DIV1_5 (0x4<<4)
|
||||
#define STEREO_AD_FILTER_DIV1_6 (0x5<<4)
|
||||
#define STEREO_AD_FILTER_DIV1_7 (0x6<<4)
|
||||
#define STEREO_AD_FILTER_DIV1_8 (0x7<<4)
|
||||
#define STEREO_AD_FILTER_DIV1_9 (0x8<<4)
|
||||
#define STEREO_AD_FILTER_DIV1_10 (0x9<<4)
|
||||
#define STEREO_AD_FILTER_DIV1_11 (0xA<<4)
|
||||
#define STEREO_AD_FILTER_DIV1_12 (0xB<<4)
|
||||
#define STEREO_AD_FILTER_DIV1_13 (0xC<<4)
|
||||
#define STEREO_AD_FILTER_DIV1_14 (0xD<<4)
|
||||
#define STEREO_AD_FILTER_DIV1_15 (0xE<<4)
|
||||
#define STEREO_AD_FILTER_DIV1_16 (0xF<<4)
|
||||
|
||||
#define STEREO_AD_FILTER_DIV2_MASK (0x7<<1)
|
||||
#define STEREO_AD_FILTER_DIV2_2 (0x0<<1)
|
||||
#define STEREO_AD_FILTER_DIV2_4 (0x1<<1)
|
||||
#define STEREO_AD_FILTER_DIV2_8 (0x2<<1)
|
||||
#define STEREO_AD_FILTER_DIV2_16 (0x3<<1)
|
||||
#define STEREO_AD_FILTER_DIV2_32 (0x4<<1)
|
||||
|
||||
|
||||
//Voice DAC PCM Clock Control 1(0x64)
|
||||
#define VOICE_MCLK_SEL_MASK (0x1<<15)
|
||||
#define VOICE_MCLK_SEL_MCLK_INPUT (0x0<<15)
|
||||
#define VOICE_MCLK_SEL_PLL_OUTPUT (0x1<<15)
|
||||
|
||||
#define VOICE_SYSCLK_SEL_MASK (0x1<<14)
|
||||
#define VOICE_SYSCLK_SEL_MCLK (0x0<<14)
|
||||
#define VOICE_SYSCLK_SEL_EXTCLK (0x1<<14)
|
||||
|
||||
#define VOICE_WCLK_DIV_MASK (0x1<<13)
|
||||
#define VOICE_WCLK_DIV_32 (0x0<<13)
|
||||
#define VOICE_WCLK_DIV_64 (0x1<<13)
|
||||
|
||||
#define VOICE_EXTCLK_OUT_DIV_MASK (0x7<<8)
|
||||
#define VOICE_EXTCLK_OUT_DIV_1 (0x0<<8)
|
||||
#define VOICE_EXTCLK_OUT_DIV_2 (0x1<<8)
|
||||
#define VOICE_EXTCLK_OUT_DIV_4 (0x2<<8)
|
||||
#define VOICE_EXTCLK_OUT_DIV_8 (0x3<<8)
|
||||
#define VOICE_EXTCLK_OUT_DIV_16 (0x4<<8)
|
||||
|
||||
#define VOICE_SCLK_DIV1_MASK (0xF<<4)
|
||||
#define VOICE_SCLK_DIV1_1 (0x0<<4)
|
||||
#define VOICE_SCLK_DIV1_2 (0x1<<4)
|
||||
#define VOICE_SCLK_DIV1_3 (0x2<<4)
|
||||
#define VOICE_SCLK_DIV1_4 (0x3<<4)
|
||||
#define VOICE_SCLK_DIV1_5 (0x4<<4)
|
||||
#define VOICE_SCLK_DIV1_6 (0x5<<4)
|
||||
#define VOICE_SCLK_DIV1_7 (0x6<<4)
|
||||
#define VOICE_SCLK_DIV1_8 (0x7<<4)
|
||||
#define VOICE_SCLK_DIV1_9 (0x8<<4)
|
||||
#define VOICE_SCLK_DIV1_10 (0x9<<4)
|
||||
#define VOICE_SCLK_DIV1_11 (0xA<<4)
|
||||
#define VOICE_SCLK_DIV1_12 (0xB<<4)
|
||||
#define VOICE_SCLK_DIV1_13 (0xC<<4)
|
||||
#define VOICE_SCLK_DIV1_14 (0xD<<4)
|
||||
#define VOICE_SCLK_DIV1_15 (0xE<<4)
|
||||
#define VOICE_SCLK_DIV1_16 (0xF<<4)
|
||||
|
||||
#define VOICE_SCLK_DIV2_MASK (0x7)
|
||||
#define VOICE_SCLK_DIV2_2 (0x0)
|
||||
#define VOICE_SCLK_DIV2_4 (0x1)
|
||||
#define VOICE_SCLK_DIV2_8 (0x2)
|
||||
#define VOICE_SCLK_DIV2_16 (0x3)
|
||||
#define VOICE_SCLK_DIV2_32 (0x4)
|
||||
|
||||
//Voice DAC PCM Clock Control 2(0x66)
|
||||
#define VOICE_CLK_FILTER_SLAVE_DIV_MASK (0x1<<15)
|
||||
#define VOICE_CLK_FILTER_SLAVE_DIV_1 (0x0<<15)
|
||||
#define VOICE_CLK_FILTER_SLAVE_DIV_2 (0x1<<15)
|
||||
|
||||
#define VOICE_FILTER_CLK_F_MASK (0x1<<14)
|
||||
#define VOICE_FILTER_CLK_F_MCLK (0x0<<14)
|
||||
#define VOICE_FILTER_CLK_F_VBCLK (0X1<<14)
|
||||
|
||||
#define VOICE_AD_DA_FILTER_SEL_MASK (0x1<<13)
|
||||
#define VOICE_AD_DA_FILTER_SEL_128X (0x0<<13)
|
||||
#define VOICE_AD_DA_FILTER_SEL_64X (0x1<<13)
|
||||
|
||||
#define VOICE_CLK_FILTER_DIV1_MASK (0xF<<4)
|
||||
#define VOICE_CLK_FILTER_DIV1_1 (0x0<<4)
|
||||
#define VOICE_CLK_FILTER_DIV1_2 (0x1<<4)
|
||||
#define VOICE_CLK_FILTER_DIV1_3 (0x2<<4)
|
||||
#define VOICE_CLK_FILTER_DIV1_4 (0x3<<4)
|
||||
#define VOICE_CLK_FILTER_DIV1_5 (0x4<<4)
|
||||
#define VOICE_CLK_FILTER_DIV1_6 (0x5<<4)
|
||||
#define VOICE_CLK_FILTER_DIV1_7 (0x6<<4)
|
||||
#define VOICE_CLK_FILTER_DIV1_8 (0x7<<4)
|
||||
#define VOICE_CLK_FILTER_DIV1_9 (0x8<<4)
|
||||
#define VOICE_CLK_FILTER_DIV1_10 (0x9<<4)
|
||||
#define VOICE_CLK_FILTER_DIV1_11 (0xA<<4)
|
||||
#define VOICE_CLK_FILTER_DIV1_12 (0xB<<4)
|
||||
#define VOICE_CLK_FILTER_DIV1_13 (0xC<<4)
|
||||
#define VOICE_CLK_FILTER_DIV1_14 (0xD<<4)
|
||||
#define VOICE_CLK_FILTER_DIV1_15 (0xE<<4)
|
||||
#define VOICE_CLK_FILTER_DIV1_16 (0xF<<4)
|
||||
|
||||
#define VOICE_CLK_FILTER_DIV2_MASK (0x7)
|
||||
#define VOICE_CLK_FILTER_DIV2_2 (0x0)
|
||||
#define VOICE_CLK_FILTER_DIV2_4 (0x1)
|
||||
#define VOICE_CLK_FILTER_DIV2_8 (0x2)
|
||||
#define VOICE_CLK_FILTER_DIV2_16 (0x3)
|
||||
#define VOICE_CLK_FILTER_DIV2_32 (0x4)
|
||||
|
||||
|
||||
//Psedueo Stereo & Spatial Effect Block Control(0x68)
|
||||
#define SPATIAL_CTRL_EN (0x1<<15)
|
||||
#define ALL_PASS_FILTER_EN (0x1<<14)
|
||||
#define PSEUDO_STEREO_EN (0x1<<13)
|
||||
#define STEREO_EXPENSION_EN (0x1<<12)
|
||||
|
||||
#define SPATIAL_GAIN_MASK (0x3<<6)
|
||||
#define SPATIAL_GAIN_1_0 (0x0<<6)
|
||||
#define SPATIAL_GAIN_1_5 (0x1<<6)
|
||||
#define SPATIAL_GAIN_2_0 (0x2<<6)
|
||||
|
||||
#define SPATIAL_RATIO_MASK (0x3<<4)
|
||||
#define SPATIAL_RATIO_0_0 (0x0<<4)
|
||||
#define SPATIAL_RATIO_0_66 (0x1<<4)
|
||||
#define SPATIAL_RATIO_1_0 (0x2<<4)
|
||||
|
||||
#define APF_MASK (0x3)
|
||||
#define APF_FOR_48K (0x3)
|
||||
#define APF_FOR_44_1K (0x2)
|
||||
#define APF_FOR_32K (0x1)
|
||||
|
||||
struct rt5624_setup_data {
|
||||
unsigned short i2c_address;
|
||||
};
|
||||
|
||||
|
||||
#define RT5624_PLL_FR_MCLK 0
|
||||
|
||||
//WaveOut channel for realtek codec
|
||||
enum
|
||||
{
|
||||
RT_WAVOUT_SPK =(0x1<<0),
|
||||
RT_WAVOUT_SPK_R =(0x1<<1),
|
||||
RT_WAVOUT_SPK_L =(0x1<<2),
|
||||
RT_WAVOUT_HP =(0x1<<3),
|
||||
RT_WAVOUT_HP_R =(0x1<<4),
|
||||
RT_WAVOUT_HP_L =(0x1<<5),
|
||||
RT_WAVOUT_MONO =(0x1<<6),
|
||||
RT_WAVOUT_AUXOUT =(0x1<<7),
|
||||
RT_WAVOUT_AUXOUT_R =(0x1<<8),
|
||||
RT_WAVOUT_AUXOUT_L =(0x1<<9),
|
||||
RT_WAVOUT_LINEOUT =(0x1<<10),
|
||||
RT_WAVOUT_LINEOUT_R =(0x1<<11),
|
||||
RT_WAVOUT_LINEOUT_L =(0x1<<12),
|
||||
RT_WAVOUT_DAC =(0x1<<13),
|
||||
RT_WAVOUT_ALL_ON =(0x1<<14),
|
||||
};
|
||||
|
||||
//WaveIn channel for realtek codec
|
||||
enum
|
||||
{
|
||||
RT_WAVIN_R_MONO_MIXER =(0x1<<0),
|
||||
RT_WAVIN_R_SPK_MIXER =(0x1<<1),
|
||||
RT_WAVIN_R_HP_MIXER =(0x1<<2),
|
||||
RT_WAVIN_R_PHONE =(0x1<<3),
|
||||
RT_WAVIN_R_AUXIN =(0x1<<3),
|
||||
RT_WAVIN_R_LINE_IN =(0x1<<4),
|
||||
RT_WAVIN_R_MIC2 =(0x1<<5),
|
||||
RT_WAVIN_R_MIC1 =(0x1<<6),
|
||||
|
||||
RT_WAVIN_L_MONO_MIXER =(0x1<<8),
|
||||
RT_WAVIN_L_SPK_MIXER =(0x1<<9),
|
||||
RT_WAVIN_L_HP_MIXER =(0x1<<10),
|
||||
RT_WAVIN_L_PHONE =(0x1<<11),
|
||||
RT_WAVIN_L_AUXIN =(0x1<<11),
|
||||
RT_WAVIN_L_LINE_IN =(0x1<<12),
|
||||
RT_WAVIN_L_MIC2 =(0x1<<13),
|
||||
RT_WAVIN_L_MIC1 =(0x1<<14),
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
POWER_STATE_D0=0,
|
||||
POWER_STATE_D1,
|
||||
POWER_STATE_D1_PLAYBACK,
|
||||
POWER_STATE_D1_RECORD,
|
||||
POWER_STATE_D2,
|
||||
POWER_STATE_D2_PLAYBACK,
|
||||
POWER_STATE_D2_RECORD,
|
||||
POWER_STATE_D3,
|
||||
POWER_STATE_D4
|
||||
|
||||
};
|
||||
|
||||
|
||||
extern struct snd_soc_codec_dai rt5624_dai;
|
||||
extern struct snd_soc_codec_device soc_codec_dev_rt5624;
|
||||
|
||||
#endif
|
||||
1376
sound/soc/codecs/rt5627.c
Normal file
1376
sound/soc/codecs/rt5627.c
Normal file
File diff suppressed because it is too large
Load Diff
316
sound/soc/codecs/rt5627.h
Normal file
316
sound/soc/codecs/rt5627.h
Normal file
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* rt5627.h -- audio driver for RT5627/RT5628
|
||||
*
|
||||
* Copyright 2008 Realtek Microelectronics
|
||||
*
|
||||
* Author: flove <flove@realtek.com>
|
||||
*
|
||||
* Based on WM8753.h
|
||||
*
|
||||
* 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 _RT5627_H
|
||||
#define _RT5627_H
|
||||
|
||||
|
||||
#define RT5627_RESET 0X00 //RESET CODEC TO DEFAULT
|
||||
#define RT5627_SPK_OUT_VOL 0X02 //SPEAKER OUT VOLUME
|
||||
#define RT5627_HP_OUT_VOL 0X04 //HEADPHONE OUTPUT VOLUME
|
||||
#define RT5627_AUXIN_VOL 0X08 //AUXIN VOLUME
|
||||
#define RT5627_LINE_IN_VOL 0X0A //LINE IN VOLUME
|
||||
#define RT5627_STEREO_DAC_VOL 0X0C //STEREO DAC VOLUME
|
||||
#define RT5627_SOFT_VOL_CTRL_TIME 0X16 //SOFT DELAY VOLUME CONTROL TIME
|
||||
#define RT5627_OUTPUT_MIXER_CTRL 0X1C //OUTPUT MIXER CONTROL
|
||||
#define RT5627_AUDIO_DATA_CTRL 0X34 //STEREO AUDIO DATA CONTROL
|
||||
#define RT5627_DAC_CLK_CTRL 0X38 //STEREO DAC CLOCK CONTROL
|
||||
#define RT5627_PWR_MANAG_ADD1 0X3A //POWER MANAGMENT ADDITION 1
|
||||
#define RT5627_PWR_MANAG_ADD2 0X3C //POWER MANAGMENT ADDITION 2
|
||||
#define RT5627_PWR_MANAG_ADD3 0X3E //POWER MANAGMENT ADDITION 3
|
||||
#define RT5627_GEN_CTRL 0X40 //GENERAL PURPOSE CONTROL
|
||||
#define RT5627_GLOBAL_CLK_CTRL 0X42 //GLOBAL CLOCK CONTROL
|
||||
#define RT5627_PLL_CTRL 0X44 //PLL CONTROL
|
||||
#define RT5627_GPIO_PIN_CONFIG 0X48 //GPIO PIN CONFIG
|
||||
#define RT5627_GPIO_OUTPUT_PIN_CTRL 0X4A //GPIO CONTROL
|
||||
#define RT5627_JACK_DET_CTRL 0X5A //JACK DETECT CONTROL
|
||||
#define RT5627_MISC1_CTRL 0X5C //MISC1 CONTROL
|
||||
#define RT5627_MISC2_CTRL 0X5E //MISC2 CONTROL
|
||||
#define RT5627_AVC_CTRL 0X68 //AVC CONTROL
|
||||
#define RT5627_HID_CTRL_INDEX 0X6A //PRIVATE REGISTER ADDRESS
|
||||
#define RT5627_HID_CTRL_DATA 0X6C //PRIVATE REGISTER DATA
|
||||
#define RT5627_VENDOR_ID1 0x7C //VENDOR ID1
|
||||
#define RT5627_VENDOR_ID2 0x7E //VENDOR ID2
|
||||
|
||||
|
||||
//global definition
|
||||
#define RT_L_MUTE (0x1<<15) //MUTE LEFT CONTROL BIT
|
||||
#define RT_R_MUTE (0x1<<7) //MUTE RIGHT CONTROL BIT
|
||||
#define RT_M_HP_MIXER (0x1<<15) //Mute source to HP Mixer
|
||||
#define RT_M_SPK_MIXER (0x1<<14) //Mute source to Speaker Mixer
|
||||
#define RT_M_MONO_MIXER (0x1<<13) //Mute source to Mono Mixer
|
||||
|
||||
#define ALL_FIELD 0xffff
|
||||
|
||||
//Output Mixer Control(0x1C)
|
||||
#define SPKOUT_N_SOUR_MASK (0x3<<14)
|
||||
#define SPKOUT_N_SOUR_MUTE (0x3<<14)
|
||||
#define SPKOUT_N_SOUR_LN (0x2<<14)
|
||||
#define SPKOUT_N_SOUR_RP (0x1<<14)
|
||||
#define SPKOUT_N_SOUR_RN (0x0<<14)
|
||||
#define SPKOUT_INPUT_SEL_MASK (0x3<<10)
|
||||
#define SPKOUT_INPUT_SEL_SPKMIXER (0x2<<10)
|
||||
#define SPKOUT_INPUT_SEL_HPMIXER (0x1<<10)
|
||||
#define SPKOUT_INPUT_SEL_VMID (0x0<<10)
|
||||
#define HPL_INPUT_SEL_HPLMIXER (0x1<<9)
|
||||
#define HPR_INPUT_SEL_HPRMIXER (0x1<<8)
|
||||
#define AUXOUT_L_INPUT_SEL_MASK (0x1<<7)
|
||||
#define AUXOUT_L_INPUT_SEL_HPLMIXER (0x1<<7)
|
||||
#define AUXOUT_L_INPUT_SEL_SPKMIXER (0x0<<7)
|
||||
#define AUXOUT_R_INPUT_SEL_MASK (0x1<<6)
|
||||
#define AUXOUT_R_INPUT_SEL_HPLMIXER (0x1<<6)
|
||||
#define AUXOUT_R_INPUT_SEL_SPKMIXER (0x0<<6)
|
||||
#define SPK_VOL_DIFF_NEG_SIG_ENA (0x2<<2)
|
||||
#define DAC_DIRECT_TO_HP (0x1<<1)
|
||||
#define DAC_DIRECT_TO_AUXOUT (0x1)
|
||||
|
||||
|
||||
//Audio Interface(0x34)
|
||||
#define SDP_MASTER_MODE (0x0<<15)
|
||||
#define SDP_SLAVE_MODE (0x1<<15)
|
||||
#define MAIN_I2S_BCLK_POL_CTRL (0x1<<7) //0:Normal 1:Invert
|
||||
#define DAC_DATA_L_R_SWAP (0x1<<4) //0:DAC data appear at left phase of LRCK
|
||||
//1:DAC data appear at right phase of LRCK
|
||||
//Data Length Slection
|
||||
#define I2S_DL_MASK (0x3<<2) //main i2s Data Length mask
|
||||
#define I2S_DL_16 (0x0<<2) //16 bits
|
||||
#define I2S_DL_20 (0x1<<2) //20 bits
|
||||
#define I2S_DL_24 (0x2<<2) //24 bits
|
||||
|
||||
//PCM Data Format Selection
|
||||
#define I2S_DF_MASK (0x3) //IIS Data Format Mask
|
||||
#define I2S_DF_I2S (0x0) //I2S FORMAT
|
||||
#define I2S_DF_LEFT (0x1) //LEFT JUSTIFIED FORMAT
|
||||
#define I2S_DF_PCM_A (0x2) //PCM MODE A
|
||||
#define I2S_DF_PCM_B (0x3) //PCM MODE B
|
||||
|
||||
//Stereo AD/DA Clock Control(0x38h)
|
||||
#define I2S_PRE_DIV_MASK (0x7<<13)
|
||||
#define I2S_PRE_DIV_1 (0x0<<13) //DIV 1
|
||||
#define I2S_PRE_DIV_2 (0x1<<13) //DIV 2
|
||||
#define I2S_PRE_DIV_4 (0x2<<13) //DIV 4
|
||||
#define I2S_PRE_DIV_8 (0x3<<13) //DIV 8
|
||||
#define I2S_PRE_DIV_16 (0x4<<13) //DIV 16
|
||||
#define I2S_PRE_DIV_32 (0x5<<13) //DIV 32
|
||||
|
||||
#define I2S_BCLK_SEL_64FS (0x0<<12) //32 BITS(64FS)
|
||||
#define I2S_BCLK_SEL_32FS (0x1<<12) //16 BITS(32FS)
|
||||
|
||||
#define DAC_FILTER_CLK_SEL_256FS (0<<2) //256FS
|
||||
#define DAC_FILTER_CLK_SEL_384FS (1<<2) //384FS
|
||||
|
||||
//Power managment addition 1 (0x3A),0:Disable,1:Enable
|
||||
#define PWR_MAIN_I2S_EN (0x1<<15)
|
||||
#define PWR_ZC_DET_PD_EN (0x1<<14)
|
||||
#define PWR_SOFTGEN_EN (0x1<<8)
|
||||
#define PWR_HP_AMP (0x1<<5)
|
||||
#define PWR_HP_ENH_AMP (0x1<<4)
|
||||
|
||||
//Power managment addition 2(0x3C),0:Disable,1:Enable
|
||||
#define PWR_CLASS_D (0x1<<14)
|
||||
#define PWR_VREF (0x1<<13)
|
||||
#define PWR_PLL (0x1<<12)
|
||||
#define PWR_THERMAL_SD (0x1<<11)
|
||||
#define PWR_DAC_REF_CIR (0x1<<10)
|
||||
#define PWR_L_DAC_CLK (0x1<<9)
|
||||
#define PWR_R_DAC_CLK (0x1<<8)
|
||||
#define PWR_L_DAC_L_D_S (0x1<<7)
|
||||
#define PWR_R_DAC_R_D_S (0x1<<6)
|
||||
#define PWR_L_HP_MIXER (0x1<<5)
|
||||
#define PWR_R_HP_MIXER (0x1<<4)
|
||||
#define PWR_SPK_MIXER (0x1<<3)
|
||||
|
||||
|
||||
//Power managment addition 3(0x3E),0:Disable,1:Enable
|
||||
#define PWR_MAIN_BIAS (0x1<<15)
|
||||
#define PWR_SPK_OUT (0x1<<12)
|
||||
#define PWR_HP_L_OUT_VOL_AMP (0x1<<10)
|
||||
#define PWR_HP_R_OUT_VOL_AMP (0x1<<9)
|
||||
#define PWR_LINEIN_L_VOL (0x1<<7)
|
||||
#define PWR_LINEIN_R_VOL (0x1<<6)
|
||||
#define PWR_AUXIN_L_VOL (0x1<<5)
|
||||
#define PWR_AUXIN_R_VOL (0x1<<4)
|
||||
|
||||
//Additional Control Register(0x40)
|
||||
#define SPK_D_AMP_CTRL_MASK (0x7<<9)
|
||||
#define SPK_D_AMP_CTRL_RATIO_225 (0x0<<9) //2.25 Vdd
|
||||
#define SPK_D_AMP_CTRL_RATIO_200 (0x1<<9) //2.00 Vdd
|
||||
#define SPK_D_AMP_CTRL_RATIO_175 (0x2<<9) //1.75 Vdd
|
||||
#define SPK_D_AMP_CTRL_RATIO_150 (0x3<<9) //1.50 Vdd
|
||||
#define SPK_D_AMP_CTRL_RATIO_125 (0x4<<9) //1.25 Vdd
|
||||
#define SPK_D_AMP_CTRL_RATIO_100 (0x5<<9) //1.00 Vdd
|
||||
|
||||
#define STEREO_DAC_H_PASS_EN (0x1<<8) //enable HIGH PASS FILTER FOR DAC
|
||||
|
||||
//Global Clock Control Register(0x42)
|
||||
#define SYSCLK_SOUR_SEL_MASK (0x1<<15)
|
||||
#define SYSCLK_SOUR_SEL_MCLK (0x0<<15) //system Clock source from MCLK
|
||||
#define SYSCLK_SOUR_SEL_PLL (0x1<<15) //system Clock source from PLL
|
||||
#define PLLCLK_SOUR_SEL_MCLK (0x0<<14) //PLL clock source from MCLK
|
||||
#define PLLCLK_SOUR_SEL_BITCLK (0x1<<14) //PLL clock source from BITCLK
|
||||
|
||||
#define PLLCLK_DIV_RATIO_MASK (0x3<<1)
|
||||
#define PLLCLK_DIV_RATIO_DIV1 (0x0<<1) //DIV 1
|
||||
#define PLLCLK_DIV_RATIO_DIV2 (0x1<<1) //DIV 2
|
||||
#define PLLCLK_DIV_RATIO_DIV4 (0x2<<1) //DIV 4
|
||||
#define PLLCLK_DIV_RATIO_DIV8 (0x3<<1) //DIV 8
|
||||
|
||||
#define PLLCLK_PRE_DIV1 (0x0) //DIV 1
|
||||
#define PLLCLK_PRE_DIV2 (0x1) //DIV 2
|
||||
|
||||
//PLL Control(0x44)
|
||||
|
||||
#define PLL_CTRL_M_VAL(m) ((m)&0xf)
|
||||
#define PLL_CTRL_K_VAL(k) (((k)&0x7)<<4)
|
||||
#define PLL_CTRL_N_VAL(n) (((n)&0xff)<<8)
|
||||
|
||||
|
||||
//GPIO CONTROL(0x4A)
|
||||
#define GPIO_PIN_SEL_MASK (0x3<<14)
|
||||
#define GPIO_PIN_SEL_LOG_OUT (0x0<<14)
|
||||
#define GPIO_PIN_SEL_IRQ (0x1<<14)
|
||||
#define GPIO_PIN_SEL_PLLOUT (0x3<<14)
|
||||
|
||||
#define GPIO_PIN_CON_MASK (0x1<<3)
|
||||
#define GPIO_PIN_CON_OUTPUT (0x0<<3)
|
||||
#define GPIO_PIN_CON_INPUT (0x1<<3)
|
||||
|
||||
#define GPIO_PIN_OUTPUT_SET_MASK (0x1<<2)
|
||||
#define GPIO_PIN_OUTPUT_SET_LOW (0x0<<2)
|
||||
#define GPIO_PIN_OUTPUT_SET_HIGH (0x1<<2)
|
||||
|
||||
#define GPIO_PIN_POLARITY_INV (0x1<<1)
|
||||
|
||||
//JACK DETECT CONTROL(0x5A)
|
||||
#define JACK_DET_SEL_MASK (0x3<<14)
|
||||
#define JACK_DET_SEL_OFF (0x0<<14) //Jack Detect Select none
|
||||
#define JACK_DET_SEL_GPIO (0x1<<14) //Jack Detect Select GPIO
|
||||
#define JACK_DET_SEL_JD1 (0x2<<14) //Jack Detect Select JD1,LineIn Left disable
|
||||
#define JACK_DET_SEL_JD2 (0x3<<14) //Jack Detect Select JD2,LineIn Right Disable
|
||||
|
||||
#define JACK_DET_TRI_VREF (0x1<<13)
|
||||
#define JACK_DET_POL_TRI_VREF (0x1<<12)
|
||||
#define JACK_DET_TRI_HP (0x1<<11)
|
||||
#define JACK_DET_POL_TRI_HP (0x1<<10)
|
||||
#define JACK_DET_TRI_SPK (0x1<<9)
|
||||
#define JACK_DET_POL_TRI_SPK (0x1<<8)
|
||||
#define JACK_DET_POL (0x1<<3)
|
||||
|
||||
|
||||
//MISC1 CONTROL(0x5C)
|
||||
#define SPK_L_ZC_CTRL_EN (0x1<<15)
|
||||
#define SPK_L_SV_CTRL_EN (0x1<<14)
|
||||
#define SPK_R_ZC_CTRL_EN (0x1<<13)
|
||||
#define SPK_R_SV_CTRL_EN (0x1<<12)
|
||||
#define HP_L_ZC_CTRL_EN (0x1<<11)
|
||||
#define HP_L_SV_CTRL_EN (0x1<<10)
|
||||
#define HP_R_ZC_CTRL_EN (0x1<<9)
|
||||
#define HP_R_SV_CTRL_EN (0x1<<8)
|
||||
#define AUXOUT_L_ZC_CTRL_EN (0x1<<7)
|
||||
#define AUXOUT_L_SV_CTRL_EN (0x1<<6)
|
||||
#define AUXOUT_R_ZC_CTRL_EN (0x1<<5)
|
||||
#define AUXOUT_R_SV_CTRL_EN (0x1<<4)
|
||||
#define DAC_ZC_CTRL_EN (0x1<<3)
|
||||
#define DAC_SV_CTRL_EN (0x1<<2)
|
||||
|
||||
|
||||
////MISC2 CONTROL(0x5E)
|
||||
#define DISABLE_FAST_VREG (0x1<<15)
|
||||
#define THERMAL_SHUTDOWN_EN (0x1<<14)
|
||||
#define HP_DEPOP_MODE2_EN (0x1<<9)
|
||||
#define HP_DEPOP_MODE1_EN (0x1<<8)
|
||||
#define HP_L_M_UM_DEPOP_EN (0x1<<7)
|
||||
#define HP_R_M_UM_DEPOP_EN (0x1<<6)
|
||||
#define M_UM_DEPOP_EN (0x1<<5)
|
||||
#define M_DAC_L_INPUT (0x1<<3)
|
||||
#define M_DAC_R_INPUT (0x1<<2)
|
||||
|
||||
//AVC Control(0x68)
|
||||
#define AVC_ENABLE (0x1<<15)
|
||||
#define AVC_TARTGET_SEL_MASK (0x1<<14)
|
||||
#define AVC_TARTGET_SEL_R (0x1<<14)
|
||||
#define AVC_TARTGET_SEL_L (0x0<<14)
|
||||
|
||||
|
||||
//WaveOut channel for realtek codec
|
||||
enum
|
||||
{
|
||||
RT_WAVOUT_SPK =(0x1<<0),
|
||||
RT_WAVOUT_SPK_R =(0x1<<1),
|
||||
RT_WAVOUT_SPK_L =(0x1<<2),
|
||||
RT_WAVOUT_HP =(0x1<<3),
|
||||
RT_WAVOUT_HP_R =(0x1<<4),
|
||||
RT_WAVOUT_HP_L =(0x1<<5),
|
||||
RT_WAVOUT_MONO =(0x1<<6),
|
||||
RT_WAVOUT_AUXOUT =(0x1<<7),
|
||||
RT_WAVOUT_AUXOUT_R =(0x1<<8),
|
||||
RT_WAVOUT_AUXOUT_L =(0x1<<9),
|
||||
RT_WAVOUT_LINEOUT =(0x1<<10),
|
||||
RT_WAVOUT_LINEOUT_R =(0x1<<11),
|
||||
RT_WAVOUT_LINEOUT_L =(0x1<<12),
|
||||
RT_WAVOUT_DAC =(0x1<<13),
|
||||
RT_WAVOUT_ALL_ON =(0x1<<14),
|
||||
};
|
||||
|
||||
//WaveIn channel for realtek codec
|
||||
enum
|
||||
{
|
||||
RT_WAVIN_R_MONO_MIXER =(0x1<<0),
|
||||
RT_WAVIN_R_SPK_MIXER =(0x1<<1),
|
||||
RT_WAVIN_R_HP_MIXER =(0x1<<2),
|
||||
RT_WAVIN_R_PHONE =(0x1<<3),
|
||||
RT_WAVIN_R_AUXIN =(0x1<<3),
|
||||
RT_WAVIN_R_LINE_IN =(0x1<<4),
|
||||
RT_WAVIN_R_MIC2 =(0x1<<5),
|
||||
RT_WAVIN_R_MIC1 =(0x1<<6),
|
||||
|
||||
RT_WAVIN_L_MONO_MIXER =(0x1<<8),
|
||||
RT_WAVIN_L_SPK_MIXER =(0x1<<9),
|
||||
RT_WAVIN_L_HP_MIXER =(0x1<<10),
|
||||
RT_WAVIN_L_PHONE =(0x1<<11),
|
||||
RT_WAVIN_L_AUXIN =(0x1<<11),
|
||||
RT_WAVIN_L_LINE_IN =(0x1<<12),
|
||||
RT_WAVIN_L_MIC2 =(0x1<<13),
|
||||
RT_WAVIN_L_MIC1 =(0x1<<14),
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
POWER_STATE_D0=0,
|
||||
POWER_STATE_D1,
|
||||
POWER_STATE_D1_PLAYBACK,
|
||||
POWER_STATE_D1_RECORD,
|
||||
POWER_STATE_D2,
|
||||
POWER_STATE_D2_PLAYBACK,
|
||||
POWER_STATE_D2_RECORD,
|
||||
POWER_STATE_D3,
|
||||
POWER_STATE_D4
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct rt5627_setup_data {
|
||||
unsigned short i2c_address;
|
||||
};
|
||||
|
||||
|
||||
#define RT5627_PLL_FR_MCLK 0
|
||||
#define RT5627_PLL_FR_BCK 1
|
||||
|
||||
|
||||
extern struct snd_soc_codec_dai rt5627_dai;
|
||||
extern struct snd_soc_codec_device soc_codec_dev_rt5627;
|
||||
|
||||
#endif
|
||||
1110
sound/soc/codecs/wm8580.c
Normal file
1110
sound/soc/codecs/wm8580.c
Normal file
File diff suppressed because it is too large
Load Diff
166
sound/soc/codecs/wm8580.h
Normal file
166
sound/soc/codecs/wm8580.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* wm8580.h -- audio driver for WM8580
|
||||
*
|
||||
* Copyright 2008 Samsung Electronics.
|
||||
* Author: Ryu Euiyoul
|
||||
* ryu.real@gmail.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _WM8580_H
|
||||
#define _WM8580_H
|
||||
|
||||
#define WM8580_PLLA 1
|
||||
#define WM8580_PLLB 2
|
||||
|
||||
#define WM8580_MCLK 1
|
||||
#define WM8580_DAC_CLKSEL 2
|
||||
#define WM8580_CLKOUTSRC 3
|
||||
|
||||
#define WM8580_CLKSRC_MCLK 1
|
||||
#define WM8580_CLKSRC_PLLA 2
|
||||
#define WM8580_CLKSRC_PLLB 3
|
||||
#define WM8580_CLKSRC_OSC 4
|
||||
#define WM8580_CLKSRC_NONE 5
|
||||
|
||||
/* WM8580 register space */
|
||||
#define WM8580_PLLA1 0x00
|
||||
#define WM8580_PLLA2 0x01
|
||||
#define WM8580_PLLA3 0x02
|
||||
#define WM8580_PLLA4 0x03
|
||||
#define WM8580_PLLB1 0x04
|
||||
#define WM8580_PLLB2 0x05
|
||||
#define WM8580_PLLB3 0x06
|
||||
#define WM8580_PLLB4 0x07
|
||||
#define WM8580_CLKSEL 0x08
|
||||
#define WM8580_PAIF1 0x09
|
||||
#define WM8580_PAIF2 0x0A
|
||||
#define WM8580_SAIF1 0x0B
|
||||
#define WM8580_PAIF3 0x0C
|
||||
#define WM8580_PAIF4 0x0D
|
||||
#define WM8580_SAIF2 0x0E
|
||||
#define WM8580_DAC_CONTROL1 0x0F
|
||||
#define WM8580_DAC_CONTROL2 0x10
|
||||
#define WM8580_DAC_CONTROL3 0x11
|
||||
#define WM8580_DAC_CONTROL4 0x12
|
||||
#define WM8580_DAC_CONTROL5 0x13
|
||||
#define WM8580_DIGITAL_ATTENUATION_DACL1 0x14
|
||||
#define WM8580_DIGITAL_ATTENUATION_DACR1 0x15
|
||||
#define WM8580_DIGITAL_ATTENUATION_DACL2 0x16
|
||||
#define WM8580_DIGITAL_ATTENUATION_DACR2 0x17
|
||||
#define WM8580_DIGITAL_ATTENUATION_DACL3 0x18
|
||||
#define WM8580_DIGITAL_ATTENUATION_DACR3 0x19
|
||||
#define WM8580_MASTER_DIGITAL_ATTENUATION 0x1C
|
||||
#define WM8580_ADC_CONTROL1 0x1D
|
||||
#define WM8580_SPDTXCHAN0 0x1E
|
||||
#define WM8580_SPDTXCHAN1 0x1F
|
||||
#define WM8580_SPDTXCHAN2 0x20
|
||||
#define WM8580_SPDTXCHAN3 0x21
|
||||
#define WM8580_SPDTXCHAN4 0x22
|
||||
#define WM8580_SPDTXCHAN5 0x23
|
||||
#define WM8580_SPDMODE 0x24
|
||||
#define WM8580_INTMASK 0x25
|
||||
#define WM8580_GPO1 0x26
|
||||
#define WM8580_GPO2 0x27
|
||||
#define WM8580_GPO3 0x28
|
||||
#define WM8580_GPO4 0x29
|
||||
#define WM8580_GPO5 0x2A
|
||||
#define WM8580_INTSTAT 0x2B
|
||||
#define WM8580_SPDRXCHAN1 0x2C
|
||||
#define WM8580_SPDRXCHAN2 0x2D
|
||||
#define WM8580_SPDRXCHAN3 0x2E
|
||||
#define WM8580_SPDRXCHAN4 0x2F
|
||||
#define WM8580_SPDRXCHAN5 0x30
|
||||
#define WM8580_SPDSTAT 0x31
|
||||
#define WM8580_PWRDN1 0x32
|
||||
#define WM8580_PWRDN2 0x33
|
||||
#define WM8580_READBACK 0x34
|
||||
#define WM8580_RESET 0x35
|
||||
|
||||
/* PLLB4 (register 7h) */
|
||||
#define WM8580_PLLB4_MCLKOUTSRC_MASK 0x60
|
||||
#define WM8580_PLLB4_MCLKOUTSRC_PLLA 0x20
|
||||
#define WM8580_PLLB4_MCLKOUTSRC_PLLB 0x40
|
||||
#define WM8580_PLLB4_MCLKOUTSRC_OSC 0x60
|
||||
|
||||
#define WM8580_PLLB4_CLKOUTSRC_MASK 0x180
|
||||
#define WM8580_PLLB4_CLKOUTSRC_PLLACLK 0x080
|
||||
#define WM8580_PLLB4_CLKOUTSRC_PLLBCLK 0x100
|
||||
#define WM8580_PLLB4_CLKOUTSRC_OSCCLK 0x180
|
||||
|
||||
/* CLKSEL (register 8h) */
|
||||
#define WM8580_CLKSEL_DAC_CLKSEL_MASK 0x03
|
||||
#define WM8580_CLKSEL_DAC_CLKSEL_PLLA 0x01
|
||||
#define WM8580_CLKSEL_DAC_CLKSEL_PLLB 0x02
|
||||
|
||||
/* AIF control 1 (registers 9h-bh) */
|
||||
#define WM8580_AIF_RATE_MASK 0x7
|
||||
#define WM8580_AIF_RATE_128 0x0
|
||||
#define WM8580_AIF_RATE_192 0x1
|
||||
#define WM8580_AIF_RATE_256 0x2
|
||||
#define WM8580_AIF_RATE_384 0x3
|
||||
#define WM8580_AIF_RATE_512 0x4
|
||||
#define WM8580_AIF_RATE_768 0x5
|
||||
#define WM8580_AIF_RATE_1152 0x6
|
||||
|
||||
#define WM8580_AIF_BCLKSEL_MASK 0x18
|
||||
#define WM8580_AIF_BCLKSEL_64 0x00
|
||||
#define WM8580_AIF_BCLKSEL_128 0x08
|
||||
#define WM8580_AIF_BCLKSEL_256 0x10
|
||||
#define WM8580_AIF_BCLKSEL_SYSCLK 0x18
|
||||
|
||||
#define WM8580_AIF_MS 0x20
|
||||
|
||||
#define WM8580_AIF_CLKSRC_MASK 0xc0
|
||||
#define WM8580_AIF_CLKSRC_PLLA 0x40
|
||||
#define WM8580_AIF_CLKSRC_PLLB 0x40
|
||||
#define WM8580_AIF_CLKSRC_MCLK 0xc0
|
||||
|
||||
/* AIF control 2 (registers ch-eh) */
|
||||
#define WM8580_AIF_FMT_MASK 0x03
|
||||
#define WM8580_AIF_FMT_RIGHTJ 0x00
|
||||
#define WM8580_AIF_FMT_LEFTJ 0x01
|
||||
#define WM8580_AIF_FMT_I2S 0x02
|
||||
#define WM8580_AIF_FMT_DSP 0x03
|
||||
|
||||
#define WM8580_AIF_LENGTH_MASK 0x0c
|
||||
#define WM8580_AIF_LENGTH_16 0x00
|
||||
#define WM8580_AIF_LENGTH_20 0x04
|
||||
#define WM8580_AIF_LENGTH_24 0x08
|
||||
#define WM8580_AIF_LENGTH_32 0x0c
|
||||
|
||||
#define WM8580_AIF_LRP 0x10
|
||||
#define WM8580_AIF_BCP 0x20
|
||||
|
||||
/* Powerdown Register 1 (register 32h) */
|
||||
#define WM8580_PWRDN1_PWDN 0x001
|
||||
#define WM8580_PWRDN1_ALLDACPD 0x040
|
||||
|
||||
/* Powerdown Register 2 (register 33h) */
|
||||
#define WM8580_PWRDN2_OSSCPD 0x001
|
||||
#define WM8580_PWRDN2_PLLAPD 0x002
|
||||
#define WM8580_PWRDN2_PLLBPD 0x004
|
||||
#define WM8580_PWRDN2_SPDIFPD 0x008
|
||||
#define WM8580_PWRDN2_SPDIFTXD 0x010
|
||||
#define WM8580_PWRDN2_SPDIFRXD 0x020
|
||||
|
||||
extern struct snd_soc_codec_device soc_codec_dev_wm8580;
|
||||
|
||||
struct wm8580_setup_data {
|
||||
unsigned short i2c_address;
|
||||
};
|
||||
|
||||
#define WM8580_DAI_PAIFRX 0
|
||||
#define WM8580_DAI_PAIFTX 1
|
||||
#define WM8580_DAI_SAIF 2
|
||||
|
||||
extern struct snd_soc_codec_dai wm8580_dai[];
|
||||
extern struct snd_soc_codec_device soc_codec_dev_wm8580;
|
||||
|
||||
#endif
|
||||
|
||||
758
sound/soc/codecs/wm8731.c
Normal file
758
sound/soc/codecs/wm8731.c
Normal file
@@ -0,0 +1,758 @@
|
||||
/*
|
||||
* wm8731.c -- WM8731 ALSA SoC Audio driver
|
||||
*
|
||||
* Copyright 2005 Openedhand Ltd.
|
||||
*
|
||||
* Author: Richard Purdie <richard@openedhand.com>
|
||||
*
|
||||
* Based on wm8753.c by Liam Girdwood
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <sound/driver.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/initval.h>
|
||||
|
||||
#include "wm8731.h"
|
||||
|
||||
#define AUDIO_NAME "wm8731"
|
||||
#define WM8731_VERSION "0.13"
|
||||
|
||||
/*
|
||||
* Debug
|
||||
*/
|
||||
|
||||
#define WM8731_DEBUG 0
|
||||
|
||||
#ifdef WM8731_DEBUG
|
||||
#define dbg(format, arg...) \
|
||||
printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
|
||||
#else
|
||||
#define dbg(format, arg...) do {} while (0)
|
||||
#endif
|
||||
#define err(format, arg...) \
|
||||
printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg)
|
||||
#define info(format, arg...) \
|
||||
printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg)
|
||||
#define warn(format, arg...) \
|
||||
printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg)
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_wm8731;
|
||||
|
||||
/* codec private data */
|
||||
struct wm8731_priv {
|
||||
unsigned int sysclk;
|
||||
};
|
||||
|
||||
/*
|
||||
* wm8731 register cache
|
||||
* We can't read the WM8731 register space when we are
|
||||
* using 2 wire for device control, so we cache them instead.
|
||||
* There is no point in caching the reset register
|
||||
*/
|
||||
static const u16 wm8731_reg[WM8731_CACHEREGNUM] = {
|
||||
0x0097, 0x0097, 0x0079, 0x0079,
|
||||
0x000a, 0x0008, 0x009f, 0x000a,
|
||||
0x0000, 0x0000
|
||||
};
|
||||
|
||||
/*
|
||||
* read wm8731 register cache
|
||||
*/
|
||||
static inline unsigned int wm8731_read_reg_cache(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
u16 *cache = codec->reg_cache;
|
||||
if (reg == WM8731_RESET)
|
||||
return 0;
|
||||
if (reg >= WM8731_CACHEREGNUM)
|
||||
return -1;
|
||||
return cache[reg];
|
||||
}
|
||||
|
||||
/*
|
||||
* write wm8731 register cache
|
||||
*/
|
||||
static inline void wm8731_write_reg_cache(struct snd_soc_codec *codec,
|
||||
u16 reg, unsigned int value)
|
||||
{
|
||||
u16 *cache = codec->reg_cache;
|
||||
if (reg >= WM8731_CACHEREGNUM)
|
||||
return;
|
||||
cache[reg] = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* write to the WM8731 register space
|
||||
*/
|
||||
static int wm8731_write(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int value)
|
||||
{
|
||||
u8 data[2];
|
||||
|
||||
/* data is
|
||||
* D15..D9 WM8731 register offset
|
||||
* D8...D0 register data
|
||||
*/
|
||||
data[0] = (reg << 1) | ((value >> 8) & 0x0001);
|
||||
data[1] = value & 0x00ff;
|
||||
|
||||
wm8731_write_reg_cache (codec, reg, value);
|
||||
if (codec->hw_write(codec->control_data, data, 2) == 2)
|
||||
return 0;
|
||||
else
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#define wm8731_reset(c) wm8731_write(c, WM8731_RESET, 0)
|
||||
|
||||
static const char *wm8731_input_select[] = {"Line In", "Mic"};
|
||||
static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
|
||||
|
||||
static const struct soc_enum wm8731_enum[] = {
|
||||
SOC_ENUM_SINGLE(WM8731_APANA, 2, 2, wm8731_input_select),
|
||||
SOC_ENUM_SINGLE(WM8731_APDIGI, 1, 4, wm8731_deemph),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new wm8731_snd_controls[] = {
|
||||
|
||||
SOC_DOUBLE_R("Master Playback Volume", WM8731_LOUT1V, WM8731_ROUT1V,
|
||||
0, 127, 0),
|
||||
SOC_DOUBLE_R("Master Playback ZC Switch", WM8731_LOUT1V, WM8731_ROUT1V,
|
||||
7, 1, 0),
|
||||
|
||||
SOC_DOUBLE_R("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0),
|
||||
SOC_DOUBLE_R("Line Capture Switch", WM8731_LINVOL, WM8731_RINVOL, 7, 1, 1),
|
||||
|
||||
SOC_SINGLE("Mic Boost (+20dB)", WM8731_APANA, 0, 1, 0),
|
||||
SOC_SINGLE("Capture Mic Switch", WM8731_APANA, 1, 1, 1),
|
||||
|
||||
SOC_SINGLE("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1),
|
||||
|
||||
SOC_SINGLE("ADC High Pass Filter Switch", WM8731_APDIGI, 0, 1, 1),
|
||||
SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0),
|
||||
|
||||
SOC_ENUM("Playback De-emphasis", wm8731_enum[1]),
|
||||
};
|
||||
|
||||
/* add non dapm controls */
|
||||
static int wm8731_add_controls(struct snd_soc_codec *codec)
|
||||
{
|
||||
int err, i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wm8731_snd_controls); i++) {
|
||||
if ((err = snd_ctl_add(codec->card,
|
||||
snd_soc_cnew(&wm8731_snd_controls[i],codec, NULL))) < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Output Mixer */
|
||||
static const struct snd_kcontrol_new wm8731_output_mixer_controls[] = {
|
||||
SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
|
||||
SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0),
|
||||
SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
|
||||
};
|
||||
|
||||
/* Input mux */
|
||||
static const struct snd_kcontrol_new wm8731_input_mux_controls =
|
||||
SOC_DAPM_ENUM("Input Select", wm8731_enum[0]);
|
||||
|
||||
static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1,
|
||||
&wm8731_output_mixer_controls[0],
|
||||
ARRAY_SIZE(wm8731_output_mixer_controls)),
|
||||
SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8731_PWR, 3, 1),
|
||||
SND_SOC_DAPM_OUTPUT("LOUT"),
|
||||
SND_SOC_DAPM_OUTPUT("LHPOUT"),
|
||||
SND_SOC_DAPM_OUTPUT("ROUT"),
|
||||
SND_SOC_DAPM_OUTPUT("RHPOUT"),
|
||||
SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8731_PWR, 2, 1),
|
||||
SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, &wm8731_input_mux_controls),
|
||||
SND_SOC_DAPM_PGA("Line Input", WM8731_PWR, 0, 1, NULL, 0),
|
||||
SND_SOC_DAPM_MICBIAS("Mic Bias", WM8731_PWR, 1, 1),
|
||||
SND_SOC_DAPM_INPUT("MICIN"),
|
||||
SND_SOC_DAPM_INPUT("RLINEIN"),
|
||||
SND_SOC_DAPM_INPUT("LLINEIN"),
|
||||
};
|
||||
|
||||
static const char *intercon[][3] = {
|
||||
/* output mixer */
|
||||
{"Output Mixer", "Line Bypass Switch", "Line Input"},
|
||||
{"Output Mixer", "HiFi Playback Switch", "DAC"},
|
||||
{"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},
|
||||
|
||||
/* outputs */
|
||||
{"RHPOUT", NULL, "Output Mixer"},
|
||||
{"ROUT", NULL, "Output Mixer"},
|
||||
{"LHPOUT", NULL, "Output Mixer"},
|
||||
{"LOUT", NULL, "Output Mixer"},
|
||||
|
||||
/* input mux */
|
||||
{"Input Mux", "Line In", "Line Input"},
|
||||
{"Input Mux", "Mic", "Mic Bias"},
|
||||
{"ADC", NULL, "Input Mux"},
|
||||
|
||||
/* inputs */
|
||||
{"Line Input", NULL, "LLINEIN"},
|
||||
{"Line Input", NULL, "RLINEIN"},
|
||||
{"Mic Bias", NULL, "MICIN"},
|
||||
|
||||
/* terminator */
|
||||
{NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
static int wm8731_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
|
||||
snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
|
||||
}
|
||||
|
||||
/* set up audio path interconnects */
|
||||
for(i = 0; intercon[i][0] != NULL; i++) {
|
||||
snd_soc_dapm_connect_input(codec, intercon[i][0],
|
||||
intercon[i][1], intercon[i][2]);
|
||||
}
|
||||
|
||||
snd_soc_dapm_new_widgets(codec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct _coeff_div {
|
||||
u32 mclk;
|
||||
u32 rate;
|
||||
u16 fs;
|
||||
u8 sr:4;
|
||||
u8 bosr:1;
|
||||
u8 usb:1;
|
||||
};
|
||||
|
||||
/* codec mclk clock divider coefficients */
|
||||
static const struct _coeff_div coeff_div[] = {
|
||||
/* 48k */
|
||||
{12288000, 48000, 256, 0x0, 0x0, 0x0},
|
||||
{18432000, 48000, 384, 0x0, 0x1, 0x0},
|
||||
{12000000, 48000, 250, 0x0, 0x0, 0x1},
|
||||
|
||||
/* 32k */
|
||||
{12288000, 32000, 384, 0x6, 0x0, 0x0},
|
||||
{18432000, 32000, 576, 0x6, 0x1, 0x0},
|
||||
{12000000, 32000, 375, 0x6, 0x0, 0x1},
|
||||
|
||||
/* 8k */
|
||||
{12288000, 8000, 1536, 0x3, 0x0, 0x0},
|
||||
{18432000, 8000, 2304, 0x3, 0x1, 0x0},
|
||||
{11289600, 8000, 1408, 0xb, 0x0, 0x0},
|
||||
{16934400, 8000, 2112, 0xb, 0x1, 0x0},
|
||||
{12000000, 8000, 1500, 0x3, 0x0, 0x1},
|
||||
|
||||
/* 96k */
|
||||
{12288000, 96000, 128, 0x7, 0x0, 0x0},
|
||||
{18432000, 96000, 192, 0x7, 0x1, 0x0},
|
||||
{12000000, 96000, 125, 0x7, 0x0, 0x1},
|
||||
|
||||
/* 44.1k */
|
||||
{11289600, 44100, 256, 0x8, 0x0, 0x0},
|
||||
{16934400, 44100, 384, 0x8, 0x1, 0x0},
|
||||
{12000000, 44100, 272, 0x8, 0x1, 0x1},
|
||||
|
||||
/* 88.2k */
|
||||
{11289600, 88200, 128, 0xf, 0x0, 0x0},
|
||||
{16934400, 88200, 192, 0xf, 0x1, 0x0},
|
||||
{12000000, 88200, 136, 0xf, 0x1, 0x1},
|
||||
};
|
||||
|
||||
static inline int get_coeff(int mclk, int rate)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
|
||||
if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8731_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_device *socdev = rtd->socdev;
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
struct wm8731_priv *wm8731 = codec->private_data;
|
||||
u16 iface = wm8731_read_reg_cache(codec, WM8731_IFACE) & 0xfff3;
|
||||
int i = get_coeff(wm8731->sysclk, params_rate(params));
|
||||
u16 srate = (coeff_div[i].sr << 2) |
|
||||
(coeff_div[i].bosr << 1) | coeff_div[i].usb;
|
||||
|
||||
wm8731_write(codec, WM8731_SRATE, srate);
|
||||
|
||||
/* bit size */
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S20_3LE:
|
||||
iface |= 0x0004;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
iface |= 0x0008;
|
||||
break;
|
||||
}
|
||||
|
||||
wm8731_write(codec, WM8731_IFACE, iface);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8731_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_device *socdev = rtd->socdev;
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
|
||||
/* set active */
|
||||
wm8731_write(codec, WM8731_ACTIVE, 0x0001);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wm8731_shutdown(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_device *socdev = rtd->socdev;
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
|
||||
/* deactivate */
|
||||
if (!codec->active) {
|
||||
udelay(50);
|
||||
wm8731_write(codec, WM8731_ACTIVE, 0x0);
|
||||
}
|
||||
}
|
||||
|
||||
static int wm8731_mute(struct snd_soc_codec_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
u16 mute_reg = wm8731_read_reg_cache(codec, WM8731_APDIGI) & 0xfff7;
|
||||
|
||||
if (mute)
|
||||
wm8731_write(codec, WM8731_APDIGI, mute_reg | 0x8);
|
||||
else
|
||||
wm8731_write(codec, WM8731_APDIGI, mute_reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8731_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
|
||||
int clk_id, unsigned int freq, int dir)
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct wm8731_priv *wm8731 = codec->private_data;
|
||||
|
||||
switch (freq) {
|
||||
case 11289600:
|
||||
case 12000000:
|
||||
case 12288000:
|
||||
case 16934400:
|
||||
case 18432000:
|
||||
wm8731->sysclk = freq;
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
static int wm8731_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
|
||||
unsigned int fmt)
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
u16 iface = 0;
|
||||
|
||||
/* set master/slave audio interface */
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
iface |= 0x0040;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* interface format */
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
iface |= 0x0002;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
iface |= 0x0001;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
iface |= 0x0003;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
iface |= 0x0013;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* clock inversion */
|
||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
case SND_SOC_DAIFMT_NB_NF:
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_IF:
|
||||
iface |= 0x0090;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_NF:
|
||||
iface |= 0x0080;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_NB_IF:
|
||||
iface |= 0x0010;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* set iface */
|
||||
wm8731_write(codec, WM8731_IFACE, iface);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8731_dapm_event(struct snd_soc_codec *codec, int event)
|
||||
{
|
||||
u16 reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f;
|
||||
|
||||
switch (event) {
|
||||
case SNDRV_CTL_POWER_D0: /* full On */
|
||||
/* vref/mid, osc on, dac unmute */
|
||||
wm8731_write(codec, WM8731_PWR, reg);
|
||||
break;
|
||||
case SNDRV_CTL_POWER_D1: /* partial On */
|
||||
case SNDRV_CTL_POWER_D2: /* partial On */
|
||||
break;
|
||||
case SNDRV_CTL_POWER_D3hot: /* Off, with power */
|
||||
/* everything off except vref/vmid, */
|
||||
wm8731_write(codec, WM8731_PWR, reg | 0x0040);
|
||||
break;
|
||||
case SNDRV_CTL_POWER_D3cold: /* Off, without power */
|
||||
/* everything off, dac mute, inactive */
|
||||
wm8731_write(codec, WM8731_ACTIVE, 0x0);
|
||||
wm8731_write(codec, WM8731_PWR, 0xffff);
|
||||
break;
|
||||
}
|
||||
codec->dapm_state = event;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define WM8731_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
|
||||
SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
|
||||
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
|
||||
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
|
||||
SNDRV_PCM_RATE_96000)
|
||||
|
||||
#define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
|
||||
SNDRV_PCM_FMTBIT_S24_LE)
|
||||
|
||||
struct snd_soc_codec_dai wm8731_dai = {
|
||||
.name = "WM8731",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = WM8731_RATES,
|
||||
.formats = WM8731_FORMATS,},
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = WM8731_RATES,
|
||||
.formats = WM8731_FORMATS,},
|
||||
.ops = {
|
||||
.prepare = wm8731_pcm_prepare,
|
||||
.hw_params = wm8731_hw_params,
|
||||
.shutdown = wm8731_shutdown,
|
||||
},
|
||||
.dai_ops = {
|
||||
.digital_mute = wm8731_mute,
|
||||
.set_sysclk = wm8731_set_dai_sysclk,
|
||||
.set_fmt = wm8731_set_dai_fmt,
|
||||
}
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(wm8731_dai);
|
||||
|
||||
static int wm8731_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
|
||||
wm8731_write(codec, WM8731_ACTIVE, 0x0);
|
||||
wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8731_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
int i;
|
||||
u8 data[2];
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
/* Sync reg_cache with the hardware */
|
||||
for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) {
|
||||
data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
|
||||
data[1] = cache[i] & 0x00ff;
|
||||
codec->hw_write(codec->control_data, data, 2);
|
||||
}
|
||||
wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
|
||||
wm8731_dapm_event(codec, codec->suspend_dapm_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* initialise the WM8731 driver
|
||||
* register the mixer and dsp interfaces with the kernel
|
||||
*/
|
||||
static int wm8731_init(struct snd_soc_device *socdev)
|
||||
{
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
int reg, ret = 0;
|
||||
|
||||
codec->name = "WM8731";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->read = wm8731_read_reg_cache;
|
||||
codec->write = wm8731_write;
|
||||
codec->dapm_event = wm8731_dapm_event;
|
||||
codec->dai = &wm8731_dai;
|
||||
codec->num_dai = 1;
|
||||
codec->reg_cache_size = sizeof(wm8731_reg);
|
||||
codec->reg_cache = kmemdup(wm8731_reg, sizeof(wm8731_reg), GFP_KERNEL);
|
||||
if (codec->reg_cache == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
wm8731_reset(codec);
|
||||
|
||||
/* register pcms */
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "wm8731: failed to create pcms\n");
|
||||
goto pcm_err;
|
||||
}
|
||||
|
||||
/* power on device */
|
||||
wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
|
||||
|
||||
/* set the update bits */
|
||||
reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V);
|
||||
wm8731_write(codec, WM8731_LOUT1V, reg | 0x0100);
|
||||
reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V);
|
||||
wm8731_write(codec, WM8731_ROUT1V, reg | 0x0100);
|
||||
reg = wm8731_read_reg_cache(codec, WM8731_LINVOL);
|
||||
wm8731_write(codec, WM8731_LINVOL, reg | 0x0100);
|
||||
reg = wm8731_read_reg_cache(codec, WM8731_RINVOL);
|
||||
wm8731_write(codec, WM8731_RINVOL, reg | 0x0100);
|
||||
|
||||
wm8731_add_controls(codec);
|
||||
wm8731_add_widgets(codec);
|
||||
ret = snd_soc_register_card(socdev);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "wm8731: failed to register card\n");
|
||||
goto card_err;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
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 *wm8731_socdev;
|
||||
|
||||
#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
|
||||
|
||||
/*
|
||||
* WM8731 2 wire address is determined by GPIO5
|
||||
* state during powerup.
|
||||
* low = 0x1a
|
||||
* high = 0x1b
|
||||
*/
|
||||
static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
|
||||
|
||||
/* Magic definition of all other variables and things */
|
||||
I2C_CLIENT_INSMOD;
|
||||
|
||||
static struct i2c_driver wm8731_i2c_driver;
|
||||
static struct i2c_client client_template;
|
||||
|
||||
/* If the i2c layer weren't so broken, we could pass this kind of data
|
||||
around */
|
||||
|
||||
static int wm8731_codec_probe(struct i2c_adapter *adap, int addr, int kind)
|
||||
{
|
||||
struct snd_soc_device *socdev = wm8731_socdev;
|
||||
struct wm8731_setup_data *setup = socdev->codec_data;
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
struct i2c_client *i2c;
|
||||
int ret;
|
||||
|
||||
if (addr != setup->i2c_address)
|
||||
return -ENODEV;
|
||||
|
||||
client_template.adapter = adap;
|
||||
client_template.addr = addr;
|
||||
|
||||
i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
|
||||
if (i2c == NULL) {
|
||||
kfree(codec);
|
||||
return -ENOMEM;
|
||||
}
|
||||
i2c_set_clientdata(i2c, codec);
|
||||
codec->control_data = i2c;
|
||||
|
||||
ret = i2c_attach_client(i2c);
|
||||
if (ret < 0) {
|
||||
err("failed to attach codec at addr %x\n", addr);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = wm8731_init(socdev);
|
||||
if (ret < 0) {
|
||||
err("failed to initialise WM8731\n");
|
||||
goto err;
|
||||
}
|
||||
return ret;
|
||||
|
||||
err:
|
||||
kfree(codec);
|
||||
kfree(i2c);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wm8731_i2c_detach(struct i2c_client *client)
|
||||
{
|
||||
struct snd_soc_codec* codec = i2c_get_clientdata(client);
|
||||
i2c_detach_client(client);
|
||||
kfree(codec->reg_cache);
|
||||
kfree(client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8731_i2c_attach(struct i2c_adapter *adap)
|
||||
{
|
||||
return i2c_probe(adap, &addr_data, wm8731_codec_probe);
|
||||
}
|
||||
|
||||
/* corgi i2c codec control layer */
|
||||
static struct i2c_driver wm8731_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "WM8731 I2C Codec",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.id = I2C_DRIVERID_WM8731,
|
||||
.attach_adapter = wm8731_i2c_attach,
|
||||
.detach_client = wm8731_i2c_detach,
|
||||
.command = NULL,
|
||||
};
|
||||
|
||||
static struct i2c_client client_template = {
|
||||
.name = "WM8731",
|
||||
.driver = &wm8731_i2c_driver,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int wm8731_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct wm8731_setup_data *setup;
|
||||
struct snd_soc_codec *codec;
|
||||
struct wm8731_priv *wm8731;
|
||||
int ret = 0;
|
||||
|
||||
info("WM8731 Audio Codec %s", WM8731_VERSION);
|
||||
|
||||
setup = socdev->codec_data;
|
||||
codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
|
||||
if (codec == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL);
|
||||
if (wm8731 == NULL) {
|
||||
kfree(codec);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
codec->private_data = wm8731;
|
||||
socdev->codec = codec;
|
||||
mutex_init(&codec->mutex);
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
|
||||
wm8731_socdev = socdev;
|
||||
#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
|
||||
if (setup->i2c_address) {
|
||||
normal_i2c[0] = setup->i2c_address;
|
||||
codec->hw_write = (hw_write_t)i2c_master_send;
|
||||
ret = i2c_add_driver(&wm8731_i2c_driver);
|
||||
if (ret != 0)
|
||||
printk(KERN_ERR "can't add i2c driver");
|
||||
}
|
||||
#else
|
||||
/* Add other interfaces here */
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* power down chip */
|
||||
static int wm8731_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
|
||||
if (codec->control_data)
|
||||
wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
|
||||
|
||||
snd_soc_free_pcms(socdev);
|
||||
snd_soc_dapm_free(socdev);
|
||||
#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
|
||||
i2c_del_driver(&wm8731_i2c_driver);
|
||||
#endif
|
||||
kfree(codec->private_data);
|
||||
kfree(codec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_wm8731 = {
|
||||
.probe = wm8731_probe,
|
||||
.remove = wm8731_remove,
|
||||
.suspend = wm8731_suspend,
|
||||
.resume = wm8731_resume,
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC WM8731 driver");
|
||||
MODULE_AUTHOR("Richard Purdie");
|
||||
MODULE_LICENSE("GPL");
|
||||
44
sound/soc/codecs/wm8731.h
Normal file
44
sound/soc/codecs/wm8731.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* wm8731.h -- WM8731 Soc Audio driver
|
||||
*
|
||||
* Copyright 2005 Openedhand Ltd.
|
||||
*
|
||||
* Author: Richard Purdie <richard@openedhand.com>
|
||||
*
|
||||
* Based on wm8753.h
|
||||
*
|
||||
* 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 _WM8731_H
|
||||
#define _WM8731_H
|
||||
|
||||
/* WM8731 register space */
|
||||
|
||||
#define WM8731_LINVOL 0x00
|
||||
#define WM8731_RINVOL 0x01
|
||||
#define WM8731_LOUT1V 0x02
|
||||
#define WM8731_ROUT1V 0x03
|
||||
#define WM8731_APANA 0x04
|
||||
#define WM8731_APDIGI 0x05
|
||||
#define WM8731_PWR 0x06
|
||||
#define WM8731_IFACE 0x07
|
||||
#define WM8731_SRATE 0x08
|
||||
#define WM8731_ACTIVE 0x09
|
||||
#define WM8731_RESET 0x0f
|
||||
|
||||
#define WM8731_CACHEREGNUM 10
|
||||
|
||||
#define WM8731_SYSCLK 0
|
||||
#define WM8731_DAI 0
|
||||
|
||||
struct wm8731_setup_data {
|
||||
unsigned short i2c_address;
|
||||
};
|
||||
|
||||
extern struct snd_soc_codec_dai wm8731_dai;
|
||||
extern struct snd_soc_codec_device soc_codec_dev_wm8731;
|
||||
|
||||
#endif
|
||||
1049
sound/soc/codecs/wm8750.c
Normal file
1049
sound/soc/codecs/wm8750.c
Normal file
File diff suppressed because it is too large
Load Diff
67
sound/soc/codecs/wm8750.h
Normal file
67
sound/soc/codecs/wm8750.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2005 Openedhand Ltd.
|
||||
*
|
||||
* Author: Richard Purdie <richard@openedhand.com>
|
||||
*
|
||||
* Based on WM8753.h
|
||||
*
|
||||
* 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 _WM8750_H
|
||||
#define _WM8750_H
|
||||
|
||||
/* WM8750 register space */
|
||||
|
||||
#define WM8750_LINVOL 0x00
|
||||
#define WM8750_RINVOL 0x01
|
||||
#define WM8750_LOUT1V 0x02
|
||||
#define WM8750_ROUT1V 0x03
|
||||
#define WM8750_ADCDAC 0x05
|
||||
#define WM8750_IFACE 0x07
|
||||
#define WM8750_SRATE 0x08
|
||||
#define WM8750_LDAC 0x0a
|
||||
#define WM8750_RDAC 0x0b
|
||||
#define WM8750_BASS 0x0c
|
||||
#define WM8750_TREBLE 0x0d
|
||||
#define WM8750_RESET 0x0f
|
||||
#define WM8750_3D 0x10
|
||||
#define WM8750_ALC1 0x11
|
||||
#define WM8750_ALC2 0x12
|
||||
#define WM8750_ALC3 0x13
|
||||
#define WM8750_NGATE 0x14
|
||||
#define WM8750_LADC 0x15
|
||||
#define WM8750_RADC 0x16
|
||||
#define WM8750_ADCTL1 0x17
|
||||
#define WM8750_ADCTL2 0x18
|
||||
#define WM8750_PWR1 0x19
|
||||
#define WM8750_PWR2 0x1a
|
||||
#define WM8750_ADCTL3 0x1b
|
||||
#define WM8750_ADCIN 0x1f
|
||||
#define WM8750_LADCIN 0x20
|
||||
#define WM8750_RADCIN 0x21
|
||||
#define WM8750_LOUTM1 0x22
|
||||
#define WM8750_LOUTM2 0x23
|
||||
#define WM8750_ROUTM1 0x24
|
||||
#define WM8750_ROUTM2 0x25
|
||||
#define WM8750_MOUTM1 0x26
|
||||
#define WM8750_MOUTM2 0x27
|
||||
#define WM8750_LOUT2V 0x28
|
||||
#define WM8750_ROUT2V 0x29
|
||||
#define WM8750_MOUTV 0x2a
|
||||
|
||||
#define WM8750_CACHE_REGNUM 0x2a
|
||||
|
||||
#define WM8750_SYSCLK 0
|
||||
|
||||
struct wm8750_setup_data {
|
||||
unsigned short i2c_address;
|
||||
};
|
||||
|
||||
extern struct snd_soc_codec_dai wm8750_dai;
|
||||
extern struct snd_soc_codec_device soc_codec_dev_wm8750;
|
||||
|
||||
#endif
|
||||
1859
sound/soc/codecs/wm8753.c
Normal file
1859
sound/soc/codecs/wm8753.c
Normal file
File diff suppressed because it is too large
Load Diff
126
sound/soc/codecs/wm8753.h
Normal file
126
sound/soc/codecs/wm8753.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* wm8753.h -- audio driver for WM8753
|
||||
*
|
||||
* Copyright 2003 Wolfson Microelectronics PLC.
|
||||
* Author: Liam Girdwood
|
||||
* liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _WM8753_H
|
||||
#define _WM8753_H
|
||||
|
||||
/* WM8753 register space */
|
||||
|
||||
#define WM8753_DAC 0x01
|
||||
#define WM8753_ADC 0x02
|
||||
#define WM8753_PCM 0x03
|
||||
#define WM8753_HIFI 0x04
|
||||
#define WM8753_IOCTL 0x05
|
||||
#define WM8753_SRATE1 0x06
|
||||
#define WM8753_SRATE2 0x07
|
||||
#define WM8753_LDAC 0x08
|
||||
#define WM8753_RDAC 0x09
|
||||
#define WM8753_BASS 0x0a
|
||||
#define WM8753_TREBLE 0x0b
|
||||
#define WM8753_ALC1 0x0c
|
||||
#define WM8753_ALC2 0x0d
|
||||
#define WM8753_ALC3 0x0e
|
||||
#define WM8753_NGATE 0x0f
|
||||
#define WM8753_LADC 0x10
|
||||
#define WM8753_RADC 0x11
|
||||
#define WM8753_ADCTL1 0x12
|
||||
#define WM8753_3D 0x13
|
||||
#define WM8753_PWR1 0x14
|
||||
#define WM8753_PWR2 0x15
|
||||
#define WM8753_PWR3 0x16
|
||||
#define WM8753_PWR4 0x17
|
||||
#define WM8753_ID 0x18
|
||||
#define WM8753_INTPOL 0x19
|
||||
#define WM8753_INTEN 0x1a
|
||||
#define WM8753_GPIO1 0x1b
|
||||
#define WM8753_GPIO2 0x1c
|
||||
#define WM8753_RESET 0x1f
|
||||
#define WM8753_RECMIX1 0x20
|
||||
#define WM8753_RECMIX2 0x21
|
||||
#define WM8753_LOUTM1 0x22
|
||||
#define WM8753_LOUTM2 0x23
|
||||
#define WM8753_ROUTM1 0x24
|
||||
#define WM8753_ROUTM2 0x25
|
||||
#define WM8753_MOUTM1 0x26
|
||||
#define WM8753_MOUTM2 0x27
|
||||
#define WM8753_LOUT1V 0x28
|
||||
#define WM8753_ROUT1V 0x29
|
||||
#define WM8753_LOUT2V 0x2a
|
||||
#define WM8753_ROUT2V 0x2b
|
||||
#define WM8753_MOUTV 0x2c
|
||||
#define WM8753_OUTCTL 0x2d
|
||||
#define WM8753_ADCIN 0x2e
|
||||
#define WM8753_INCTL1 0x2f
|
||||
#define WM8753_INCTL2 0x30
|
||||
#define WM8753_LINVOL 0x31
|
||||
#define WM8753_RINVOL 0x32
|
||||
#define WM8753_MICBIAS 0x33
|
||||
#define WM8753_CLOCK 0x34
|
||||
#define WM8753_PLL1CTL1 0x35
|
||||
#define WM8753_PLL1CTL2 0x36
|
||||
#define WM8753_PLL1CTL3 0x37
|
||||
#define WM8753_PLL1CTL4 0x38
|
||||
#define WM8753_PLL2CTL1 0x39
|
||||
#define WM8753_PLL2CTL2 0x3a
|
||||
#define WM8753_PLL2CTL3 0x3b
|
||||
#define WM8753_PLL2CTL4 0x3c
|
||||
#define WM8753_BIASCTL 0x3d
|
||||
#define WM8753_ADCTL2 0x3f
|
||||
|
||||
struct wm8753_setup_data {
|
||||
unsigned short i2c_address;
|
||||
};
|
||||
|
||||
#define WM8753_PLL1 0
|
||||
#define WM8753_PLL2 1
|
||||
|
||||
/* clock inputs */
|
||||
#define WM8753_MCLK 0
|
||||
#define WM8753_PCMCLK 1
|
||||
|
||||
/* clock divider id's */
|
||||
#define WM8753_PCMDIV 0
|
||||
#define WM8753_BCLKDIV 1
|
||||
#define WM8753_VXCLKDIV 2
|
||||
|
||||
/* PCM clock dividers */
|
||||
#define WM8753_PCM_DIV_1 (0 << 6)
|
||||
#define WM8753_PCM_DIV_3 (2 << 6)
|
||||
#define WM8753_PCM_DIV_5_5 (3 << 6)
|
||||
#define WM8753_PCM_DIV_2 (4 << 6)
|
||||
#define WM8753_PCM_DIV_4 (5 << 6)
|
||||
#define WM8753_PCM_DIV_6 (6 << 6)
|
||||
#define WM8753_PCM_DIV_8 (7 << 6)
|
||||
|
||||
/* BCLK clock dividers */
|
||||
#define WM8753_BCLK_DIV_1 (0 << 3)
|
||||
#define WM8753_BCLK_DIV_2 (1 << 3)
|
||||
#define WM8753_BCLK_DIV_4 (2 << 3)
|
||||
#define WM8753_BCLK_DIV_8 (3 << 3)
|
||||
#define WM8753_BCLK_DIV_16 (4 << 3)
|
||||
|
||||
/* VXCLK clock dividers */
|
||||
#define WM8753_VXCLK_DIV_1 (0 << 6)
|
||||
#define WM8753_VXCLK_DIV_2 (1 << 6)
|
||||
#define WM8753_VXCLK_DIV_4 (2 << 6)
|
||||
#define WM8753_VXCLK_DIV_8 (3 << 6)
|
||||
#define WM8753_VXCLK_DIV_16 (4 << 6)
|
||||
|
||||
#define WM8753_DAI_HIFI 0
|
||||
#define WM8753_DAI_VOICE 1
|
||||
|
||||
extern struct snd_soc_codec_dai wm8753_dai[2];
|
||||
extern struct snd_soc_codec_device soc_codec_dev_wm8753;
|
||||
|
||||
#endif
|
||||
807
sound/soc/codecs/wm8772.c
Normal file
807
sound/soc/codecs/wm8772.c
Normal file
@@ -0,0 +1,807 @@
|
||||
/*
|
||||
* wm8772.c -- WM8772 ALSA Soc Audio driver
|
||||
*
|
||||
* Copyright 2005 Wolfson Microelectronics PLC.
|
||||
* Author: Liam Girdwood
|
||||
* liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include <sound/driver.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/initval.h>
|
||||
|
||||
#include "wm8772.h"
|
||||
|
||||
#define AUDIO_NAME "WM8772"
|
||||
#define WM8772_VERSION "0.3"
|
||||
|
||||
/*
|
||||
* wm8772 register cache
|
||||
* We can't read the WM8772 register space when we
|
||||
* are using 2 wire for device control, so we cache them instead.
|
||||
*/
|
||||
static const u16 wm8772_reg[] = {
|
||||
0x00ff, 0x00ff, 0x0120, 0x0000, /* 0 */
|
||||
0x00ff, 0x00ff, 0x00ff, 0x00ff, /* 4 */
|
||||
0x00ff, 0x0000, 0x0080, 0x0040, /* 8 */
|
||||
0x0000
|
||||
};
|
||||
|
||||
#define WM8772_DAIFMT \
|
||||
(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_RIGHT_J | \
|
||||
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_IB_NF)
|
||||
|
||||
#define WM8772_DIR \
|
||||
(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
|
||||
|
||||
#define WM8772_PRATES \
|
||||
(SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
|
||||
SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
|
||||
|
||||
#define WM8772_CRATES \
|
||||
(SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
|
||||
SNDRV_PCM_RATE_96000)
|
||||
|
||||
static struct snd_soc_dai_mode wm8772_modes[] = {
|
||||
/* common codec frame and clock master modes */
|
||||
/* 32k */
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_32000,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 768,
|
||||
.bfs = 64,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_32000,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 512,
|
||||
.bfs = 64,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_32000,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 384,
|
||||
.bfs = 64,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_32000,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 256,
|
||||
.bfs = 64,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_32000,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 192,
|
||||
.bfs = 64,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_32000,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 128,
|
||||
.bfs = 64,
|
||||
},
|
||||
|
||||
/* 44.1k */
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_44100,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 768,
|
||||
.bfs = 64,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_44100,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 512,
|
||||
.bfs = 64,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_44100,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 384,
|
||||
.bfs = 64,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_44100,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 256,
|
||||
.bfs = 64,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_44100,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 192,
|
||||
.bfs = 64,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_44100,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 128,
|
||||
.bfs = 64,
|
||||
},
|
||||
|
||||
/* 48k */
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_48000,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 768,
|
||||
.bfs = 64,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_48000,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 512,
|
||||
.bfs = 64,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_48000,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 384,
|
||||
.bfs = 64,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_48000,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 256,
|
||||
.bfs = 64,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_48000,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 192,
|
||||
.bfs = 64,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_48000,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 128,
|
||||
.bfs = 64,
|
||||
},
|
||||
|
||||
/* 96k */
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_96000,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 384,
|
||||
.bfs = 64,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_96000,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 256,
|
||||
.bfs = 64,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_96000,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 192,
|
||||
.bfs = 64,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_96000,
|
||||
.pcmdir = WM8772_DIR,
|
||||
.pcmrate = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 128,
|
||||
.bfs = 64,
|
||||
},
|
||||
|
||||
/* 192k */
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_192000,
|
||||
.pcmdir = SND_SOC_DAIDIR_PLAYBACK,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 192,
|
||||
.bfs = 64,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = SNDRV_PCM_RATE_192000,
|
||||
.pcmdir = SND_SOC_DAIDIR_PLAYBACK,
|
||||
.flags = SND_SOC_DAI_BFS_RATE,
|
||||
.fs = 128,
|
||||
.bfs = 64,
|
||||
},
|
||||
|
||||
/* slave mode */
|
||||
{
|
||||
.fmt = WM8772_DAIFMT,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = WM8772_PRATES,
|
||||
.pcmdir = SND_SOC_DAIDIR_PLAYBACK,
|
||||
.fs = SND_SOC_FS_ALL,
|
||||
.bfs = SND_SOC_FSB_ALL,
|
||||
},
|
||||
{
|
||||
.fmt = WM8772_DAIFMT,
|
||||
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.pcmrate = WM8772_CRATES,
|
||||
.pcmdir = SND_SOC_DAIDIR_CAPTURE,
|
||||
.fs = SND_SOC_FS_ALL,
|
||||
.bfs = SND_SOC_FSB_ALL,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* read wm8772 register cache
|
||||
*/
|
||||
static inline unsigned int wm8772_read_reg_cache(struct snd_soc_codec * codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
u16 *cache = codec->reg_cache;
|
||||
if (reg > WM8772_CACHE_REGNUM)
|
||||
return -1;
|
||||
return cache[reg];
|
||||
}
|
||||
|
||||
/*
|
||||
* write wm8772 register cache
|
||||
*/
|
||||
static inline void wm8772_write_reg_cache(struct snd_soc_codec * codec,
|
||||
unsigned int reg, unsigned int value)
|
||||
{
|
||||
u16 *cache = codec->reg_cache;
|
||||
if (reg > WM8772_CACHE_REGNUM)
|
||||
return;
|
||||
cache[reg] = value;
|
||||
}
|
||||
|
||||
static int wm8772_write(struct snd_soc_codec * codec, unsigned int reg,
|
||||
unsigned int value)
|
||||
{
|
||||
u8 data[2];
|
||||
|
||||
/* data is
|
||||
* D15..D9 WM8772 register offset
|
||||
* D8...D0 register data
|
||||
*/
|
||||
data[0] = (reg << 1) | ((value >> 8) & 0x0001);
|
||||
data[1] = value & 0x00ff;
|
||||
|
||||
wm8772_write_reg_cache (codec, reg, value);
|
||||
if (codec->hw_write(codec->control_data, data, 2) == 2)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define wm8772_reset(c) wm8772_write(c, WM8772_RESET, 0)
|
||||
|
||||
/*
|
||||
* WM8772 Controls
|
||||
*/
|
||||
static const char *wm8772_zero_flag[] = {"All Ch", "Ch 1", "Ch 2", "Ch3"};
|
||||
|
||||
static const struct soc_enum wm8772_enum[] = {
|
||||
SOC_ENUM_SINGLE(WM8772_DACCTRL, 0, 4, wm8772_zero_flag),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new wm8772_snd_controls[] = {
|
||||
|
||||
SOC_SINGLE("Left1 Playback Volume", WM8772_LDAC1VOL, 0, 255, 0),
|
||||
SOC_SINGLE("Left2 Playback Volume", WM8772_LDAC2VOL, 0, 255, 0),
|
||||
SOC_SINGLE("Left3 Playback Volume", WM8772_LDAC3VOL, 0, 255, 0),
|
||||
SOC_SINGLE("Right1 Playback Volume", WM8772_RDAC1VOL, 0, 255, 0),
|
||||
SOC_SINGLE("Right1 Playback Volume", WM8772_RDAC2VOL, 0, 255, 0),
|
||||
SOC_SINGLE("Right1 Playback Volume", WM8772_RDAC3VOL, 0, 255, 0),
|
||||
SOC_SINGLE("Master Playback Volume", WM8772_MDACVOL, 0, 255, 0),
|
||||
|
||||
SOC_SINGLE("Playback Switch", WM8772_DACCH, 0, 1, 0),
|
||||
SOC_SINGLE("Capture Switch", WM8772_ADCCTRL, 2, 1, 0),
|
||||
|
||||
SOC_SINGLE("Demp1 Playback Switch", WM8772_DACCTRL, 6, 1, 0),
|
||||
SOC_SINGLE("Demp2 Playback Switch", WM8772_DACCTRL, 7, 1, 0),
|
||||
SOC_SINGLE("Demp3 Playback Switch", WM8772_DACCTRL, 8, 1, 0),
|
||||
|
||||
SOC_SINGLE("Phase Invert 1 Switch", WM8772_IFACE, 6, 1, 0),
|
||||
SOC_SINGLE("Phase Invert 2 Switch", WM8772_IFACE, 7, 1, 0),
|
||||
SOC_SINGLE("Phase Invert 3 Switch", WM8772_IFACE, 8, 1, 0),
|
||||
|
||||
SOC_SINGLE("Playback ZC Switch", WM8772_DACCTRL, 0, 1, 0),
|
||||
|
||||
SOC_SINGLE("Capture High Pass Switch", WM8772_ADCCTRL, 3, 1, 0),
|
||||
};
|
||||
|
||||
/* add non dapm controls */
|
||||
static int wm8772_add_controls(struct snd_soc_codec *codec)
|
||||
{
|
||||
int err, i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wm8772_snd_controls); i++) {
|
||||
err = snd_ctl_add(codec->card,
|
||||
snd_soc_cnew(&wm8772_snd_controls[i],codec, NULL));
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* valid wm8772 mclk frequencies */
|
||||
static const int freq_table[5][6] = {
|
||||
{4096000, 6144000, 8192000, 12288000, 16384000, 24576000},
|
||||
{5644800, 8467000, 11289600, 16934000, 22579200, 33868800},
|
||||
{6144000, 9216000, 12288000, 18432000, 24576000, 36864000},
|
||||
{12288000, 18432000, 24576000, 36864000, 0, 0},
|
||||
{24576000, 36864000, 0, 0, 0},
|
||||
};
|
||||
|
||||
static unsigned int check_freq(int rate, unsigned int freq)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 6; i++) {
|
||||
if(freq == freq_table[i][rate])
|
||||
return freq;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int wm8772_config_sysclk(struct snd_soc_codec_dai *dai,
|
||||
struct snd_soc_clock_info *info, unsigned int clk)
|
||||
{
|
||||
switch (info->rate){
|
||||
case 32000:
|
||||
dai->mclk = check_freq(0, clk);
|
||||
break;
|
||||
case 44100:
|
||||
dai->mclk = check_freq(1, clk);
|
||||
break;
|
||||
case 48000:
|
||||
dai->mclk = check_freq(2, clk);
|
||||
break;
|
||||
case 96000:
|
||||
dai->mclk = check_freq(3, clk);
|
||||
break;
|
||||
case 192000:
|
||||
dai->mclk = check_freq(4, clk);
|
||||
break;
|
||||
default:
|
||||
dai->mclk = 0;
|
||||
}
|
||||
return dai->mclk;
|
||||
}
|
||||
|
||||
static int wm8772_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_device *socdev = rtd->socdev;
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
u16 diface = wm8772_read_reg_cache(codec, WM8772_IFACE) & 0xffc0;
|
||||
u16 diface_ctrl = wm8772_read_reg_cache(codec, WM8772_DACRATE) & 0xfe1f;
|
||||
u16 aiface = 0;
|
||||
u16 aiface_ctrl = wm8772_read_reg_cache(codec, WM8772_ADCCTRL) & 0xfcff;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
|
||||
/* set master/slave audio interface */
|
||||
switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
diface_ctrl |= 0x0010;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
break;
|
||||
}
|
||||
|
||||
/* interface format */
|
||||
switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
diface |= 0x0002;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
diface |= 0x0001;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
diface |= 0x0003;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
diface |= 0x0007;
|
||||
break;
|
||||
}
|
||||
|
||||
/* bit size */
|
||||
switch (rtd->codec_dai->dai_runtime.pcmfmt) {
|
||||
case SNDRV_PCM_FMTBIT_S16_LE:
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S20_3LE:
|
||||
diface |= 0x0010;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_3LE:
|
||||
diface |= 0x0020;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
diface |= 0x0030;
|
||||
break;
|
||||
}
|
||||
|
||||
/* clock inversion */
|
||||
switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
case SND_SOC_DAIFMT_NB_NF:
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_NF:
|
||||
diface |= 0x0008;
|
||||
break;
|
||||
}
|
||||
|
||||
/* set rate */
|
||||
switch (rtd->codec_dai->dai_runtime.fs) {
|
||||
case 768:
|
||||
diface_ctrl |= (0x5 << 6);
|
||||
break;
|
||||
case 512:
|
||||
diface_ctrl |= (0x4 << 6);
|
||||
break;
|
||||
case 384:
|
||||
diface_ctrl |= (0x3 << 6);
|
||||
break;
|
||||
case 256:
|
||||
diface_ctrl |= (0x2 << 6);
|
||||
break;
|
||||
case 192:
|
||||
diface_ctrl |= (0x1 << 6);
|
||||
break;
|
||||
}
|
||||
|
||||
wm8772_write(codec, WM8772_DACRATE, diface_ctrl);
|
||||
wm8772_write(codec, WM8772_IFACE, diface);
|
||||
|
||||
} else {
|
||||
|
||||
/* set master/slave audio interface */
|
||||
switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
aiface |= 0x0010;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
break;
|
||||
}
|
||||
|
||||
/* interface format */
|
||||
switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
aiface |= 0x0002;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
aiface |= 0x0001;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
aiface |= 0x0003;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
aiface |= 0x0003;
|
||||
aiface_ctrl |= 0x0010;
|
||||
break;
|
||||
}
|
||||
|
||||
/* bit size */
|
||||
switch (rtd->codec_dai->dai_runtime.pcmfmt) {
|
||||
case SNDRV_PCM_FMTBIT_S16_LE:
|
||||
break;
|
||||
case SNDRV_PCM_FMTBIT_S20_3LE:
|
||||
aiface |= 0x0004;
|
||||
break;
|
||||
case SNDRV_PCM_FMTBIT_S24_LE:
|
||||
aiface |= 0x0008;
|
||||
break;
|
||||
case SNDRV_PCM_FMTBIT_S32_LE:
|
||||
aiface |= 0x000c;
|
||||
break;
|
||||
}
|
||||
|
||||
/* clock inversion */
|
||||
switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
case SND_SOC_DAIFMT_NB_NF:
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_NF:
|
||||
aiface_ctrl |= 0x0020;
|
||||
break;
|
||||
}
|
||||
|
||||
/* set rate */
|
||||
switch (rtd->codec_dai->dai_runtime.fs) {
|
||||
case 768:
|
||||
aiface |= (0x5 << 5);
|
||||
break;
|
||||
case 512:
|
||||
aiface |= (0x4 << 5);
|
||||
break;
|
||||
case 384:
|
||||
aiface |= (0x3 << 5);
|
||||
break;
|
||||
case 256:
|
||||
aiface |= (0x2 << 5);
|
||||
break;
|
||||
}
|
||||
|
||||
wm8772_write(codec, WM8772_ADCCTRL, aiface_ctrl);
|
||||
wm8772_write(codec, WM8772_ADCRATE, aiface);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8772_dapm_event(struct snd_soc_codec *codec, int event)
|
||||
{
|
||||
u16 master = wm8772_read_reg_cache(codec, WM8772_DACRATE) & 0xffe0;
|
||||
|
||||
switch (event) {
|
||||
case SNDRV_CTL_POWER_D0: /* full On */
|
||||
/* vref/mid, clk and osc on, dac unmute, active */
|
||||
wm8772_write(codec, WM8772_DACRATE, master);
|
||||
break;
|
||||
case SNDRV_CTL_POWER_D1: /* partial On */
|
||||
case SNDRV_CTL_POWER_D2: /* partial On */
|
||||
break;
|
||||
case SNDRV_CTL_POWER_D3hot: /* Off, with power */
|
||||
/* everything off except vref/vmid, dac mute, inactive */
|
||||
wm8772_write(codec, WM8772_DACRATE, master | 0x0f);
|
||||
break;
|
||||
case SNDRV_CTL_POWER_D3cold: /* Off, without power */
|
||||
/* everything off, dac mute, inactive */
|
||||
wm8772_write(codec, WM8772_DACRATE, master | 0x1f);
|
||||
break;
|
||||
}
|
||||
codec->dapm_state = event;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_codec_dai wm8772_dai = {
|
||||
.name = "WM8772",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 6,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
},
|
||||
.config_sysclk = wm8772_config_sysclk,
|
||||
.ops = {
|
||||
.prepare = wm8772_pcm_prepare,
|
||||
},
|
||||
.caps = {
|
||||
.num_modes = ARRAY_SIZE(wm8772_modes),
|
||||
.mode = wm8772_modes,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(wm8772_dai);
|
||||
|
||||
static int wm8772_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
|
||||
wm8772_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8772_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
int i;
|
||||
u8 data[2];
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
/* Sync reg_cache with the hardware */
|
||||
for (i = 0; i < ARRAY_SIZE(wm8772_reg); i++) {
|
||||
data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
|
||||
data[1] = cache[i] & 0x00ff;
|
||||
codec->hw_write(codec->control_data, data, 2);
|
||||
}
|
||||
wm8772_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
|
||||
wm8772_dapm_event(codec, codec->suspend_dapm_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* initialise the WM8772 driver
|
||||
* register the mixer and dsp interfaces with the kernel
|
||||
*/
|
||||
static int wm8772_init(struct snd_soc_device *socdev)
|
||||
{
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
int reg, ret = 0;
|
||||
|
||||
codec->name = "WM8772";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->read = wm8772_read_reg_cache;
|
||||
codec->write = wm8772_write;
|
||||
codec->dapm_event = wm8772_dapm_event;
|
||||
codec->dai = &wm8772_dai;
|
||||
codec->num_dai = 1;
|
||||
codec->reg_cache_size = ARRAY_SIZE(wm8772_reg);
|
||||
codec->reg_cache =
|
||||
kzalloc(sizeof(u16) * ARRAY_SIZE(wm8772_reg), GFP_KERNEL);
|
||||
if (codec->reg_cache == NULL)
|
||||
return -ENOMEM;
|
||||
memcpy(codec->reg_cache, wm8772_reg,
|
||||
sizeof(u16) * ARRAY_SIZE(wm8772_reg));
|
||||
codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(wm8772_reg);
|
||||
|
||||
wm8772_reset(codec);
|
||||
|
||||
/* register pcms */
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
if(ret < 0) {
|
||||
kfree(codec->reg_cache);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* power on device */
|
||||
wm8772_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
|
||||
|
||||
/* set the update bits */
|
||||
reg = wm8772_read_reg_cache(codec, WM8772_MDACVOL);
|
||||
wm8772_write(codec, WM8772_MDACVOL, reg | 0x0100);
|
||||
reg = wm8772_read_reg_cache(codec, WM8772_LDAC1VOL);
|
||||
wm8772_write(codec, WM8772_LDAC1VOL, reg | 0x0100);
|
||||
reg = wm8772_read_reg_cache(codec, WM8772_LDAC2VOL);
|
||||
wm8772_write(codec, WM8772_LDAC2VOL, reg | 0x0100);
|
||||
reg = wm8772_read_reg_cache(codec, WM8772_LDAC3VOL);
|
||||
wm8772_write(codec, WM8772_LDAC3VOL, reg | 0x0100);
|
||||
reg = wm8772_read_reg_cache(codec, WM8772_RDAC1VOL);
|
||||
wm8772_write(codec, WM8772_RDAC1VOL, reg | 0x0100);
|
||||
reg = wm8772_read_reg_cache(codec, WM8772_RDAC2VOL);
|
||||
wm8772_write(codec, WM8772_RDAC2VOL, reg | 0x0100);
|
||||
reg = wm8772_read_reg_cache(codec, WM8772_RDAC3VOL);
|
||||
wm8772_write(codec, WM8772_RDAC3VOL, reg | 0x0100);
|
||||
|
||||
wm8772_add_controls(codec);
|
||||
ret = snd_soc_register_card(socdev);
|
||||
if (ret < 0) {
|
||||
snd_soc_free_pcms(socdev);
|
||||
snd_soc_dapm_free(socdev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct snd_soc_device *wm8772_socdev;
|
||||
|
||||
static int wm8772_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct wm8772_setup_data *setup;
|
||||
struct snd_soc_codec *codec;
|
||||
int ret = 0;
|
||||
|
||||
printk(KERN_INFO "WM8772 Audio Codec %s", WM8772_VERSION);
|
||||
|
||||
setup = socdev->codec_data;
|
||||
codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
|
||||
if (codec == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
socdev->codec = codec;
|
||||
mutex_init(&codec->mutex);
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
|
||||
wm8772_socdev = socdev;
|
||||
|
||||
/* Add other interfaces here */
|
||||
#warning do SPI device probe here and then call wm8772_init()
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* power down chip */
|
||||
static int wm8772_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
|
||||
if (codec->control_data)
|
||||
wm8772_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
|
||||
|
||||
snd_soc_free_pcms(socdev);
|
||||
kfree(codec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_wm8772 = {
|
||||
.probe = wm8772_probe,
|
||||
.remove = wm8772_remove,
|
||||
.suspend = wm8772_suspend,
|
||||
.resume = wm8772_resume,
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8772);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC WM8772 driver");
|
||||
MODULE_AUTHOR("Liam Girdwood");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
41
sound/soc/codecs/wm8772.h
Normal file
41
sound/soc/codecs/wm8772.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* wm8772.h -- audio driver for WM8772
|
||||
*
|
||||
* Copyright 2005 Wolfson Microelectronics PLC.
|
||||
* Author: Liam Girdwood
|
||||
* liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _WM8772_H
|
||||
#define _WM8772_H
|
||||
|
||||
/* WM8772 register space */
|
||||
|
||||
#define WM8772_LDAC1VOL 0x00
|
||||
#define WM8772_RDAC1VOL 0x01
|
||||
#define WM8772_DACCH 0x02
|
||||
#define WM8772_IFACE 0x03
|
||||
#define WM8772_LDAC2VOL 0x04
|
||||
#define WM8772_RDAC2VOL 0x05
|
||||
#define WM8772_LDAC3VOL 0x06
|
||||
#define WM8772_RDAC3VOL 0x07
|
||||
#define WM8772_MDACVOL 0x08
|
||||
#define WM8772_DACCTRL 0x09
|
||||
#define WM8772_DACRATE 0x0a
|
||||
#define WM8772_ADCRATE 0x0b
|
||||
#define WM8772_ADCCTRL 0x0c
|
||||
#define WM8772_RESET 0x1f
|
||||
|
||||
#define WM8772_CACHE_REGNUM 10
|
||||
|
||||
extern struct snd_soc_codec_dai wm8772_dai;
|
||||
extern struct snd_soc_codec_device soc_codec_dev_wm8772;
|
||||
|
||||
#endif
|
||||
|
||||
1657
sound/soc/codecs/wm8990.c
Normal file
1657
sound/soc/codecs/wm8990.c
Normal file
File diff suppressed because it is too large
Load Diff
904
sound/soc/codecs/wm8990.h
Normal file
904
sound/soc/codecs/wm8990.h
Normal file
@@ -0,0 +1,904 @@
|
||||
/*
|
||||
* wm8753.h -- audio driver for WM8753
|
||||
*
|
||||
* Copyright 2007 Wolfson Microelectronics PLC.
|
||||
* Author: Graeme Gregory
|
||||
* graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __WM8990REGISTERDEFS_H__
|
||||
#define __WM8990REGISTERDEFS_H__
|
||||
|
||||
/*
|
||||
* Register values.
|
||||
*/
|
||||
#define WM8990_RESET 0x00
|
||||
#define WM8990_POWER_MANAGEMENT_1 0x01
|
||||
#define WM8990_POWER_MANAGEMENT_2 0x02
|
||||
#define WM8990_POWER_MANAGEMENT_3 0x03
|
||||
#define WM8990_AUDIO_INTERFACE_1 0x04
|
||||
#define WM8990_AUDIO_INTERFACE_2 0x05
|
||||
#define WM8990_CLOCKING_1 0x06
|
||||
#define WM8990_CLOCKING_2 0x07
|
||||
#define WM8990_AUDIO_INTERFACE_3 0x08
|
||||
#define WM8990_AUDIO_INTERFACE_4 0x09
|
||||
#define WM8990_DAC_CTRL 0x0A
|
||||
#define WM8990_LEFT_DAC_DIGITAL_VOLUME 0x0B
|
||||
#define WM8990_RIGHT_DAC_DIGITAL_VOLUME 0x0C
|
||||
#define WM8990_DIGITAL_SIDE_TONE 0x0D
|
||||
#define WM8990_ADC_CTRL 0x0E
|
||||
#define WM8990_LEFT_ADC_DIGITAL_VOLUME 0x0F
|
||||
#define WM8990_RIGHT_ADC_DIGITAL_VOLUME 0x10
|
||||
#define WM8990_GPIO_CTRL_1 0x12
|
||||
#define WM8990_GPIO1_GPIO2 0x13
|
||||
#define WM8990_GPIO3_GPIO4 0x14
|
||||
#define WM8990_GPIO5_GPIO6 0x15
|
||||
#define WM8990_GPIOCTRL_2 0x16
|
||||
#define WM8990_GPIO_POL 0x17
|
||||
#define WM8990_LEFT_LINE_INPUT_1_2_VOLUME 0x18
|
||||
#define WM8990_LEFT_LINE_INPUT_3_4_VOLUME 0x19
|
||||
#define WM8990_RIGHT_LINE_INPUT_1_2_VOLUME 0x1A
|
||||
#define WM8990_RIGHT_LINE_INPUT_3_4_VOLUME 0x1B
|
||||
#define WM8990_LEFT_OUTPUT_VOLUME 0x1C
|
||||
#define WM8990_RIGHT_OUTPUT_VOLUME 0x1D
|
||||
#define WM8990_LINE_OUTPUTS_VOLUME 0x1E
|
||||
#define WM8990_OUT3_4_VOLUME 0x1F
|
||||
#define WM8990_LEFT_OPGA_VOLUME 0x20
|
||||
#define WM8990_RIGHT_OPGA_VOLUME 0x21
|
||||
#define WM8990_SPEAKER_VOLUME 0x22
|
||||
#define WM8990_CLASSD1 0x23
|
||||
#define WM8990_CLASSD3 0x25
|
||||
#define WM8990_INPUT_MIXER1 0x27
|
||||
#define WM8990_INPUT_MIXER2 0x28
|
||||
#define WM8990_INPUT_MIXER3 0x29
|
||||
#define WM8990_INPUT_MIXER4 0x2A
|
||||
#define WM8990_INPUT_MIXER5 0x2B
|
||||
#define WM8990_INPUT_MIXER6 0x2C
|
||||
#define WM8990_OUTPUT_MIXER1 0x2D
|
||||
#define WM8990_OUTPUT_MIXER2 0x2E
|
||||
#define WM8990_OUTPUT_MIXER3 0x2F
|
||||
#define WM8990_OUTPUT_MIXER4 0x30
|
||||
#define WM8990_OUTPUT_MIXER5 0x31
|
||||
#define WM8990_OUTPUT_MIXER6 0x32
|
||||
#define WM8990_OUT3_4_MIXER 0x33
|
||||
#define WM8990_LINE_MIXER1 0x34
|
||||
#define WM8990_LINE_MIXER2 0x35
|
||||
#define WM8990_SPEAKER_MIXER 0x36
|
||||
#define WM8990_ADDITIONAL_CONTROL 0x37
|
||||
#define WM8990_ANTIPOP1 0x38
|
||||
#define WM8990_ANTIPOP2 0x39
|
||||
#define WM8990_MICBIAS 0x3A
|
||||
#define WM8990_PLL1 0x3C
|
||||
#define WM8990_PLL2 0x3D
|
||||
#define WM8990_PLL3 0x3E
|
||||
#define WM8990_INTDRIVBITS 0x3F
|
||||
|
||||
#define WM8990_REGISTER_COUNT 60
|
||||
#define WM8990_MAX_REGISTER 0x3F
|
||||
|
||||
/*
|
||||
* Field Definitions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* R0 (0x00) - Reset
|
||||
*/
|
||||
#define WM8990_SW_RESET_CHIP_ID_MASK 0xFFFF /* SW_RESET_CHIP_ID - [15:0] */
|
||||
|
||||
/*
|
||||
* R1 (0x01) - Power Management (1)
|
||||
*/
|
||||
#define WM8990_SPK_ENA 0x1000 /* SPK_ENA */
|
||||
#define WM8990_SPK_ENA_BIT 12
|
||||
#define WM8990_OUT3_ENA 0x0800 /* OUT3_ENA */
|
||||
#define WM8990_OUT3_ENA_BIT 11
|
||||
#define WM8990_OUT4_ENA 0x0400 /* OUT4_ENA */
|
||||
#define WM8990_OUT4_ENA_BIT 10
|
||||
#define WM8990_LOUT_ENA 0x0200 /* LOUT_ENA */
|
||||
#define WM8990_LOUT_ENA_BIT 9
|
||||
#define WM8990_ROUT_ENA 0x0100 /* ROUT_ENA */
|
||||
#define WM8990_ROUT_ENA_BIT 8
|
||||
#define WM8990_MICBIAS_ENA 0x0010 /* MICBIAS_ENA */
|
||||
#define WM8990_MICBIAS_ENA_BIT 4
|
||||
#define WM8990_VMID_MODE_MASK 0x0006 /* VMID_MODE - [2:1] */
|
||||
#define WM8990_VREF_ENA 0x0001 /* VREF_ENA */
|
||||
#define WM8990_VREF_ENA_BIT 0
|
||||
|
||||
/*
|
||||
* R2 (0x02) - Power Management (2)
|
||||
*/
|
||||
#define WM8990_PLL_ENA 0x8000 /* PLL_ENA */
|
||||
#define WM8990_PLL_ENA_BIT 15
|
||||
#define WM8990_TSHUT_ENA 0x4000 /* TSHUT_ENA */
|
||||
#define WM8990_TSHUT_ENA_BIT 14
|
||||
#define WM8990_TSHUT_OPDIS 0x2000 /* TSHUT_OPDIS */
|
||||
#define WM8990_TSHUT_OPDIS_BIT 13
|
||||
#define WM8990_OPCLK_ENA 0x0800 /* OPCLK_ENA */
|
||||
#define WM8990_OPCLK_ENA_BIT 11
|
||||
#define WM8990_AINL_ENA 0x0200 /* AINL_ENA */
|
||||
#define WM8990_AINL_ENA_BIT 9
|
||||
#define WM8990_AINR_ENA 0x0100 /* AINR_ENA */
|
||||
#define WM8990_AINR_ENA_BIT 8
|
||||
#define WM8990_LIN34_ENA 0x0080 /* LIN34_ENA */
|
||||
#define WM8990_LIN34_ENA_BIT 7
|
||||
#define WM8990_LIN12_ENA 0x0040 /* LIN12_ENA */
|
||||
#define WM8990_LIN12_ENA_BIT 6
|
||||
#define WM8990_RIN34_ENA 0x0020 /* RIN34_ENA */
|
||||
#define WM8990_RIN34_ENA_BIT 5
|
||||
#define WM8990_RIN12_ENA 0x0010 /* RIN12_ENA */
|
||||
#define WM8990_RIN12_ENA_BIT 4
|
||||
#define WM8990_ADCL_ENA 0x0002 /* ADCL_ENA */
|
||||
#define WM8990_ADCL_ENA_BIT 1
|
||||
#define WM8990_ADCR_ENA 0x0001 /* ADCR_ENA */
|
||||
#define WM8990_ADCR_ENA_BIT 0
|
||||
|
||||
/*
|
||||
* R3 (0x03) - Power Management (3)
|
||||
*/
|
||||
#define WM8990_LON_ENA 0x2000 /* LON_ENA */
|
||||
#define WM8990_LON_ENA_BIT 13
|
||||
#define WM8990_LOP_ENA 0x1000 /* LOP_ENA */
|
||||
#define WM8990_LOP_ENA_BIT 12
|
||||
#define WM8990_RON_ENA 0x0800 /* RON_ENA */
|
||||
#define WM8990_RON_ENA_BIT 11
|
||||
#define WM8990_ROP_ENA 0x0400 /* ROP_ENA */
|
||||
#define WM8990_ROP_ENA_BIT 10
|
||||
#define WM8990_LOPGA_ENA 0x0080 /* LOPGA_ENA */
|
||||
#define WM8990_LOPGA_ENA_BIT 7
|
||||
#define WM8990_ROPGA_ENA 0x0040 /* ROPGA_ENA */
|
||||
#define WM8990_ROPGA_ENA_BIT 6
|
||||
#define WM8990_LOMIX_ENA 0x0020 /* LOMIX_ENA */
|
||||
#define WM8990_LOMIX_ENA_BIT 5
|
||||
#define WM8990_ROMIX_ENA 0x0010 /* ROMIX_ENA */
|
||||
#define WM8990_ROMIX_ENA_BIT 4
|
||||
#define WM8990_DACL_ENA 0x0002 /* DACL_ENA */
|
||||
#define WM8990_DACL_ENA_BIT 1
|
||||
#define WM8990_DACR_ENA 0x0001 /* DACR_ENA */
|
||||
#define WM8990_DACR_ENA_BIT 0
|
||||
|
||||
/*
|
||||
* R4 (0x04) - Audio Interface (1)
|
||||
*/
|
||||
#define WM8990_AIFADCL_SRC 0x8000 /* AIFADCL_SRC */
|
||||
#define WM8990_AIFADCR_SRC 0x4000 /* AIFADCR_SRC */
|
||||
#define WM8990_AIFADC_TDM 0x2000 /* AIFADC_TDM */
|
||||
#define WM8990_AIFADC_TDM_CHAN 0x1000 /* AIFADC_TDM_CHAN */
|
||||
#define WM8990_AIF_BCLK_INV 0x0100 /* AIF_BCLK_INV */
|
||||
#define WM8990_AIF_LRCLK_INV 0x0080 /* AIF_LRCLK_INV */
|
||||
#define WM8990_AIF_WL_MASK 0x0060 /* AIF_WL - [6:5] */
|
||||
#define WM8990_AIF_WL_16BITS (0 << 5)
|
||||
#define WM8990_AIF_WL_20BITS (1 << 5)
|
||||
#define WM8990_AIF_WL_24BITS (2 << 5)
|
||||
#define WM8990_AIF_WL_32BITS (3 << 5)
|
||||
#define WM8990_AIF_FMT_MASK 0x0018 /* AIF_FMT - [4:3] */
|
||||
#define WM8990_AIF_TMF_RIGHTJ (0 << 3)
|
||||
#define WM8990_AIF_TMF_LEFTJ (1 << 3)
|
||||
#define WM8990_AIF_TMF_I2S (2 << 3)
|
||||
#define WM8990_AIF_TMF_DSP (3 << 3)
|
||||
|
||||
/*
|
||||
* R5 (0x05) - Audio Interface (2)
|
||||
*/
|
||||
#define WM8990_DACL_SRC 0x8000 /* DACL_SRC */
|
||||
#define WM8990_DACR_SRC 0x4000 /* DACR_SRC */
|
||||
#define WM8990_AIFDAC_TDM 0x2000 /* AIFDAC_TDM */
|
||||
#define WM8990_AIFDAC_TDM_CHAN 0x1000 /* AIFDAC_TDM_CHAN */
|
||||
#define WM8990_DAC_BOOST_MASK 0x0C00 /* DAC_BOOST - [11:10] */
|
||||
#define WM8990_DAC_COMP 0x0010 /* DAC_COMP */
|
||||
#define WM8990_DAC_COMPMODE 0x0008 /* DAC_COMPMODE */
|
||||
#define WM8990_ADC_COMP 0x0004 /* ADC_COMP */
|
||||
#define WM8990_ADC_COMPMODE 0x0002 /* ADC_COMPMODE */
|
||||
#define WM8990_LOOPBACK 0x0001 /* LOOPBACK */
|
||||
|
||||
/*
|
||||
* R6 (0x06) - Clocking (1)
|
||||
*/
|
||||
#define WM8990_TOCLK_RATE 0x8000 /* TOCLK_RATE */
|
||||
#define WM8990_TOCLK_ENA 0x4000 /* TOCLK_ENA */
|
||||
#define WM8990_OPCLKDIV_MASK 0x1E00 /* OPCLKDIV - [12:9] */
|
||||
#define WM8990_DCLKDIV_MASK 0x01C0 /* DCLKDIV - [8:6] */
|
||||
#define WM8990_BCLK_DIV_MASK 0x001E /* BCLK_DIV - [4:1] */
|
||||
#define WM8990_BCLK_DIV_1 (0x0 << 1)
|
||||
#define WM8990_BCLK_DIV_1_5 (0x1 << 1)
|
||||
#define WM8990_BCLK_DIV_2 (0x2 << 1)
|
||||
#define WM8990_BCLK_DIV_3 (0x3 << 1)
|
||||
#define WM8990_BCLK_DIV_4 (0x4 << 1)
|
||||
#define WM8990_BCLK_DIV_5_5 (0x5 << 1)
|
||||
#define WM8990_BCLK_DIV_6 (0x6 << 1)
|
||||
#define WM8990_BCLK_DIV_8 (0x7 << 1)
|
||||
#define WM8990_BCLK_DIV_11 (0x8 << 1)
|
||||
#define WM8990_BCLK_DIV_12 (0x9 << 1)
|
||||
#define WM8990_BCLK_DIV_16 (0xA << 1)
|
||||
#define WM8990_BCLK_DIV_22 (0xB << 1)
|
||||
#define WM8990_BCLK_DIV_24 (0xC << 1)
|
||||
#define WM8990_BCLK_DIV_32 (0xD << 1)
|
||||
#define WM8990_BCLK_DIV_44 (0xE << 1)
|
||||
#define WM8990_BCLK_DIV_48 (0xF << 1)
|
||||
|
||||
/*
|
||||
* R7 (0x07) - Clocking (2)
|
||||
*/
|
||||
#define WM8990_MCLK_SRC 0x8000 /* MCLK_SRC */
|
||||
#define WM8990_SYSCLK_SRC 0x4000 /* SYSCLK_SRC */
|
||||
#define WM8990_CLK_FORCE 0x2000 /* CLK_FORCE */
|
||||
#define WM8990_MCLK_DIV_MASK 0x1800 /* MCLK_DIV - [12:11] */
|
||||
#define WM8990_MCLK_DIV_1 ( 0 << 11)
|
||||
#define WM8990_MCLK_DIV_2 ( 2 << 11)
|
||||
#define WM8990_MCLK_INV 0x0400 /* MCLK_INV */
|
||||
#define WM8990_ADC_CLKDIV_MASK 0x00E0 /* ADC_CLKDIV - [7:5] */
|
||||
#define WM8990_ADC_CLKDIV_1 ( 0 << 5)
|
||||
#define WM8990_ADC_CLKDIV_1_5 ( 1 << 5)
|
||||
#define WM8990_ADC_CLKDIV_2 ( 2 << 5)
|
||||
#define WM8990_ADC_CLKDIV_3 ( 3 << 5)
|
||||
#define WM8990_ADC_CLKDIV_4 ( 4 << 5)
|
||||
#define WM8990_ADC_CLKDIV_5_5 ( 5 << 5)
|
||||
#define WM8990_ADC_CLKDIV_6 ( 6 << 5)
|
||||
#define WM8990_DAC_CLKDIV_MASK 0x001C /* DAC_CLKDIV - [4:2] */
|
||||
#define WM8990_DAC_CLKDIV_1 ( 0 << 2)
|
||||
#define WM8990_DAC_CLKDIV_1_5 ( 1 << 2)
|
||||
#define WM8990_DAC_CLKDIV_2 ( 2 << 2)
|
||||
#define WM8990_DAC_CLKDIV_3 ( 3 << 2)
|
||||
#define WM8990_DAC_CLKDIV_4 ( 4 << 2)
|
||||
#define WM8990_DAC_CLKDIV_5_5 ( 5 << 2)
|
||||
#define WM8990_DAC_CLKDIV_6 ( 6 << 2)
|
||||
|
||||
/*
|
||||
* R8 (0x08) - Audio Interface (3)
|
||||
*/
|
||||
#define WM8990_AIF_MSTR1 0x8000 /* AIF_MSTR1 */
|
||||
#define WM8990_AIF_MSTR2 0x4000 /* AIF_MSTR2 */
|
||||
#define WM8990_AIF_SEL 0x2000 /* AIF_SEL */
|
||||
#define WM8990_ADCLRC_DIR 0x0800 /* ADCLRC_DIR */
|
||||
#define WM8990_ADCLRC_RATE_MASK 0x07FF /* ADCLRC_RATE - [10:0] */
|
||||
|
||||
/*
|
||||
* R9 (0x09) - Audio Interface (4)
|
||||
*/
|
||||
#define WM8990_ALRCGPIO1 0x8000 /* ALRCGPIO1 */
|
||||
#define WM8990_ALRCBGPIO6 0x4000 /* ALRCBGPIO6 */
|
||||
#define WM8990_AIF_TRIS 0x2000 /* AIF_TRIS */
|
||||
#define WM8990_DACLRC_DIR 0x0800 /* DACLRC_DIR */
|
||||
#define WM8990_DACLRC_RATE_MASK 0x07FF /* DACLRC_RATE - [10:0] */
|
||||
|
||||
/*
|
||||
* R10 (0x0A) - DAC CTRL
|
||||
*/
|
||||
#define WM8990_AIF_LRCLKRATE 0x0400 /* AIF_LRCLKRATE */
|
||||
#define WM8990_DAC_MONO 0x0200 /* DAC_MONO */
|
||||
#define WM8990_DAC_SB_FILT 0x0100 /* DAC_SB_FILT */
|
||||
#define WM8990_DAC_MUTERATE 0x0080 /* DAC_MUTERATE */
|
||||
#define WM8990_DAC_MUTEMODE 0x0040 /* DAC_MUTEMODE */
|
||||
#define WM8990_DEEMP_MASK 0x0030 /* DEEMP - [5:4] */
|
||||
#define WM8990_DAC_MUTE 0x0004 /* DAC_MUTE */
|
||||
#define WM8990_DACL_DATINV 0x0002 /* DACL_DATINV */
|
||||
#define WM8990_DACR_DATINV 0x0001 /* DACR_DATINV */
|
||||
|
||||
/*
|
||||
* R11 (0x0B) - Left DAC Digital Volume
|
||||
*/
|
||||
#define WM8990_DAC_VU 0x0100 /* DAC_VU */
|
||||
#define WM8990_DACL_VOL_MASK 0x00FF /* DACL_VOL - [7:0] */
|
||||
#define WM8990_DACL_VOL_SHIFT 0
|
||||
/*
|
||||
* R12 (0x0C) - Right DAC Digital Volume
|
||||
*/
|
||||
#define WM8990_DAC_VU 0x0100 /* DAC_VU */
|
||||
#define WM8990_DACR_VOL_MASK 0x00FF /* DACR_VOL - [7:0] */
|
||||
#define WM8990_DACR_VOL_SHIFT 0
|
||||
/*
|
||||
* R13 (0x0D) - Digital Side Tone
|
||||
*/
|
||||
#define WM8990_ADCL_DAC_SVOL_MASK 0x0F /* ADCL_DAC_SVOL - [12:9] */
|
||||
#define WM8990_ADCL_DAC_SVOL_SHIFT 9
|
||||
#define WM8990_ADCR_DAC_SVOL_MASK 0x0F /* ADCR_DAC_SVOL - [8:5] */
|
||||
#define WM8990_ADCR_DAC_SVOL_SHIFT 5
|
||||
#define WM8990_ADC_TO_DACL_MASK 0x03 /* ADC_TO_DACL - [3:2] */
|
||||
#define WM8990_ADC_TO_DACL_SHIFT 2
|
||||
#define WM8990_ADC_TO_DACR_MASK 0x03 /* ADC_TO_DACR - [1:0] */
|
||||
#define WM8990_ADC_TO_DACR_SHIFT 0
|
||||
|
||||
/*
|
||||
* R14 (0x0E) - ADC CTRL
|
||||
*/
|
||||
#define WM8990_ADC_HPF_ENA 0x0100 /* ADC_HPF_ENA */
|
||||
#define WM8990_ADC_HPF_ENA_BIT 8
|
||||
#define WM8990_ADC_HPF_CUT_MASK 0x03 /* ADC_HPF_CUT - [6:5] */
|
||||
#define WM8990_ADC_HPF_CUT_SHIFT 5
|
||||
#define WM8990_ADCL_DATINV 0x0002 /* ADCL_DATINV */
|
||||
#define WM8990_ADCL_DATINV_BIT 1
|
||||
#define WM8990_ADCR_DATINV 0x0001 /* ADCR_DATINV */
|
||||
#define WM8990_ADCR_DATINV_BIT 0
|
||||
|
||||
/*
|
||||
* R15 (0x0F) - Left ADC Digital Volume
|
||||
*/
|
||||
#define WM8990_ADC_VU 0x0100 /* ADC_VU */
|
||||
#define WM8990_ADCL_VOL_MASK 0x00FF /* ADCL_VOL - [7:0] */
|
||||
#define WM8990_ADCL_VOL_SHIFT 0
|
||||
|
||||
/*
|
||||
* R16 (0x10) - Right ADC Digital Volume
|
||||
*/
|
||||
#define WM8990_ADC_VU 0x0100 /* ADC_VU */
|
||||
#define WM8990_ADCR_VOL_MASK 0x00FF /* ADCR_VOL - [7:0] */
|
||||
#define WM8990_ADCR_VOL_SHIFT 0
|
||||
|
||||
/*
|
||||
* R18 (0x12) - GPIO CTRL 1
|
||||
*/
|
||||
#define WM8990_IRQ 0x1000 /* IRQ */
|
||||
#define WM8990_TEMPOK 0x0800 /* TEMPOK */
|
||||
#define WM8990_MICSHRT 0x0400 /* MICSHRT */
|
||||
#define WM8990_MICDET 0x0200 /* MICDET */
|
||||
#define WM8990_PLL_LCK 0x0100 /* PLL_LCK */
|
||||
#define WM8990_GPI8_STATUS 0x0080 /* GPI8_STATUS */
|
||||
#define WM8990_GPI7_STATUS 0x0040 /* GPI7_STATUS */
|
||||
#define WM8990_GPIO6_STATUS 0x0020 /* GPIO6_STATUS */
|
||||
#define WM8990_GPIO5_STATUS 0x0010 /* GPIO5_STATUS */
|
||||
#define WM8990_GPIO4_STATUS 0x0008 /* GPIO4_STATUS */
|
||||
#define WM8990_GPIO3_STATUS 0x0004 /* GPIO3_STATUS */
|
||||
#define WM8990_GPIO2_STATUS 0x0002 /* GPIO2_STATUS */
|
||||
#define WM8990_GPIO1_STATUS 0x0001 /* GPIO1_STATUS */
|
||||
|
||||
/*
|
||||
* R19 (0x13) - GPIO1 & GPIO2
|
||||
*/
|
||||
#define WM8990_GPIO2_DEB_ENA 0x8000 /* GPIO2_DEB_ENA */
|
||||
#define WM8990_GPIO2_IRQ_ENA 0x4000 /* GPIO2_IRQ_ENA */
|
||||
#define WM8990_GPIO2_PU 0x2000 /* GPIO2_PU */
|
||||
#define WM8990_GPIO2_PD 0x1000 /* GPIO2_PD */
|
||||
#define WM8990_GPIO2_SEL_MASK 0x0F00 /* GPIO2_SEL - [11:8] */
|
||||
#define WM8990_GPIO1_DEB_ENA 0x0080 /* GPIO1_DEB_ENA */
|
||||
#define WM8990_GPIO1_IRQ_ENA 0x0040 /* GPIO1_IRQ_ENA */
|
||||
#define WM8990_GPIO1_PU 0x0020 /* GPIO1_PU */
|
||||
#define WM8990_GPIO1_PD 0x0010 /* GPIO1_PD */
|
||||
#define WM8990_GPIO1_SEL_MASK 0x000F /* GPIO1_SEL - [3:0] */
|
||||
|
||||
/*
|
||||
* R20 (0x14) - GPIO3 & GPIO4
|
||||
*/
|
||||
#define WM8990_GPIO4_DEB_ENA 0x8000 /* GPIO4_DEB_ENA */
|
||||
#define WM8990_GPIO4_IRQ_ENA 0x4000 /* GPIO4_IRQ_ENA */
|
||||
#define WM8990_GPIO4_PU 0x2000 /* GPIO4_PU */
|
||||
#define WM8990_GPIO4_PD 0x1000 /* GPIO4_PD */
|
||||
#define WM8990_GPIO4_SEL_MASK 0x0F00 /* GPIO4_SEL - [11:8] */
|
||||
#define WM8990_GPIO3_DEB_ENA 0x0080 /* GPIO3_DEB_ENA */
|
||||
#define WM8990_GPIO3_IRQ_ENA 0x0040 /* GPIO3_IRQ_ENA */
|
||||
#define WM8990_GPIO3_PU 0x0020 /* GPIO3_PU */
|
||||
#define WM8990_GPIO3_PD 0x0010 /* GPIO3_PD */
|
||||
#define WM8990_GPIO3_SEL_MASK 0x000F /* GPIO3_SEL - [3:0] */
|
||||
|
||||
/*
|
||||
* R21 (0x15) - GPIO5 & GPIO6
|
||||
*/
|
||||
#define WM8990_GPIO6_DEB_ENA 0x8000 /* GPIO6_DEB_ENA */
|
||||
#define WM8990_GPIO6_IRQ_ENA 0x4000 /* GPIO6_IRQ_ENA */
|
||||
#define WM8990_GPIO6_PU 0x2000 /* GPIO6_PU */
|
||||
#define WM8990_GPIO6_PD 0x1000 /* GPIO6_PD */
|
||||
#define WM8990_GPIO6_SEL_MASK 0x0F00 /* GPIO6_SEL - [11:8] */
|
||||
#define WM8990_GPIO5_DEB_ENA 0x0080 /* GPIO5_DEB_ENA */
|
||||
#define WM8990_GPIO5_IRQ_ENA 0x0040 /* GPIO5_IRQ_ENA */
|
||||
#define WM8990_GPIO5_PU 0x0020 /* GPIO5_PU */
|
||||
#define WM8990_GPIO5_PD 0x0010 /* GPIO5_PD */
|
||||
#define WM8990_GPIO5_SEL_MASK 0x000F /* GPIO5_SEL - [3:0] */
|
||||
|
||||
/*
|
||||
* R22 (0x16) - GPIOCTRL 2
|
||||
*/
|
||||
#define WM8990_RD_3W_ENA 0x8000 /* RD_3W_ENA */
|
||||
#define WM8990_MODE_3W4W 0x4000 /* MODE_3W4W */
|
||||
#define WM8990_TEMPOK_IRQ_ENA 0x0800 /* TEMPOK_IRQ_ENA */
|
||||
#define WM8990_MICSHRT_IRQ_ENA 0x0400 /* MICSHRT_IRQ_ENA */
|
||||
#define WM8990_MICDET_IRQ_ENA 0x0200 /* MICDET_IRQ_ENA */
|
||||
#define WM8990_PLL_LCK_IRQ_ENA 0x0100 /* PLL_LCK_IRQ_ENA */
|
||||
#define WM8990_GPI8_DEB_ENA 0x0080 /* GPI8_DEB_ENA */
|
||||
#define WM8990_GPI8_IRQ_ENA 0x0040 /* GPI8_IRQ_ENA */
|
||||
#define WM8990_GPI8_ENA 0x0010 /* GPI8_ENA */
|
||||
#define WM8990_GPI7_DEB_ENA 0x0008 /* GPI7_DEB_ENA */
|
||||
#define WM8990_GPI7_IRQ_ENA 0x0004 /* GPI7_IRQ_ENA */
|
||||
#define WM8990_GPI7_ENA 0x0001 /* GPI7_ENA */
|
||||
|
||||
/*
|
||||
* R23 (0x17) - GPIO_POL
|
||||
*/
|
||||
#define WM8990_IRQ_INV 0x1000 /* IRQ_INV */
|
||||
#define WM8990_TEMPOK_POL 0x0800 /* TEMPOK_POL */
|
||||
#define WM8990_MICSHRT_POL 0x0400 /* MICSHRT_POL */
|
||||
#define WM8990_MICDET_POL 0x0200 /* MICDET_POL */
|
||||
#define WM8990_PLL_LCK_POL 0x0100 /* PLL_LCK_POL */
|
||||
#define WM8990_GPI8_POL 0x0080 /* GPI8_POL */
|
||||
#define WM8990_GPI7_POL 0x0040 /* GPI7_POL */
|
||||
#define WM8990_GPIO6_POL 0x0020 /* GPIO6_POL */
|
||||
#define WM8990_GPIO5_POL 0x0010 /* GPIO5_POL */
|
||||
#define WM8990_GPIO4_POL 0x0008 /* GPIO4_POL */
|
||||
#define WM8990_GPIO3_POL 0x0004 /* GPIO3_POL */
|
||||
#define WM8990_GPIO2_POL 0x0002 /* GPIO2_POL */
|
||||
#define WM8990_GPIO1_POL 0x0001 /* GPIO1_POL */
|
||||
|
||||
/*
|
||||
* R24 (0x18) - Left Line Input 1&2 Volume
|
||||
*/
|
||||
#define WM8990_IPVU 0x0100 /* IPVU */
|
||||
#define WM8990_LI12MUTE 0x0080 /* LI12MUTE */
|
||||
#define WM8990_LI12MUTE_BIT 7
|
||||
#define WM8990_LI12ZC 0x0040 /* LI12ZC */
|
||||
#define WM8990_LI12ZC_BIT 6
|
||||
#define WM8990_LIN12VOL_MASK 0x001F /* LIN12VOL - [4:0] */
|
||||
#define WM8990_LIN12VOL_SHIFT 0
|
||||
/*
|
||||
* R25 (0x19) - Left Line Input 3&4 Volume
|
||||
*/
|
||||
#define WM8990_IPVU 0x0100 /* IPVU */
|
||||
#define WM8990_LI34MUTE 0x0080 /* LI34MUTE */
|
||||
#define WM8990_LI34MUTE_BIT 7
|
||||
#define WM8990_LI34ZC 0x0040 /* LI34ZC */
|
||||
#define WM8990_LI34ZC_BIT 6
|
||||
#define WM8990_LIN34VOL_MASK 0x001F /* LIN34VOL - [4:0] */
|
||||
#define WM8990_LIN34VOL_SHIFT 0
|
||||
|
||||
/*
|
||||
* R26 (0x1A) - Right Line Input 1&2 Volume
|
||||
*/
|
||||
#define WM8990_IPVU 0x0100 /* IPVU */
|
||||
#define WM8990_RI12MUTE 0x0080 /* RI12MUTE */
|
||||
#define WM8990_RI12MUTE_BIT 7
|
||||
#define WM8990_RI12ZC 0x0040 /* RI12ZC */
|
||||
#define WM8990_RI12ZC_BIT 6
|
||||
#define WM8990_RIN12VOL_MASK 0x001F /* RIN12VOL - [4:0] */
|
||||
#define WM8990_RIN12VOL_SHIFT 0
|
||||
|
||||
/*
|
||||
* R27 (0x1B) - Right Line Input 3&4 Volume
|
||||
*/
|
||||
#define WM8990_IPVU 0x0100 /* IPVU */
|
||||
#define WM8990_RI34MUTE 0x0080 /* RI34MUTE */
|
||||
#define WM8990_RI34MUTE_BIT 7
|
||||
#define WM8990_RI34ZC 0x0040 /* RI34ZC */
|
||||
#define WM8990_RI34ZC_BIT 6
|
||||
#define WM8990_RIN34VOL_MASK 0x001F /* RIN34VOL - [4:0] */
|
||||
#define WM8990_RIN34VOL_SHIFT 0
|
||||
|
||||
/*
|
||||
* R28 (0x1C) - Left Output Volume
|
||||
*/
|
||||
#define WM8990_OPVU 0x0100 /* OPVU */
|
||||
#define WM8990_LOZC 0x0080 /* LOZC */
|
||||
#define WM8990_LOZC_BIT 7
|
||||
#define WM8990_LOUTVOL_MASK 0x007F /* LOUTVOL - [6:0] */
|
||||
#define WM8990_LOUTVOL_SHIFT 0
|
||||
/*
|
||||
* R29 (0x1D) - Right Output Volume
|
||||
*/
|
||||
#define WM8990_OPVU 0x0100 /* OPVU */
|
||||
#define WM8990_ROZC 0x0080 /* ROZC */
|
||||
#define WM8990_ROZC_BIT 7
|
||||
#define WM8990_ROUTVOL_MASK 0x007F /* ROUTVOL - [6:0] */
|
||||
#define WM8990_ROUTVOL_SHIFT 0
|
||||
/*
|
||||
* R30 (0x1E) - Line Outputs Volume
|
||||
*/
|
||||
#define WM8990_LONMUTE 0x0040 /* LONMUTE */
|
||||
#define WM8990_LONMUTE_BIT 6
|
||||
#define WM8990_LOPMUTE 0x0020 /* LOPMUTE */
|
||||
#define WM8990_LOPMUTE_BIT 5
|
||||
#define WM8990_LOATTN 0x0010 /* LOATTN */
|
||||
#define WM8990_LOATTN_BIT 4
|
||||
#define WM8990_RONMUTE 0x0004 /* RONMUTE */
|
||||
#define WM8990_RONMUTE_BIT 2
|
||||
#define WM8990_ROPMUTE 0x0002 /* ROPMUTE */
|
||||
#define WM8990_ROPMUTE_BIT 1
|
||||
#define WM8990_ROATTN 0x0001 /* ROATTN */
|
||||
#define WM8990_ROATTN_BIT 0
|
||||
|
||||
/*
|
||||
* R31 (0x1F) - Out3/4 Volume
|
||||
*/
|
||||
#define WM8990_OUT3MUTE 0x0020 /* OUT3MUTE */
|
||||
#define WM8990_OUT3MUTE_BIT 5
|
||||
#define WM8990_OUT3ATTN 0x0010 /* OUT3ATTN */
|
||||
#define WM8990_OUT3ATTN_BIT 4
|
||||
#define WM8990_OUT4MUTE 0x0002 /* OUT4MUTE */
|
||||
#define WM8990_OUT4MUTE_BIT 1
|
||||
#define WM8990_OUT4ATTN 0x0001 /* OUT4ATTN */
|
||||
#define WM8990_OUT4ATTN_BIT 0
|
||||
|
||||
/*
|
||||
* R32 (0x20) - Left OPGA Volume
|
||||
*/
|
||||
#define WM8990_OPVU 0x0100 /* OPVU */
|
||||
#define WM8990_LOPGAZC 0x0080 /* LOPGAZC */
|
||||
#define WM8990_LOPGAZC_BIT 7
|
||||
#define WM8990_LOPGAVOL_MASK 0x007F /* LOPGAVOL - [6:0] */
|
||||
#define WM8990_LOPGAVOL_SHIFT 0
|
||||
|
||||
/*
|
||||
* R33 (0x21) - Right OPGA Volume
|
||||
*/
|
||||
#define WM8990_OPVU 0x0100 /* OPVU */
|
||||
#define WM8990_ROPGAZC 0x0080 /* ROPGAZC */
|
||||
#define WM8990_ROPGAZC_BIT 7
|
||||
#define WM8990_ROPGAVOL_MASK 0x007F /* ROPGAVOL - [6:0] */
|
||||
#define WM8990_ROPGAVOL_SHIFT 0
|
||||
/*
|
||||
* R34 (0x22) - Speaker Volume
|
||||
*/
|
||||
#define WM8990_SPKVOL_MASK 0x0003 /* SPKVOL - [1:0] */
|
||||
#define WM8990_SPKVOL_SHIFT 0
|
||||
|
||||
/*
|
||||
* R35 (0x23) - ClassD1
|
||||
*/
|
||||
#define WM8990_CDMODE 0x0100 /* CDMODE */
|
||||
#define WM8990_CDMODE_BIT 8
|
||||
|
||||
/*
|
||||
* R37 (0x25) - ClassD3
|
||||
*/
|
||||
#define WM8990_DCGAIN_MASK 0x0007 /* DCGAIN - [5:3] */
|
||||
#define WM8990_DCGAIN_SHIFT 3
|
||||
#define WM8990_ACGAIN_MASK 0x0007 /* ACGAIN - [2:0] */
|
||||
#define WM8990_ACGAIN_SHIFT 0
|
||||
/*
|
||||
* R39 (0x27) - Input Mixer1
|
||||
*/
|
||||
#define WM8990_AINLMODE_MASK 0x000C /* AINLMODE - [3:2] */
|
||||
#define WM8990_AINLMODE_SHIFT 2
|
||||
#define WM8990_AINRMODE_MASK 0x0003 /* AINRMODE - [1:0] */
|
||||
#define WM8990_AINRMODE_SHIFT 0
|
||||
|
||||
/*
|
||||
* R40 (0x28) - Input Mixer2
|
||||
*/
|
||||
#define WM8990_LMP4 0x0080 /* LMP4 */
|
||||
#define WM8990_LMP4_BIT 7 /* LMP4 */
|
||||
#define WM8990_LMN3 0x0040 /* LMN3 */
|
||||
#define WM8990_LMN3_BIT 6 /* LMN3 */
|
||||
#define WM8990_LMP2 0x0020 /* LMP2 */
|
||||
#define WM8990_LMP2_BIT 5 /* LMP2 */
|
||||
#define WM8990_LMN1 0x0010 /* LMN1 */
|
||||
#define WM8990_LMN1_BIT 4 /* LMN1 */
|
||||
#define WM8990_RMP4 0x0008 /* RMP4 */
|
||||
#define WM8990_RMP4_BIT 3 /* RMP4 */
|
||||
#define WM8990_RMN3 0x0004 /* RMN3 */
|
||||
#define WM8990_RMN3_BIT 2 /* RMN3 */
|
||||
#define WM8990_RMP2 0x0002 /* RMP2 */
|
||||
#define WM8990_RMP2_BIT 1 /* RMP2 */
|
||||
#define WM8990_RMN1 0x0001 /* RMN1 */
|
||||
#define WM8990_RMN1_BIT 0 /* RMN1 */
|
||||
|
||||
/*
|
||||
* R41 (0x29) - Input Mixer3
|
||||
*/
|
||||
#define WM8990_L34MNB 0x0100 /* L34MNB */
|
||||
#define WM8990_L34MNB_BIT 8
|
||||
#define WM8990_L34MNBST 0x0080 /* L34MNBST */
|
||||
#define WM8990_L34MNBST_BIT 7
|
||||
#define WM8990_L12MNB 0x0020 /* L12MNB */
|
||||
#define WM8990_L12MNB_BIT 5
|
||||
#define WM8990_L12MNBST 0x0010 /* L12MNBST */
|
||||
#define WM8990_L12MNBST_BIT 4
|
||||
#define WM8990_LDBVOL_MASK 0x0007 /* LDBVOL - [2:0] */
|
||||
#define WM8990_LDBVOL_SHIFT 0
|
||||
|
||||
/*
|
||||
* R42 (0x2A) - Input Mixer4
|
||||
*/
|
||||
#define WM8990_R34MNB 0x0100 /* R34MNB */
|
||||
#define WM8990_R34MNB_BIT 8
|
||||
#define WM8990_R34MNBST 0x0080 /* R34MNBST */
|
||||
#define WM8990_R34MNBST_BIT 7
|
||||
#define WM8990_R12MNB 0x0020 /* R12MNB */
|
||||
#define WM8990_R12MNB_BIT 5
|
||||
#define WM8990_R12MNBST 0x0010 /* R12MNBST */
|
||||
#define WM8990_R12MNBST_BIT 4
|
||||
#define WM8990_RDBVOL_MASK 0x0007 /* RDBVOL - [2:0] */
|
||||
#define WM8990_RDBVOL_SHIFT 0
|
||||
|
||||
/*
|
||||
* R43 (0x2B) - Input Mixer5
|
||||
*/
|
||||
#define WM8990_LI2BVOL_MASK 0x07 /* LI2BVOL - [8:6] */
|
||||
#define WM8990_LI2BVOL_SHIFT 6
|
||||
#define WM8990_LR4BVOL_MASK 0x07 /* LR4BVOL - [5:3] */
|
||||
#define WM8990_LR4BVOL_SHIFT 3
|
||||
#define WM8990_LL4BVOL_MASK 0x07 /* LL4BVOL - [2:0] */
|
||||
#define WM8990_LL4BVOL_SHIFT 0
|
||||
|
||||
/*
|
||||
* R44 (0x2C) - Input Mixer6
|
||||
*/
|
||||
#define WM8990_RI2BVOL_MASK 0x07 /* RI2BVOL - [8:6] */
|
||||
#define WM8990_RI2BVOL_SHIFT 6
|
||||
#define WM8990_RL4BVOL_MASK 0x07 /* RL4BVOL - [5:3] */
|
||||
#define WM8990_RL4BVOL_SHIFT 3
|
||||
#define WM8990_RR4BVOL_MASK 0x07 /* RR4BVOL - [2:0] */
|
||||
#define WM8990_RR4BVOL_SHIFT 0
|
||||
|
||||
/*
|
||||
* R45 (0x2D) - Output Mixer1
|
||||
*/
|
||||
#define WM8990_LRBLO 0x0080 /* LRBLO */
|
||||
#define WM8990_LRBLO_BIT 7
|
||||
#define WM8990_LLBLO 0x0040 /* LLBLO */
|
||||
#define WM8990_LLBLO_BIT 6
|
||||
#define WM8990_LRI3LO 0x0020 /* LRI3LO */
|
||||
#define WM8990_LRI3LO_BIT 5
|
||||
#define WM8990_LLI3LO 0x0010 /* LLI3LO */
|
||||
#define WM8990_LLI3LO_BIT 4
|
||||
#define WM8990_LR12LO 0x0008 /* LR12LO */
|
||||
#define WM8990_LR12LO_BIT 3
|
||||
#define WM8990_LL12LO 0x0004 /* LL12LO */
|
||||
#define WM8990_LL12LO_BIT 2
|
||||
#define WM8990_LDLO 0x0001 /* LDLO */
|
||||
#define WM8990_LDLO_BIT 0
|
||||
|
||||
/*
|
||||
* R46 (0x2E) - Output Mixer2
|
||||
*/
|
||||
#define WM8990_RLBRO 0x0080 /* RLBRO */
|
||||
#define WM8990_RLBRO_BIT 7
|
||||
#define WM8990_RRBRO 0x0040 /* RRBRO */
|
||||
#define WM8990_RRBRO_BIT 6
|
||||
#define WM8990_RLI3RO 0x0020 /* RLI3RO */
|
||||
#define WM8990_RLI3RO_BIT 5
|
||||
#define WM8990_RRI3RO 0x0010 /* RRI3RO */
|
||||
#define WM8990_RRI3RO_BIT 4
|
||||
#define WM8990_RL12RO 0x0008 /* RL12RO */
|
||||
#define WM8990_RL12RO_BIT 3
|
||||
#define WM8990_RR12RO 0x0004 /* RR12RO */
|
||||
#define WM8990_RR12RO_BIT 2
|
||||
#define WM8990_RDRO 0x0001 /* RDRO */
|
||||
#define WM8990_RDRO_BIT 0
|
||||
|
||||
/*
|
||||
* R47 (0x2F) - Output Mixer3
|
||||
*/
|
||||
#define WM8990_LLI3LOVOL_MASK 0x07 /* LLI3LOVOL - [8:6] */
|
||||
#define WM8990_LLI3LOVOL_SHIFT 6
|
||||
#define WM8990_LR12LOVOL_MASK 0x07 /* LR12LOVOL - [5:3] */
|
||||
#define WM8990_LR12LOVOL_SHIFT 3
|
||||
#define WM8990_LL12LOVOL_MASK 0x07 /* LL12LOVOL - [2:0] */
|
||||
#define WM8990_LL12LOVOL_SHIFT 0
|
||||
|
||||
/*
|
||||
* R48 (0x30) - Output Mixer4
|
||||
*/
|
||||
#define WM8990_RRI3ROVOL_MASK 0x07 /* RRI3ROVOL - [8:6] */
|
||||
#define WM8990_RRI3ROVOL_SHIFT 6
|
||||
#define WM8990_RL12ROVOL_MASK 0x07 /* RL12ROVOL - [5:3] */
|
||||
#define WM8990_RL12ROVOL_SHIFT 3
|
||||
#define WM8990_RR12ROVOL_MASK 0x07 /* RR12ROVOL - [2:0] */
|
||||
#define WM8990_RR12ROVOL_SHIFT 0
|
||||
|
||||
/*
|
||||
* R49 (0x31) - Output Mixer5
|
||||
*/
|
||||
#define WM8990_LRI3LOVOL_MASK 0x07 /* LRI3LOVOL - [8:6] */
|
||||
#define WM8990_LRI3LOVOL_SHIFT 6
|
||||
#define WM8990_LRBLOVOL_MASK 0x07 /* LRBLOVOL - [5:3] */
|
||||
#define WM8990_LRBLOVOL_SHIFT 3
|
||||
#define WM8990_LLBLOVOL_MASK 0x07 /* LLBLOVOL - [2:0] */
|
||||
#define WM8990_LLBLOVOL_SHIFT 0
|
||||
|
||||
/*
|
||||
* R50 (0x32) - Output Mixer6
|
||||
*/
|
||||
#define WM8990_RLI3ROVOL_MASK 0x07 /* RLI3ROVOL - [8:6] */
|
||||
#define WM8990_RLI3ROVOL_SHIFT 6
|
||||
#define WM8990_RLBROVOL_MASK 0x07 /* RLBROVOL - [5:3] */
|
||||
#define WM8990_RLBROVOL_SHIFT 3
|
||||
#define WM8990_RRBROVOL_MASK 0x07 /* RRBROVOL - [2:0] */
|
||||
#define WM8990_RRBROVOL_SHIFT 0
|
||||
|
||||
/*
|
||||
* R51 (0x33) - Out3/4 Mixer
|
||||
*/
|
||||
#define WM8990_VSEL_MASK 0x0180 /* VSEL - [8:7] */
|
||||
#define WM8990_LI4O3 0x0020 /* LI4O3 */
|
||||
#define WM8990_LI4O3_BIT 5
|
||||
#define WM8990_LPGAO3 0x0010 /* LPGAO3 */
|
||||
#define WM8990_LPGAO3_BIT 4
|
||||
#define WM8990_RI4O4 0x0002 /* RI4O4 */
|
||||
#define WM8990_RI4O4_BIT 1
|
||||
#define WM8990_RPGAO4 0x0001 /* RPGAO4 */
|
||||
#define WM8990_RPGAO4_BIT 0
|
||||
/*
|
||||
* R52 (0x34) - Line Mixer1
|
||||
*/
|
||||
#define WM8990_LLOPGALON 0x0040 /* LLOPGALON */
|
||||
#define WM8990_LLOPGALON_BIT 6
|
||||
#define WM8990_LROPGALON 0x0020 /* LROPGALON */
|
||||
#define WM8990_LROPGALON_BIT 5
|
||||
#define WM8990_LOPLON 0x0010 /* LOPLON */
|
||||
#define WM8990_LOPLON_BIT 4
|
||||
#define WM8990_LR12LOP 0x0004 /* LR12LOP */
|
||||
#define WM8990_LR12LOP_BIT 2
|
||||
#define WM8990_LL12LOP 0x0002 /* LL12LOP */
|
||||
#define WM8990_LL12LOP_BIT 1
|
||||
#define WM8990_LLOPGALOP 0x0001 /* LLOPGALOP */
|
||||
#define WM8990_LLOPGALOP_BIT 0
|
||||
/*
|
||||
* R53 (0x35) - Line Mixer2
|
||||
*/
|
||||
#define WM8990_RROPGARON 0x0040 /* RROPGARON */
|
||||
#define WM8990_RROPGARON_BIT 6
|
||||
#define WM8990_RLOPGARON 0x0020 /* RLOPGARON */
|
||||
#define WM8990_RLOPGARON_BIT 5
|
||||
#define WM8990_ROPRON 0x0010 /* ROPRON */
|
||||
#define WM8990_ROPRON_BIT 4
|
||||
#define WM8990_RL12ROP 0x0004 /* RL12ROP */
|
||||
#define WM8990_RL12ROP_BIT 2
|
||||
#define WM8990_RR12ROP 0x0002 /* RR12ROP */
|
||||
#define WM8990_RR12ROP_BIT 1
|
||||
#define WM8990_RROPGAROP 0x0001 /* RROPGAROP */
|
||||
#define WM8990_RROPGAROP_BIT 0
|
||||
|
||||
/*
|
||||
* R54 (0x36) - Speaker Mixer
|
||||
*/
|
||||
#define WM8990_LB2SPK 0x0080 /* LB2SPK */
|
||||
#define WM8990_LB2SPK_BIT 7
|
||||
#define WM8990_RB2SPK 0x0040 /* RB2SPK */
|
||||
#define WM8990_RB2SPK_BIT 6
|
||||
#define WM8990_LI2SPK 0x0020 /* LI2SPK */
|
||||
#define WM8990_LI2SPK_BIT 5
|
||||
#define WM8990_RI2SPK 0x0010 /* RI2SPK */
|
||||
#define WM8990_RI2SPK_BIT 4
|
||||
#define WM8990_LOPGASPK 0x0008 /* LOPGASPK */
|
||||
#define WM8990_LOPGASPK_BIT 3
|
||||
#define WM8990_ROPGASPK 0x0004 /* ROPGASPK */
|
||||
#define WM8990_ROPGASPK_BIT 2
|
||||
#define WM8990_LDSPK 0x0002 /* LDSPK */
|
||||
#define WM8990_LDSPK_BIT 1
|
||||
#define WM8990_RDSPK 0x0001 /* RDSPK */
|
||||
#define WM8990_RDSPK_BIT 0
|
||||
|
||||
/*
|
||||
* R55 (0x37) - Additional Control
|
||||
*/
|
||||
#define WM8990_VROI 0x0001 /* VROI */
|
||||
|
||||
/*
|
||||
* R56 (0x38) - AntiPOP1
|
||||
*/
|
||||
#define WM8990_DIS_LLINE 0x0020 /* DIS_LLINE */
|
||||
#define WM8990_DIS_RLINE 0x0010 /* DIS_RLINE */
|
||||
#define WM8990_DIS_OUT3 0x0008 /* DIS_OUT3 */
|
||||
#define WM8990_DIS_OUT4 0x0004 /* DIS_OUT4 */
|
||||
#define WM8990_DIS_LOUT 0x0002 /* DIS_LOUT */
|
||||
#define WM8990_DIS_ROUT 0x0001 /* DIS_ROUT */
|
||||
|
||||
/*
|
||||
* R57 (0x39) - AntiPOP2
|
||||
*/
|
||||
#define WM8990_SOFTST 0x0040 /* SOFTST */
|
||||
#define WM8990_BUFIOEN 0x0008 /* BUFIOEN */
|
||||
#define WM8990_BUFDCOPEN 0x0004 /* BUFDCOPEN */
|
||||
#define WM8990_POBCTRL 0x0002 /* POBCTRL */
|
||||
#define WM8990_VMIDTOG 0x0001 /* VMIDTOG */
|
||||
|
||||
/*
|
||||
* R58 (0x3A) - MICBIAS
|
||||
*/
|
||||
#define WM8990_MCDSCTH_MASK 0x00C0 /* MCDSCTH - [7:6] */
|
||||
#define WM8990_MCDTHR_MASK 0x0038 /* MCDTHR - [5:3] */
|
||||
#define WM8990_MCD 0x0004 /* MCD */
|
||||
#define WM8990_MBSEL 0x0001 /* MBSEL */
|
||||
|
||||
/*
|
||||
* R60 (0x3C) - PLL1
|
||||
*/
|
||||
#define WM8990_SDM 0x0080 /* SDM */
|
||||
#define WM8990_PRESCALE 0x0040 /* PRESCALE */
|
||||
#define WM8990_PLLN_MASK 0x000F /* PLLN - [3:0] */
|
||||
|
||||
/*
|
||||
* R61 (0x3D) - PLL2
|
||||
*/
|
||||
#define WM8990_PLLK1_MASK 0x00FF /* PLLK1 - [7:0] */
|
||||
|
||||
/*
|
||||
* R62 (0x3E) - PLL3
|
||||
*/
|
||||
#define WM8990_PLLK2_MASK 0x00FF /* PLLK2 - [7:0] */
|
||||
|
||||
/*
|
||||
* R63 (0x3F) - Internal Driver Bits
|
||||
*/
|
||||
#define WM8990_INMIXL_PWR_BIT 0
|
||||
#define WM8990_AINLMUX_PWR_BIT 1
|
||||
#define WM8990_INMIXR_PWR_BIT 2
|
||||
#define WM8990_AINRMUX_PWR_BIT 3
|
||||
|
||||
/*
|
||||
* Default values.
|
||||
*/
|
||||
#define WM8990_REGISTER_DEFAULTS \
|
||||
{ \
|
||||
/*0x8990,*/ /* R0 - Reset */ \
|
||||
0x0000, /* R1 - Power Management (1) */ \
|
||||
0x6000, /* R2 - Power Management (2) */ \
|
||||
0x0000, /* R3 - Power Management (3) */ \
|
||||
0x4050, /* R4 - Audio Interface (1) */ \
|
||||
0x4000, /* R5 - Audio Interface (2) */ \
|
||||
0x01C8, /* R6 - Clocking (1) */ \
|
||||
0x0000, /* R7 - Clocking (2) */ \
|
||||
0x0040, /* R8 - Audio Interface (3) */ \
|
||||
0x0040, /* R9 - Audio Interface (4) */ \
|
||||
0x0004, /* R10 - DAC CTRL */ \
|
||||
0x00C0, /* R11 - Left DAC Digital Volume */ \
|
||||
0x00C0, /* R12 - Right DAC Digital Volume */ \
|
||||
0x0000, /* R13 - Digital Side Tone */ \
|
||||
0x0100, /* R14 - ADC CTRL */ \
|
||||
0x00C0, /* R15 - Left ADC Digital Volume */ \
|
||||
0x00C0, /* R16 - Right ADC Digital Volume */ \
|
||||
0x0000, /* R17 */ \
|
||||
0x0000, /* R18 - GPIO CTRL 1 */ \
|
||||
0x1000, /* R19 - GPIO1 & GPIO2 */ \
|
||||
0x1010, /* R20 - GPIO3 & GPIO4 */ \
|
||||
0x1010, /* R21 - GPIO5 & GPIO6 */ \
|
||||
0x8000, /* R22 - GPIOCTRL 2 */ \
|
||||
0x0800, /* R23 - GPIO_POL */ \
|
||||
0x008B, /* R24 - Left Line Input 1&2 Volume */ \
|
||||
0x008B, /* R25 - Left Line Input 3&4 Volume */ \
|
||||
0x008B, /* R26 - Right Line Input 1&2 Volume */ \
|
||||
0x008B, /* R27 - Right Line Input 3&4 Volume */ \
|
||||
0x0000, /* R28 - Left Output Volume */ \
|
||||
0x0000, /* R29 - Right Output Volume */ \
|
||||
0x0066, /* R30 - Line Outputs Volume */ \
|
||||
0x0022, /* R31 - Out3/4 Volume */ \
|
||||
0x0079, /* R32 - Left OPGA Volume */ \
|
||||
0x0079, /* R33 - Right OPGA Volume */ \
|
||||
0x0003, /* R34 - Speaker Volume */ \
|
||||
0x0003, /* R35 - ClassD1 */ \
|
||||
0x0000, /* R36 */ \
|
||||
0x0100, /* R37 - ClassD3 */ \
|
||||
0x0000, /* R38 */ \
|
||||
0x0000, /* R39 - Input Mixer1 */ \
|
||||
0x0000, /* R40 - Input Mixer2 */ \
|
||||
0x0000, /* R41 - Input Mixer3 */ \
|
||||
0x0000, /* R42 - Input Mixer4 */ \
|
||||
0x0000, /* R43 - Input Mixer5 */ \
|
||||
0x0000, /* R44 - Input Mixer6 */ \
|
||||
0x0000, /* R45 - Output Mixer1 */ \
|
||||
0x0000, /* R46 - Output Mixer2 */ \
|
||||
0x0000, /* R47 - Output Mixer3 */ \
|
||||
0x0000, /* R48 - Output Mixer4 */ \
|
||||
0x0000, /* R49 - Output Mixer5 */ \
|
||||
0x0000, /* R50 - Output Mixer6 */ \
|
||||
0x0180, /* R51 - Out3/4 Mixer */ \
|
||||
0x0000, /* R52 - Line Mixer1 */ \
|
||||
0x0000, /* R53 - Line Mixer2 */ \
|
||||
0x0000, /* R54 - Speaker Mixer */ \
|
||||
0x0000, /* R55 - Additional Control */ \
|
||||
0x0000, /* R56 - AntiPOP1 */ \
|
||||
0x0000, /* R57 - AntiPOP2 */ \
|
||||
0x0000, /* R58 - MICBIAS */ \
|
||||
0x0000, /* R59 */ \
|
||||
0x0008, /* R60 - PLL1 */ \
|
||||
0x0031, /* R61 - PLL2 */ \
|
||||
0x0026, /* R62 - PLL3 */ \
|
||||
}
|
||||
|
||||
struct wm8990_setup_data {
|
||||
unsigned short i2c_address;
|
||||
};
|
||||
|
||||
#define WM8990_MCLK_DIV 0
|
||||
#define WM8990_DACCLK_DIV 1
|
||||
#define WM8990_ADCCLK_DIV 2
|
||||
#define WM8990_BCLK_DIV 3
|
||||
|
||||
#define WM8990_MCLK 0
|
||||
|
||||
extern struct snd_soc_codec_dai wm8990_dai;
|
||||
extern struct snd_soc_codec_device soc_codec_dev_wm8990;
|
||||
|
||||
#endif /* __WM8990REGISTERDEFS_H__ */
|
||||
/*------------------------------ END OF FILE ---------------------------------*/
|
||||
772
sound/soc/codecs/wm9712.c
Normal file
772
sound/soc/codecs/wm9712.c
Normal file
@@ -0,0 +1,772 @@
|
||||
/*
|
||||
* wm9712.c -- ALSA Soc WM9712 codec support
|
||||
*
|
||||
* Copyright 2006 Wolfson Microelectronics PLC.
|
||||
* Author: Liam Girdwood
|
||||
* liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Revision history
|
||||
* 4th Feb 2006 Initial version.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/ac97_codec.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
|
||||
#define WM9712_VERSION "0.4"
|
||||
|
||||
static unsigned int ac97_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg);
|
||||
static int ac97_write(struct snd_soc_codec *codec,
|
||||
unsigned int reg, unsigned int val);
|
||||
|
||||
/*
|
||||
* WM9712 register cache
|
||||
*/
|
||||
static const u16 wm9712_reg[] = {
|
||||
0x6174, 0x8000, 0x8000, 0x8000, // 6
|
||||
0x0f0f, 0xaaa0, 0xc008, 0x6808, // e
|
||||
0xe808, 0xaaa0, 0xad00, 0x8000, // 16
|
||||
0xe808, 0x3000, 0x8000, 0x0000, // 1e
|
||||
0x0000, 0x0000, 0x0000, 0x000f, // 26
|
||||
0x0405, 0x0410, 0xbb80, 0xbb80, // 2e
|
||||
0x0000, 0xbb80, 0x0000, 0x0000, // 36
|
||||
0x0000, 0x2000, 0x0000, 0x0000, // 3e
|
||||
0x0000, 0x0000, 0x0000, 0x0000, // 46
|
||||
0x0000, 0x0000, 0xf83e, 0xffff, // 4e
|
||||
0x0000, 0x0000, 0x0000, 0xf83e, // 56
|
||||
0x0008, 0x0000, 0x0000, 0x0000, // 5e
|
||||
0xb032, 0x3e00, 0x0000, 0x0000, // 66
|
||||
0x0000, 0x0000, 0x0000, 0x0000, // 6e
|
||||
0x0000, 0x0000, 0x0000, 0x0006, // 76
|
||||
0x0001, 0x0000, 0x574d, 0x4c12, // 7e
|
||||
0x0000, 0x0000 // virtual hp mixers
|
||||
};
|
||||
|
||||
/* virtual HP mixers regs */
|
||||
#define HPL_MIXER 0x80
|
||||
#define HPR_MIXER 0x82
|
||||
|
||||
static const char *wm9712_alc_select[] = {"None", "Left", "Right", "Stereo"};
|
||||
static const char *wm9712_alc_mux[] = {"Stereo", "Left", "Right", "None"};
|
||||
static const char *wm9712_out3_src[] = {"Left", "VREF", "Left + Right",
|
||||
"Mono"};
|
||||
static const char *wm9712_spk_src[] = {"Speaker Mix", "Headphone Mix"};
|
||||
static const char *wm9712_rec_adc[] = {"Stereo", "Left", "Right", "Mute"};
|
||||
static const char *wm9712_base[] = {"Linear Control", "Adaptive Boost"};
|
||||
static const char *wm9712_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
|
||||
static const char *wm9712_mic[] = {"Mic 1", "Differential", "Mic 2",
|
||||
"Stereo"};
|
||||
static const char *wm9712_rec_sel[] = {"Mic", "NC", "NC", "Speaker Mixer",
|
||||
"Line", "Headphone Mixer", "Phone Mixer", "Phone"};
|
||||
static const char *wm9712_ng_type[] = {"Constant Gain", "Mute"};
|
||||
static const char *wm9712_diff_sel[] = {"Mic", "Line"};
|
||||
|
||||
static const struct soc_enum wm9712_enum[] = {
|
||||
SOC_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9712_alc_select),
|
||||
SOC_ENUM_SINGLE(AC97_VIDEO, 12, 4, wm9712_alc_mux),
|
||||
SOC_ENUM_SINGLE(AC97_AUX, 9, 4, wm9712_out3_src),
|
||||
SOC_ENUM_SINGLE(AC97_AUX, 8, 2, wm9712_spk_src),
|
||||
SOC_ENUM_SINGLE(AC97_REC_SEL, 12, 4, wm9712_rec_adc),
|
||||
SOC_ENUM_SINGLE(AC97_MASTER_TONE, 15, 2, wm9712_base),
|
||||
SOC_ENUM_DOUBLE(AC97_REC_GAIN, 14, 6, 2, wm9712_rec_gain),
|
||||
SOC_ENUM_SINGLE(AC97_MIC, 5, 4, wm9712_mic),
|
||||
SOC_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9712_rec_sel),
|
||||
SOC_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9712_rec_sel),
|
||||
SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9712_ng_type),
|
||||
SOC_ENUM_SINGLE(0x5c, 8, 2, wm9712_diff_sel),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new wm9712_snd_ac97_controls[] = {
|
||||
SOC_DOUBLE("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1),
|
||||
SOC_SINGLE("Speaker Playback Switch", AC97_MASTER, 15, 1, 1),
|
||||
SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1),
|
||||
SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE,15, 1, 1),
|
||||
SOC_DOUBLE("PCM Playback Volume", AC97_PCM, 8, 0, 31, 1),
|
||||
|
||||
SOC_SINGLE("Speaker Playback ZC Switch", AC97_MASTER, 7, 1, 0),
|
||||
SOC_SINGLE("Speaker Playback Invert Switch", AC97_MASTER, 6, 1, 0),
|
||||
SOC_SINGLE("Headphone Playback ZC Switch", AC97_HEADPHONE, 7, 1, 0),
|
||||
SOC_SINGLE("Mono Playback ZC Switch", AC97_MASTER_MONO, 7, 1, 0),
|
||||
SOC_SINGLE("Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 0),
|
||||
|
||||
SOC_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
|
||||
SOC_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
|
||||
SOC_SINGLE("ALC Decay Time", AC97_CODEC_CLASS_REV, 4, 15, 0),
|
||||
SOC_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
|
||||
SOC_ENUM("ALC Function", wm9712_enum[0]),
|
||||
SOC_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0),
|
||||
SOC_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 1),
|
||||
SOC_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
|
||||
SOC_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
|
||||
SOC_ENUM("ALC NG Type", wm9712_enum[10]),
|
||||
SOC_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 1),
|
||||
|
||||
SOC_SINGLE("Mic Headphone Volume", AC97_VIDEO, 12, 7, 1),
|
||||
SOC_SINGLE("ALC Headphone Volume", AC97_VIDEO, 7, 7, 1),
|
||||
|
||||
SOC_SINGLE("Out3 Switch", AC97_AUX, 15, 1, 1),
|
||||
SOC_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 1),
|
||||
SOC_SINGLE("Out3 Volume", AC97_AUX, 0, 31, 1),
|
||||
|
||||
SOC_SINGLE("PCBeep Bypass Headphone Volume", AC97_PC_BEEP, 12, 7, 1),
|
||||
SOC_SINGLE("PCBeep Bypass Speaker Volume", AC97_PC_BEEP, 8, 7, 1),
|
||||
SOC_SINGLE("PCBeep Bypass Phone Volume", AC97_PC_BEEP, 4, 7, 1),
|
||||
|
||||
SOC_SINGLE("Aux Playback Headphone Volume", AC97_CD, 12, 7, 1),
|
||||
SOC_SINGLE("Aux Playback Speaker Volume", AC97_CD, 8, 7, 1),
|
||||
SOC_SINGLE("Aux Playback Phone Volume", AC97_CD, 4, 7, 1),
|
||||
|
||||
SOC_SINGLE("Phone Volume", AC97_PHONE, 0, 15, 0),
|
||||
SOC_DOUBLE("Line Capture Volume", AC97_LINE, 8, 0, 31, 1),
|
||||
|
||||
SOC_SINGLE("Capture 20dB Boost Switch", AC97_REC_SEL, 14, 1, 0),
|
||||
SOC_SINGLE("Capture to Phone 20dB Boost Switch", AC97_REC_SEL, 11, 1, 1),
|
||||
|
||||
SOC_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1),
|
||||
SOC_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1),
|
||||
SOC_SINGLE("3D Playback Volume", AC97_3D_CONTROL, 0, 15, 0),
|
||||
|
||||
SOC_ENUM("Bass Control", wm9712_enum[5]),
|
||||
SOC_SINGLE("Bass Cut-off Switch", AC97_MASTER_TONE, 12, 1, 1),
|
||||
SOC_SINGLE("Tone Cut-off Switch", AC97_MASTER_TONE, 4, 1, 1),
|
||||
SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0),
|
||||
SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 15, 0),
|
||||
SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 0),
|
||||
|
||||
SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN, 15, 1, 1),
|
||||
SOC_ENUM("Capture Volume Steps", wm9712_enum[6]),
|
||||
SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1),
|
||||
SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
|
||||
|
||||
SOC_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
|
||||
SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
|
||||
SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
|
||||
};
|
||||
|
||||
/* add non dapm controls */
|
||||
static int wm9712_add_controls(struct snd_soc_codec *codec)
|
||||
{
|
||||
int err, i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wm9712_snd_ac97_controls); i++) {
|
||||
err = snd_ctl_add(codec->card,
|
||||
snd_soc_cnew(&wm9712_snd_ac97_controls[i],codec, NULL));
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We have to create a fake left and right HP mixers because
|
||||
* the codec only has a single control that is shared by both channels.
|
||||
* This makes it impossible to determine the audio path.
|
||||
*/
|
||||
static int mixer_event (struct snd_soc_dapm_widget *w, int event)
|
||||
{
|
||||
u16 l, r, beep, line, phone, mic, pcm, aux;
|
||||
|
||||
l = ac97_read(w->codec, HPL_MIXER);
|
||||
r = ac97_read(w->codec, HPR_MIXER);
|
||||
beep = ac97_read(w->codec, AC97_PC_BEEP);
|
||||
mic = ac97_read(w->codec, AC97_VIDEO);
|
||||
phone = ac97_read(w->codec, AC97_PHONE);
|
||||
line = ac97_read(w->codec, AC97_LINE);
|
||||
pcm = ac97_read(w->codec, AC97_PCM);
|
||||
aux = ac97_read(w->codec, AC97_CD);
|
||||
|
||||
if (l & 0x1 || r & 0x1)
|
||||
ac97_write(w->codec, AC97_VIDEO, mic & 0x7fff);
|
||||
else
|
||||
ac97_write(w->codec, AC97_VIDEO, mic | 0x8000);
|
||||
|
||||
if (l & 0x2 || r & 0x2)
|
||||
ac97_write(w->codec, AC97_PCM, pcm & 0x7fff);
|
||||
else
|
||||
ac97_write(w->codec, AC97_PCM, pcm | 0x8000);
|
||||
|
||||
if (l & 0x4 || r & 0x4)
|
||||
ac97_write(w->codec, AC97_LINE, line & 0x7fff);
|
||||
else
|
||||
ac97_write(w->codec, AC97_LINE, line | 0x8000);
|
||||
|
||||
if (l & 0x8 || r & 0x8)
|
||||
ac97_write(w->codec, AC97_PHONE, phone & 0x7fff);
|
||||
else
|
||||
ac97_write(w->codec, AC97_PHONE, phone | 0x8000);
|
||||
|
||||
if (l & 0x10 || r & 0x10)
|
||||
ac97_write(w->codec, AC97_CD, aux & 0x7fff);
|
||||
else
|
||||
ac97_write(w->codec, AC97_CD, aux | 0x8000);
|
||||
|
||||
if (l & 0x20 || r & 0x20)
|
||||
ac97_write(w->codec, AC97_PC_BEEP, beep & 0x7fff);
|
||||
else
|
||||
ac97_write(w->codec, AC97_PC_BEEP, beep | 0x8000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Left Headphone Mixers */
|
||||
static const struct snd_kcontrol_new wm9712_hpl_mixer_controls[] = {
|
||||
SOC_DAPM_SINGLE("PCBeep Bypass Switch", HPL_MIXER, 5, 1, 0),
|
||||
SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 4, 1, 0),
|
||||
SOC_DAPM_SINGLE("Phone Bypass Switch", HPL_MIXER, 3, 1, 0),
|
||||
SOC_DAPM_SINGLE("Line Bypass Switch", HPL_MIXER, 2, 1, 0),
|
||||
SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 1, 1, 0),
|
||||
SOC_DAPM_SINGLE("Mic Sidetone Switch", HPL_MIXER, 0, 1, 0),
|
||||
};
|
||||
|
||||
/* Right Headphone Mixers */
|
||||
static const struct snd_kcontrol_new wm9712_hpr_mixer_controls[] = {
|
||||
SOC_DAPM_SINGLE("PCBeep Bypass Switch", HPR_MIXER, 5, 1, 0),
|
||||
SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 4, 1, 0),
|
||||
SOC_DAPM_SINGLE("Phone Bypass Switch", HPR_MIXER, 3, 1, 0),
|
||||
SOC_DAPM_SINGLE("Line Bypass Switch", HPR_MIXER, 2, 1, 0),
|
||||
SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 1, 1, 0),
|
||||
SOC_DAPM_SINGLE("Mic Sidetone Switch", HPR_MIXER, 0, 1, 0),
|
||||
};
|
||||
|
||||
/* Speaker Mixer */
|
||||
static const struct snd_kcontrol_new wm9712_speaker_mixer_controls[] = {
|
||||
SOC_DAPM_SINGLE("PCBeep Bypass Switch", AC97_PC_BEEP, 11, 1, 1),
|
||||
SOC_DAPM_SINGLE("Aux Playback Switch", AC97_CD, 11, 1, 1),
|
||||
SOC_DAPM_SINGLE("Phone Bypass Switch", AC97_PHONE, 14, 1, 1),
|
||||
SOC_DAPM_SINGLE("Line Bypass Switch", AC97_LINE, 14, 1, 1),
|
||||
SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PCM, 14, 1, 1),
|
||||
};
|
||||
|
||||
/* Phone Mixer */
|
||||
static const struct snd_kcontrol_new wm9712_phone_mixer_controls[] = {
|
||||
SOC_DAPM_SINGLE("PCBeep Bypass Switch", AC97_PC_BEEP, 7, 1, 1),
|
||||
SOC_DAPM_SINGLE("Aux Playback Switch", AC97_CD, 7, 1, 1),
|
||||
SOC_DAPM_SINGLE("Line Bypass Switch", AC97_LINE, 13, 1, 1),
|
||||
SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PCM, 13, 1, 1),
|
||||
SOC_DAPM_SINGLE("Mic 1 Sidetone Switch", AC97_MIC, 14, 1, 1),
|
||||
SOC_DAPM_SINGLE("Mic 2 Sidetone Switch", AC97_MIC, 13, 1, 1),
|
||||
};
|
||||
|
||||
/* ALC headphone mux */
|
||||
static const struct snd_kcontrol_new wm9712_alc_mux_controls =
|
||||
SOC_DAPM_ENUM("Route", wm9712_enum[1]);
|
||||
|
||||
/* out 3 mux */
|
||||
static const struct snd_kcontrol_new wm9712_out3_mux_controls =
|
||||
SOC_DAPM_ENUM("Route", wm9712_enum[2]);
|
||||
|
||||
/* spk mux */
|
||||
static const struct snd_kcontrol_new wm9712_spk_mux_controls =
|
||||
SOC_DAPM_ENUM("Route", wm9712_enum[3]);
|
||||
|
||||
/* Capture to Phone mux */
|
||||
static const struct snd_kcontrol_new wm9712_capture_phone_mux_controls =
|
||||
SOC_DAPM_ENUM("Route", wm9712_enum[4]);
|
||||
|
||||
/* Capture left select */
|
||||
static const struct snd_kcontrol_new wm9712_capture_selectl_controls =
|
||||
SOC_DAPM_ENUM("Route", wm9712_enum[8]);
|
||||
|
||||
/* Capture right select */
|
||||
static const struct snd_kcontrol_new wm9712_capture_selectr_controls =
|
||||
SOC_DAPM_ENUM("Route", wm9712_enum[9]);
|
||||
|
||||
/* Mic select */
|
||||
static const struct snd_kcontrol_new wm9712_mic_src_controls =
|
||||
SOC_DAPM_ENUM("Route", wm9712_enum[7]);
|
||||
|
||||
/* diff select */
|
||||
static const struct snd_kcontrol_new wm9712_diff_sel_controls =
|
||||
SOC_DAPM_ENUM("Route", wm9712_enum[11]);
|
||||
|
||||
static const struct snd_soc_dapm_widget wm9712_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_MUX("ALC Sidetone Mux", SND_SOC_NOPM, 0, 0,
|
||||
&wm9712_alc_mux_controls),
|
||||
SND_SOC_DAPM_MUX("Out3 Mux", SND_SOC_NOPM, 0, 0,
|
||||
&wm9712_out3_mux_controls),
|
||||
SND_SOC_DAPM_MUX("Speaker Mux", SND_SOC_NOPM, 0, 0,
|
||||
&wm9712_spk_mux_controls),
|
||||
SND_SOC_DAPM_MUX("Capture Phone Mux", SND_SOC_NOPM, 0, 0,
|
||||
&wm9712_capture_phone_mux_controls),
|
||||
SND_SOC_DAPM_MUX("Left Capture Select", SND_SOC_NOPM, 0, 0,
|
||||
&wm9712_capture_selectl_controls),
|
||||
SND_SOC_DAPM_MUX("Right Capture Select", SND_SOC_NOPM, 0, 0,
|
||||
&wm9712_capture_selectr_controls),
|
||||
SND_SOC_DAPM_MUX("Mic Select Source", SND_SOC_NOPM, 0, 0,
|
||||
&wm9712_mic_src_controls),
|
||||
SND_SOC_DAPM_MUX("Differential Source", SND_SOC_NOPM, 0, 0,
|
||||
&wm9712_diff_sel_controls),
|
||||
SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_INT_PAGING, 9, 1,
|
||||
&wm9712_hpl_mixer_controls[0], ARRAY_SIZE(wm9712_hpl_mixer_controls),
|
||||
mixer_event, SND_SOC_DAPM_POST_REG),
|
||||
SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_INT_PAGING, 8, 1,
|
||||
&wm9712_hpr_mixer_controls[0], ARRAY_SIZE(wm9712_hpr_mixer_controls),
|
||||
mixer_event, SND_SOC_DAPM_POST_REG),
|
||||
SND_SOC_DAPM_MIXER("Phone Mixer", AC97_INT_PAGING, 6, 1,
|
||||
&wm9712_phone_mixer_controls[0], ARRAY_SIZE(wm9712_phone_mixer_controls)),
|
||||
SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_INT_PAGING, 7, 1,
|
||||
&wm9712_speaker_mixer_controls[0],
|
||||
ARRAY_SIZE(wm9712_speaker_mixer_controls)),
|
||||
SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", AC97_INT_PAGING, 14, 1),
|
||||
SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", AC97_INT_PAGING, 13, 1),
|
||||
SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", AC97_INT_PAGING, 12, 1),
|
||||
SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", AC97_INT_PAGING, 11, 1),
|
||||
SND_SOC_DAPM_PGA("Headphone PGA", AC97_INT_PAGING, 4, 1, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("Speaker PGA", AC97_INT_PAGING, 3, 1, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("Out 3 PGA", AC97_INT_PAGING, 5, 1, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("Line PGA", AC97_INT_PAGING, 2, 1, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("Phone PGA", AC97_INT_PAGING, 1, 1, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("Mic PGA", AC97_INT_PAGING, 0, 1, NULL, 0),
|
||||
SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_INT_PAGING, 10, 1),
|
||||
SND_SOC_DAPM_OUTPUT("MONOOUT"),
|
||||
SND_SOC_DAPM_OUTPUT("HPOUTL"),
|
||||
SND_SOC_DAPM_OUTPUT("HPOUTR"),
|
||||
SND_SOC_DAPM_OUTPUT("LOUT2"),
|
||||
SND_SOC_DAPM_OUTPUT("ROUT2"),
|
||||
SND_SOC_DAPM_OUTPUT("OUT3"),
|
||||
SND_SOC_DAPM_INPUT("LINEINL"),
|
||||
SND_SOC_DAPM_INPUT("LINEINR"),
|
||||
SND_SOC_DAPM_INPUT("PHONE"),
|
||||
SND_SOC_DAPM_INPUT("PCBEEP"),
|
||||
SND_SOC_DAPM_INPUT("MIC1"),
|
||||
SND_SOC_DAPM_INPUT("MIC2"),
|
||||
};
|
||||
|
||||
static const char *audio_map[][3] = {
|
||||
/* virtual mixer - mixes left & right channels for spk and mono */
|
||||
{"AC97 Mixer", NULL, "Left DAC"},
|
||||
{"AC97 Mixer", NULL, "Right DAC"},
|
||||
|
||||
/* Left HP mixer */
|
||||
{"Left HP Mixer", "PCBeep Bypass Switch", "PCBEEP"},
|
||||
{"Left HP Mixer", "Aux Playback Switch", "Aux DAC"},
|
||||
{"Left HP Mixer", "Phone Bypass Switch", "Phone PGA"},
|
||||
{"Left HP Mixer", "Line Bypass Switch", "Line PGA"},
|
||||
{"Left HP Mixer", "PCM Playback Switch", "Left DAC"},
|
||||
{"Left HP Mixer", "Mic Sidetone Switch", "Mic PGA"},
|
||||
{"Left HP Mixer", NULL, "ALC Sidetone Mux"},
|
||||
//{"Right HP Mixer", NULL, "HP Mixer"},
|
||||
|
||||
/* Right HP mixer */
|
||||
{"Right HP Mixer", "PCBeep Bypass Switch", "PCBEEP"},
|
||||
{"Right HP Mixer", "Aux Playback Switch", "Aux DAC"},
|
||||
{"Right HP Mixer", "Phone Bypass Switch", "Phone PGA"},
|
||||
{"Right HP Mixer", "Line Bypass Switch", "Line PGA"},
|
||||
{"Right HP Mixer", "PCM Playback Switch", "Right DAC"},
|
||||
{"Right HP Mixer", "Mic Sidetone Switch", "Mic PGA"},
|
||||
{"Right HP Mixer", NULL, "ALC Sidetone Mux"},
|
||||
|
||||
/* speaker mixer */
|
||||
{"Speaker Mixer", "PCBeep Bypass Switch", "PCBEEP"},
|
||||
{"Speaker Mixer", "Line Bypass Switch", "Line PGA"},
|
||||
{"Speaker Mixer", "PCM Playback Switch", "AC97 Mixer"},
|
||||
{"Speaker Mixer", "Phone Bypass Switch", "Phone PGA"},
|
||||
{"Speaker Mixer", "Aux Playback Switch", "Aux DAC"},
|
||||
|
||||
/* Phone mixer */
|
||||
{"Phone Mixer", "PCBeep Bypass Switch", "PCBEEP"},
|
||||
{"Phone Mixer", "Line Bypass Switch", "Line PGA"},
|
||||
{"Phone Mixer", "Aux Playback Switch", "Aux DAC"},
|
||||
{"Phone Mixer", "PCM Playback Switch", "AC97 Mixer"},
|
||||
{"Phone Mixer", "Mic 1 Sidetone Switch", "Mic PGA"},
|
||||
{"Phone Mixer", "Mic 2 Sidetone Switch", "Mic PGA"},
|
||||
|
||||
/* inputs */
|
||||
{"Line PGA", NULL, "LINEINL"},
|
||||
{"Line PGA", NULL, "LINEINR"},
|
||||
{"Phone PGA", NULL, "PHONE"},
|
||||
{"Mic PGA", NULL, "MIC1"},
|
||||
{"Mic PGA", NULL, "MIC2"},
|
||||
|
||||
/* left capture selector */
|
||||
{"Left Capture Select", "Mic", "MIC1"},
|
||||
{"Left Capture Select", "Speaker Mixer", "Speaker Mixer"},
|
||||
{"Left Capture Select", "Line", "LINEINL"},
|
||||
{"Left Capture Select", "Headphone Mixer", "Left HP Mixer"},
|
||||
{"Left Capture Select", "Phone Mixer", "Phone Mixer"},
|
||||
{"Left Capture Select", "Phone", "PHONE"},
|
||||
|
||||
/* right capture selector */
|
||||
{"Right Capture Select", "Mic", "MIC2"},
|
||||
{"Right Capture Select", "Speaker Mixer", "Speaker Mixer"},
|
||||
{"Right Capture Select", "Line", "LINEINR"},
|
||||
{"Right Capture Select", "Headphone Mixer", "Right HP Mixer"},
|
||||
{"Right Capture Select", "Phone Mixer", "Phone Mixer"},
|
||||
{"Right Capture Select", "Phone", "PHONE"},
|
||||
|
||||
/* ALC Sidetone */
|
||||
{"ALC Sidetone Mux", "Stereo", "Left Capture Select"},
|
||||
{"ALC Sidetone Mux", "Stereo", "Right Capture Select"},
|
||||
{"ALC Sidetone Mux", "Left", "Left Capture Select"},
|
||||
{"ALC Sidetone Mux", "Right", "Right Capture Select"},
|
||||
|
||||
/* ADC's */
|
||||
{"Left ADC", NULL, "Left Capture Select"},
|
||||
{"Right ADC", NULL, "Right Capture Select"},
|
||||
|
||||
/* outputs */
|
||||
{"MONOOUT", NULL, "Phone Mixer"},
|
||||
{"HPOUTL", NULL, "Headphone PGA"},
|
||||
{"Headphone PGA", NULL, "Left HP Mixer"},
|
||||
{"HPOUTR", NULL, "Headphone PGA"},
|
||||
{"Headphone PGA", NULL, "Right HP Mixer"},
|
||||
|
||||
/* mono hp mixer */
|
||||
{"Mono HP Mixer", NULL, "Left HP Mixer"},
|
||||
{"Mono HP Mixer", NULL, "Right HP Mixer"},
|
||||
|
||||
/* Out3 Mux */
|
||||
{"Out3 Mux", "Left", "Left HP Mixer"},
|
||||
{"Out3 Mux", "Mono", "Phone Mixer"},
|
||||
{"Out3 Mux", "Left + Right", "Mono HP Mixer"},
|
||||
{"Out 3 PGA", NULL, "Out3 Mux"},
|
||||
{"OUT3", NULL, "Out 3 PGA"},
|
||||
|
||||
/* speaker Mux */
|
||||
{"Speaker Mux", "Speaker Mix", "Speaker Mixer"},
|
||||
{"Speaker Mux", "Headphone Mix", "Mono HP Mixer"},
|
||||
{"Speaker PGA", NULL, "Speaker Mux"},
|
||||
{"LOUT2", NULL, "Speaker PGA"},
|
||||
{"ROUT2", NULL, "Speaker PGA"},
|
||||
|
||||
{NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
static int wm9712_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(wm9712_dapm_widgets); i++) {
|
||||
snd_soc_dapm_new_control(codec, &wm9712_dapm_widgets[i]);
|
||||
}
|
||||
|
||||
/* set up audio path audio_mapnects */
|
||||
for(i = 0; audio_map[i][0] != NULL; i++) {
|
||||
snd_soc_dapm_connect_input(codec, audio_map[i][0],
|
||||
audio_map[i][1], audio_map[i][2]);
|
||||
}
|
||||
|
||||
snd_soc_dapm_new_widgets(codec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int ac97_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
|
||||
reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 ||
|
||||
reg == AC97_REC_GAIN)
|
||||
return soc_ac97_ops.read(codec->ac97, reg);
|
||||
else {
|
||||
reg = reg >> 1;
|
||||
|
||||
if (reg > (ARRAY_SIZE(wm9712_reg)))
|
||||
return -EIO;
|
||||
|
||||
return cache[reg];
|
||||
}
|
||||
}
|
||||
|
||||
static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int val)
|
||||
{
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
soc_ac97_ops.write(codec->ac97, reg, val);
|
||||
reg = reg >> 1;
|
||||
if (reg <= (ARRAY_SIZE(wm9712_reg)))
|
||||
cache[reg] = val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ac97_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_device *socdev = rtd->socdev;
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
int reg;
|
||||
u16 vra;
|
||||
|
||||
vra = ac97_read(codec, AC97_EXTENDED_STATUS);
|
||||
ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
reg = AC97_PCM_FRONT_DAC_RATE;
|
||||
else
|
||||
reg = AC97_PCM_LR_ADC_RATE;
|
||||
|
||||
return ac97_write(codec, reg, runtime->rate);
|
||||
}
|
||||
|
||||
static int ac97_aux_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_device *socdev = rtd->socdev;
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
u16 vra, xsle;
|
||||
|
||||
vra = ac97_read(codec, AC97_EXTENDED_STATUS);
|
||||
ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
|
||||
xsle = ac97_read(codec, AC97_PCI_SID);
|
||||
ac97_write(codec, AC97_PCI_SID, xsle | 0x8000);
|
||||
|
||||
if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
|
||||
return -ENODEV;
|
||||
|
||||
return ac97_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate);
|
||||
}
|
||||
|
||||
#define WM9712_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
|
||||
SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
|
||||
|
||||
struct snd_soc_codec_dai wm9712_dai[] = {
|
||||
{
|
||||
.name = "AC97 HiFi",
|
||||
.type = SND_SOC_DAI_AC97_BUS,
|
||||
.playback = {
|
||||
.stream_name = "HiFi Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = WM9712_AC97_RATES,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
|
||||
.capture = {
|
||||
.stream_name = "HiFi Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = WM9712_AC97_RATES,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
|
||||
.ops = {
|
||||
.prepare = ac97_prepare,},
|
||||
},
|
||||
{
|
||||
.name = "AC97 Aux",
|
||||
.playback = {
|
||||
.stream_name = "Aux Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 1,
|
||||
.rates = WM9712_AC97_RATES,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
|
||||
.ops = {
|
||||
.prepare = ac97_aux_prepare,},
|
||||
}
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(wm9712_dai);
|
||||
|
||||
static int wm9712_dapm_event(struct snd_soc_codec *codec, int event)
|
||||
{
|
||||
u16 reg;
|
||||
|
||||
switch (event) {
|
||||
case SNDRV_CTL_POWER_D0: /* full On */
|
||||
/* liam - maybe enable thermal shutdown */
|
||||
reg = ac97_read(codec, AC97_EXTENDED_MID) & 0xdfff;
|
||||
ac97_write(codec, AC97_EXTENDED_MID, reg);
|
||||
break;
|
||||
case SNDRV_CTL_POWER_D1: /* partial On */
|
||||
case SNDRV_CTL_POWER_D2: /* partial On */
|
||||
break;
|
||||
case SNDRV_CTL_POWER_D3hot: /* Off, with power */
|
||||
/* enable master bias and vmid */
|
||||
reg = ac97_read(codec, AC97_EXTENDED_MID) & 0xbbff;
|
||||
ac97_write(codec, AC97_EXTENDED_MID, reg);
|
||||
ac97_write(codec, AC97_POWERDOWN, 0x0000);
|
||||
break;
|
||||
case SNDRV_CTL_POWER_D3cold: /* Off, without power */
|
||||
/* disable everything including AC link */
|
||||
ac97_write(codec, AC97_EXTENDED_MID, 0xffff);
|
||||
ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
|
||||
ac97_write(codec, AC97_POWERDOWN, 0xffff);
|
||||
break;
|
||||
}
|
||||
codec->dapm_state = event;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm9712_reset(struct snd_soc_codec *codec, int try_warm)
|
||||
{
|
||||
if (try_warm && soc_ac97_ops.warm_reset) {
|
||||
soc_ac97_ops.warm_reset(codec->ac97);
|
||||
if (!(ac97_read(codec, 0) & 0x8000))
|
||||
return 1;
|
||||
}
|
||||
|
||||
soc_ac97_ops.reset(codec->ac97);
|
||||
if (ac97_read(codec, 0) & 0x8000)
|
||||
goto err;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
printk(KERN_ERR "WM9712 AC97 reset failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int wm9712_soc_suspend(struct platform_device *pdev,
|
||||
pm_message_t state)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
|
||||
wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm9712_soc_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
int i, ret;
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
ret = wm9712_reset(codec, 1);
|
||||
if (ret < 0){
|
||||
printk(KERN_ERR "could not reset AC97 codec\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
|
||||
|
||||
if (ret == 0) {
|
||||
/* Sync reg_cache with the hardware after cold reset */
|
||||
for (i = 2; i < ARRAY_SIZE(wm9712_reg) << 1; i+=2) {
|
||||
if (i == AC97_INT_PAGING || i == AC97_POWERDOWN ||
|
||||
(i > 0x58 && i != 0x5c))
|
||||
continue;
|
||||
soc_ac97_ops.write(codec->ac97, i, cache[i>>1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0)
|
||||
wm9712_dapm_event(codec, SNDRV_CTL_POWER_D0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wm9712_soc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec;
|
||||
int ret = 0;
|
||||
|
||||
printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION);
|
||||
|
||||
socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
|
||||
if (socdev->codec == NULL)
|
||||
return -ENOMEM;
|
||||
codec = socdev->codec;
|
||||
mutex_init(&codec->mutex);
|
||||
|
||||
codec->reg_cache = kmemdup(wm9712_reg, sizeof(wm9712_reg), GFP_KERNEL);
|
||||
|
||||
if (codec->reg_cache == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto cache_err;
|
||||
}
|
||||
codec->reg_cache_size = sizeof(wm9712_reg);
|
||||
codec->reg_cache_step = 2;
|
||||
|
||||
codec->name = "WM9712";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->dai = wm9712_dai;
|
||||
codec->num_dai = ARRAY_SIZE(wm9712_dai);
|
||||
codec->write = ac97_write;
|
||||
codec->read = ac97_read;
|
||||
codec->dapm_event = wm9712_dapm_event;
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
|
||||
ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "wm9712: failed to register AC97 codec\n");
|
||||
goto codec_err;
|
||||
}
|
||||
|
||||
/* register pcms */
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
if (ret < 0)
|
||||
goto pcm_err;
|
||||
|
||||
ret = wm9712_reset(codec, 0);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "AC97 link error\n");
|
||||
goto reset_err;
|
||||
}
|
||||
|
||||
/* set alc mux to none */
|
||||
ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000);
|
||||
|
||||
wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
|
||||
wm9712_add_controls(codec);
|
||||
wm9712_add_widgets(codec);
|
||||
ret = snd_soc_register_card(socdev);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "wm9712: failed to register card\n");
|
||||
goto reset_err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
reset_err:
|
||||
snd_soc_free_pcms(socdev);
|
||||
|
||||
pcm_err:
|
||||
snd_soc_free_ac97_codec(codec);
|
||||
|
||||
codec_err:
|
||||
kfree(codec->reg_cache);
|
||||
|
||||
cache_err:
|
||||
kfree(socdev->codec);
|
||||
socdev->codec = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wm9712_soc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->codec;
|
||||
|
||||
if (codec == NULL)
|
||||
return 0;
|
||||
|
||||
snd_soc_dapm_free(socdev);
|
||||
snd_soc_free_pcms(socdev);
|
||||
snd_soc_free_ac97_codec(codec);
|
||||
kfree(codec->reg_cache);
|
||||
kfree(codec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_wm9712 = {
|
||||
.probe = wm9712_soc_probe,
|
||||
.remove = wm9712_soc_remove,
|
||||
.suspend = wm9712_soc_suspend,
|
||||
.resume = wm9712_soc_resume,
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL_GPL(soc_codec_dev_wm9712);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver");
|
||||
MODULE_AUTHOR("Liam Girdwood");
|
||||
MODULE_LICENSE("GPL");
|
||||
14
sound/soc/codecs/wm9712.h
Normal file
14
sound/soc/codecs/wm9712.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* wm9712.h -- WM9712 Soc Audio driver
|
||||
*/
|
||||
|
||||
#ifndef _WM9712_H
|
||||
#define _WM9712_H
|
||||
|
||||
#define WM9712_DAI_AC97_HIFI 0
|
||||
#define WM9712_DAI_AC97_AUX 1
|
||||
|
||||
extern struct snd_soc_codec_dai wm9712_dai[2];
|
||||
extern struct snd_soc_codec_device soc_codec_dev_wm9712;
|
||||
|
||||
#endif
|
||||
1224
sound/soc/codecs/wm9713.c
Normal file
1224
sound/soc/codecs/wm9713.c
Normal file
File diff suppressed because it is too large
Load Diff
51
sound/soc/codecs/wm9713.h
Normal file
51
sound/soc/codecs/wm9713.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* wm9713.h -- WM9713 Soc Audio driver
|
||||
*/
|
||||
|
||||
#ifndef _WM9713_H
|
||||
#define _WM9713_H
|
||||
|
||||
/* clock inputs */
|
||||
#define WM9713_CLKA_PIN 0
|
||||
#define WM9713_CLKB_PIN 1
|
||||
|
||||
/* clock divider ID's */
|
||||
#define WM9713_PCMCLK_DIV 0
|
||||
#define WM9713_CLKA_MULT 1
|
||||
#define WM9713_CLKB_MULT 2
|
||||
#define WM9713_HIFI_DIV 3
|
||||
#define WM9713_PCMBCLK_DIV 4
|
||||
|
||||
/* PCM clk div */
|
||||
#define WM9713_PCMDIV(x) ((x - 1) << 8)
|
||||
|
||||
/* HiFi Div */
|
||||
#define WM9713_HIFIDIV(x) ((x - 1) << 12)
|
||||
|
||||
/* MCLK clock mulitipliers */
|
||||
#define WM9713_CLKA_X1 (0 << 1)
|
||||
#define WM9713_CLKA_X2 (1 << 1)
|
||||
#define WM9713_CLKB_X1 (0 << 2)
|
||||
#define WM9713_CLKB_X2 (1 << 2)
|
||||
|
||||
/* MCLK clock MUX */
|
||||
#define WM9713_CLK_MUX_A (0 << 0)
|
||||
#define WM9713_CLK_MUX_B (1 << 0)
|
||||
|
||||
/* Voice DAI BCLK divider */
|
||||
#define WM9713_PCMBCLK_DIV_1 (0 << 9)
|
||||
#define WM9713_PCMBCLK_DIV_2 (1 << 9)
|
||||
#define WM9713_PCMBCLK_DIV_4 (2 << 9)
|
||||
#define WM9713_PCMBCLK_DIV_8 (3 << 9)
|
||||
#define WM9713_PCMBCLK_DIV_16 (4 << 9)
|
||||
|
||||
#define WM9713_DAI_AC97_HIFI 0
|
||||
#define WM9713_DAI_AC97_AUX 1
|
||||
#define WM9713_DAI_PCM_VOICE 2
|
||||
|
||||
extern struct snd_soc_codec_device soc_codec_dev_wm9713;
|
||||
extern struct snd_soc_codec_dai wm9713_dai[3];
|
||||
|
||||
int wm9713_reset(struct snd_soc_codec *codec, int try_warm);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user