提交 27b92d4f 编写于 作者: T Takashi Iwai

Merge branch 'topic/asoc' into for-linus

......@@ -119,13 +119,6 @@ static struct platform_device keysc_device = {
};
/* FSI A */
static struct sh_fsi_platform_info fsi_info = {
.porta_flags = SH_FSI_OUT_SLAVE_MODE |
SH_FSI_IN_SLAVE_MODE |
SH_FSI_OFMT(I2S) |
SH_FSI_IFMT(I2S),
};
static struct resource fsi_resources[] = {
[0] = {
.name = "FSI",
......@@ -144,9 +137,6 @@ static struct platform_device fsi_device = {
.id = -1,
.num_resources = ARRAY_SIZE(fsi_resources),
.resource = fsi_resources,
.dev = {
.platform_data = &fsi_info,
},
};
static struct resource sh_mmcif_resources[] = {
......
......@@ -673,16 +673,12 @@ static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable)
}
static struct sh_fsi_platform_info fsi_info = {
.porta_flags = SH_FSI_BRS_INV |
SH_FSI_OUT_SLAVE_MODE |
SH_FSI_IN_SLAVE_MODE |
SH_FSI_OFMT(PCM) |
SH_FSI_IFMT(PCM),
.porta_flags = SH_FSI_BRS_INV,
.portb_flags = SH_FSI_BRS_INV |
SH_FSI_BRM_INV |
SH_FSI_LRS_INV |
SH_FSI_OFMT(SPDIF),
SH_FSI_FMT_SPDIF,
.set_rate = fsi_set_rate,
};
......@@ -783,6 +779,10 @@ static struct platform_device hdmi_device = {
},
};
static struct platform_device fsi_hdmi_device = {
.name = "sh_fsi2_b_hdmi",
};
static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq,
unsigned long *parent_freq)
{
......@@ -936,6 +936,7 @@ static struct platform_device *ap4evb_devices[] __initdata = {
&usb1_host_device,
&fsi_device,
&fsi_ak4643_device,
&fsi_hdmi_device,
&sh_mmcif_device,
&lcdc1_device,
&lcdc_device,
......
......@@ -399,6 +399,10 @@ static struct platform_device hdmi_device = {
},
};
static struct platform_device fsi_hdmi_device = {
.name = "sh_fsi2_b_hdmi",
};
static int __init hdmi_init_pm_clock(void)
{
struct clk *hdmi_ick = clk_get(&hdmi_device.dev, "ick");
......@@ -609,16 +613,12 @@ static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable)
}
static struct sh_fsi_platform_info fsi_info = {
.porta_flags = SH_FSI_BRS_INV |
SH_FSI_OUT_SLAVE_MODE |
SH_FSI_IN_SLAVE_MODE |
SH_FSI_OFMT(PCM) |
SH_FSI_IFMT(PCM),
.porta_flags = SH_FSI_BRS_INV,
.portb_flags = SH_FSI_BRS_INV |
SH_FSI_BRM_INV |
SH_FSI_LRS_INV |
SH_FSI_OFMT(SPDIF),
SH_FSI_FMT_SPDIF,
.set_rate = fsi_set_rate,
};
......@@ -921,6 +921,7 @@ static struct platform_device *mackerel_devices[] __initdata = {
&leds_device,
&fsi_device,
&fsi_ak4643_device,
&fsi_hdmi_device,
&sdhi0_device,
#if !defined(CONFIG_MMC_SH_MMCIF)
&sdhi1_device,
......
/*
* arch/arm/mach-tegra/include/mach/harmony_audio.h
*
* Copyright 2011 NVIDIA, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
struct harmony_audio_platform_data {
int gpio_spkr_en;
int gpio_hp_det;
int gpio_int_mic_en;
int gpio_ext_mic_en;
};
......@@ -723,11 +723,7 @@ static struct platform_device camera_devices[] = {
/* FSI */
static struct sh_fsi_platform_info fsi_info = {
.portb_flags = SH_FSI_BRS_INV |
SH_FSI_OUT_SLAVE_MODE |
SH_FSI_IN_SLAVE_MODE |
SH_FSI_OFMT(I2S) |
SH_FSI_IFMT(I2S),
.portb_flags = SH_FSI_BRS_INV,
};
static struct resource fsi_resources[] = {
......
......@@ -286,11 +286,7 @@ static struct platform_device ceu1_device = {
/* FSI */
/* change J20, J21, J22 pin to 1-2 connection to use slave mode */
static struct sh_fsi_platform_info fsi_info = {
.porta_flags = SH_FSI_BRS_INV |
SH_FSI_OUT_SLAVE_MODE |
SH_FSI_IN_SLAVE_MODE |
SH_FSI_OFMT(PCM) |
SH_FSI_IFMT(PCM),
.porta_flags = SH_FSI_BRS_INV,
};
static struct resource fsi_resources[] = {
......
......@@ -103,13 +103,21 @@ struct wm8994_pdata {
unsigned int lineout1fb:1;
unsigned int lineout2fb:1;
/* Microphone biases: 0=0.9*AVDD1 1=0.65*AVVD1 */
/* IRQ for microphone detection if brought out directly as a
* signal.
*/
int micdet_irq;
/* WM8994 microphone biases: 0=0.9*AVDD1 1=0.65*AVVD1 */
unsigned int micbias1_lvl:1;
unsigned int micbias2_lvl:1;
/* Jack detect threashold levels, see datasheet for values */
/* WM8994 jack detect threashold levels, see datasheet for values */
unsigned int jd_scthr:2;
unsigned int jd_thr:2;
/* WM8958 microphone bias configuration */
int micbias[2];
};
#endif
......@@ -63,6 +63,8 @@
#define WM8994_MICBIAS 0x3A
#define WM8994_LDO_1 0x3B
#define WM8994_LDO_2 0x3C
#define WM8958_MICBIAS1 0x3D
#define WM8958_MICBIAS2 0x3E
#define WM8994_CHARGE_PUMP_1 0x4C
#define WM8958_CHARGE_PUMP_2 0x4D
#define WM8994_CLASS_W_1 0x51
......
......@@ -115,6 +115,8 @@ int snd_ctl_add(struct snd_card * card, struct snd_kcontrol * kcontrol);
int snd_ctl_remove(struct snd_card * card, struct snd_kcontrol * kcontrol);
int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id);
int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id);
int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
int active);
struct snd_kcontrol *snd_ctl_find_numid(struct snd_card * card, unsigned int numid);
struct snd_kcontrol *snd_ctl_find_id(struct snd_card * card, struct snd_ctl_elem_id *id);
......
/*
* Definitions for CS4271 ASoC codec driver
*
* Copyright (c) 2010 Alexander Sverdlin <subaparts@yandex.ru>
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __CS4271_H
#define __CS4271_H
struct cs4271_platform_data {
int gpio_nreset; /* GPIO driving Reset pin, if any */
};
#endif /* __CS4271_H */
......@@ -15,67 +15,29 @@
#define FSI_PORT_A 0
#define FSI_PORT_B 1
/* flags format
* 0xABCDEEFF
*
* A: channel size for TDM (input)
* B: channel size for TDM (ooutput)
* C: inversion
* D: mode
* E: input format
* F: output format
*/
#include <linux/clk.h>
#include <sound/soc.h>
/* TDM channel */
#define SH_FSI_SET_CH_I(x) ((x & 0xF) << 28)
#define SH_FSI_SET_CH_O(x) ((x & 0xF) << 24)
#define SH_FSI_CH_IMASK 0xF0000000
#define SH_FSI_CH_OMASK 0x0F000000
#define SH_FSI_GET_CH_I(x) ((x & SH_FSI_CH_IMASK) >> 28)
#define SH_FSI_GET_CH_O(x) ((x & SH_FSI_CH_OMASK) >> 24)
/* clock inversion */
#define SH_FSI_INVERSION_MASK 0x00F00000
#define SH_FSI_LRM_INV (1 << 20)
#define SH_FSI_BRM_INV (1 << 21)
#define SH_FSI_LRS_INV (1 << 22)
#define SH_FSI_BRS_INV (1 << 23)
/* mode */
#define SH_FSI_MODE_MASK 0x000F0000
#define SH_FSI_IN_SLAVE_MODE (1 << 16) /* default master mode */
#define SH_FSI_OUT_SLAVE_MODE (1 << 17) /* default master mode */
/* DI format */
#define SH_FSI_FMT_MASK 0x000000FF
#define SH_FSI_IFMT(x) (((SH_FSI_FMT_ ## x) & SH_FSI_FMT_MASK) << 8)
#define SH_FSI_OFMT(x) (((SH_FSI_FMT_ ## x) & SH_FSI_FMT_MASK) << 0)
#define SH_FSI_GET_IFMT(x) ((x >> 8) & SH_FSI_FMT_MASK)
#define SH_FSI_GET_OFMT(x) ((x >> 0) & SH_FSI_FMT_MASK)
#define SH_FSI_FMT_MONO 0
#define SH_FSI_FMT_MONO_DELAY 1
#define SH_FSI_FMT_PCM 2
#define SH_FSI_FMT_I2S 3
#define SH_FSI_FMT_TDM 4
#define SH_FSI_FMT_TDM_DELAY 5
#define SH_FSI_FMT_SPDIF 6
#define SH_FSI_IFMT_TDM_CH(x) \
(SH_FSI_IFMT(TDM) | SH_FSI_SET_CH_I(x))
#define SH_FSI_IFMT_TDM_DELAY_CH(x) \
(SH_FSI_IFMT(TDM_DELAY) | SH_FSI_SET_CH_I(x))
/*
* flags format
*
* 0x000000BA
*
* A: inversion
* B: format mode
*/
#define SH_FSI_OFMT_TDM_CH(x) \
(SH_FSI_OFMT(TDM) | SH_FSI_SET_CH_O(x))
#define SH_FSI_OFMT_TDM_DELAY_CH(x) \
(SH_FSI_OFMT(TDM_DELAY) | SH_FSI_SET_CH_O(x))
/* A: clock inversion */
#define SH_FSI_INVERSION_MASK 0x0000000F
#define SH_FSI_LRM_INV (1 << 0)
#define SH_FSI_BRM_INV (1 << 1)
#define SH_FSI_LRS_INV (1 << 2)
#define SH_FSI_BRS_INV (1 << 3)
/* B: format mode */
#define SH_FSI_FMT_MASK 0x000000F0
#define SH_FSI_FMT_DAI (0 << 4)
#define SH_FSI_FMT_SPDIF (1 << 4)
/*
......
......@@ -157,6 +157,18 @@
.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1, \
.event = wevent, .event_flags = wflags}
/* additional sequencing control within an event type */
#define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \
wevent, wflags) \
{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .event = wevent, .event_flags = wflags, \
.subseq = wsubseq}
#define SND_SOC_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, winvert, wevent, \
wflags) \
{ .id = snd_soc_dapm_supply, .name = wname, .reg = wreg, \
.shift = wshift, .invert = winvert, .event = wevent, \
.event_flags = wflags, .subseq = wsubseq}
/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
#define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
wevent, wflags) \
......@@ -450,6 +462,7 @@ struct snd_soc_dapm_widget {
unsigned char ext:1; /* has external widgets */
unsigned char force:1; /* force state */
unsigned char ignore_suspend:1; /* kept enabled over suspend */
int subseq; /* sort within widget type */
int (*power_check)(struct snd_soc_dapm_widget *w);
......@@ -487,6 +500,9 @@ struct snd_soc_dapm_context {
struct snd_soc_dapm_update *update;
void (*seq_notifier)(struct snd_soc_dapm_context *,
enum snd_soc_dapm_type, int);
struct device *dev; /* from parent - for debug */
struct snd_soc_codec *codec; /* parent codec */
struct snd_soc_card *card; /* parent card */
......
......@@ -234,6 +234,7 @@ struct snd_soc_codec;
struct snd_soc_codec_driver;
struct soc_enum;
struct snd_soc_jack;
struct snd_soc_jack_zone;
struct snd_soc_jack_pin;
struct snd_soc_cache_ops;
#include <sound/soc-dapm.h>
......@@ -258,6 +259,16 @@ enum snd_soc_compress_type {
SND_SOC_RBTREE_COMPRESSION
};
int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id,
unsigned int freq, int dir);
int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
unsigned int freq_in, unsigned int freq_out);
int snd_soc_register_card(struct snd_soc_card *card);
int snd_soc_unregister_card(struct snd_soc_card *card);
int snd_soc_suspend(struct device *dev);
int snd_soc_resume(struct device *dev);
int snd_soc_poweroff(struct device *dev);
int snd_soc_register_platform(struct device *dev,
struct snd_soc_platform_driver *platform_drv);
void snd_soc_unregister_platform(struct device *dev);
......@@ -265,7 +276,8 @@ int snd_soc_register_codec(struct device *dev,
const struct snd_soc_codec_driver *codec_drv,
struct snd_soc_dai_driver *dai_drv, int num_dai);
void snd_soc_unregister_codec(struct device *dev);
int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg);
int snd_soc_codec_volatile_register(struct snd_soc_codec *codec,
unsigned int reg);
int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
int addr_bits, int data_bits,
enum snd_soc_control_type control);
......@@ -276,6 +288,10 @@ int snd_soc_cache_write(struct snd_soc_codec *codec,
unsigned int reg, unsigned int value);
int snd_soc_cache_read(struct snd_soc_codec *codec,
unsigned int reg, unsigned int *value);
int snd_soc_default_volatile_register(struct snd_soc_codec *codec,
unsigned int reg);
int snd_soc_default_readable_register(struct snd_soc_codec *codec,
unsigned int reg);
/* Utility functions to get clock rates from various things */
int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
......@@ -297,6 +313,9 @@ void snd_soc_jack_notifier_register(struct snd_soc_jack *jack,
struct notifier_block *nb);
void snd_soc_jack_notifier_unregister(struct snd_soc_jack *jack,
struct notifier_block *nb);
int snd_soc_jack_add_zones(struct snd_soc_jack *jack, int count,
struct snd_soc_jack_zone *zones);
int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage);
#ifdef CONFIG_GPIOLIB
int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
struct snd_soc_jack_gpio *gpios);
......@@ -321,7 +340,8 @@ void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);
*Controls
*/
struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
void *data, char *long_name);
void *data, char *long_name,
const char *prefix);
int snd_soc_add_controls(struct snd_soc_codec *codec,
const struct snd_kcontrol_new *controls, int num_controls);
int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
......@@ -366,6 +386,22 @@ int snd_soc_get_volsw_2r_sx(struct snd_kcontrol *kcontrol,
int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
/**
* struct snd_soc_reg_access - Describes whether a given register is
* readable, writable or volatile.
*
* @reg: the register number
* @read: whether this register is readable
* @write: whether this register is writable
* @vol: whether this register is volatile
*/
struct snd_soc_reg_access {
u16 reg;
u16 read;
u16 write;
u16 vol;
};
/**
* struct snd_soc_jack_pin - Describes a pin to update based on jack detection
*
......@@ -380,6 +416,24 @@ struct snd_soc_jack_pin {
bool invert;
};
/**
* struct snd_soc_jack_zone - Describes voltage zones of jack detection
*
* @min_mv: start voltage in mv
* @max_mv: end voltage in mv
* @jack_type: type of jack that is expected for this voltage
* @debounce_time: debounce_time for jack, codec driver should wait for this
* duration before reading the adc for voltages
* @:list: list container
*/
struct snd_soc_jack_zone {
unsigned int min_mv;
unsigned int max_mv;
unsigned int jack_type;
unsigned int debounce_time;
struct list_head list;
};
/**
* struct snd_soc_jack_gpio - Describes a gpio pin for jack detection
*
......@@ -388,6 +442,10 @@ struct snd_soc_jack_pin {
* @report: value to report when jack detected
* @invert: report presence in low state
* @debouce_time: debouce time in ms
* @wake: enable as wake source
* @jack_status_check: callback function which overrides the detection
* to provide more complex checks (eg, reading an
* ADC).
*/
#ifdef CONFIG_GPIOLIB
struct snd_soc_jack_gpio {
......@@ -396,6 +454,8 @@ struct snd_soc_jack_gpio {
int report;
int invert;
int debounce_time;
bool wake;
struct snd_soc_jack *jack;
struct delayed_work work;
......@@ -409,6 +469,7 @@ struct snd_soc_jack {
struct list_head pins;
int status;
struct blocking_notifier_head notifier;
struct list_head jack_zones;
};
/* SoC PCM stream information */
......@@ -459,18 +520,22 @@ struct snd_soc_codec {
struct list_head card_list;
int num_dai;
enum snd_soc_compress_type compress_type;
size_t reg_size; /* reg_cache_size * reg_word_size */
int (*volatile_register)(struct snd_soc_codec *, unsigned int);
int (*readable_register)(struct snd_soc_codec *, unsigned int);
/* runtime */
struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */
unsigned int active;
unsigned int cache_only:1; /* Suppress writes to hardware */
unsigned int cache_sync:1; /* Cache needs to be synced to hardware */
unsigned int cache_bypass:1; /* Suppress access to the cache */
unsigned int suspended:1; /* Codec is in suspend PM state */
unsigned int probed:1; /* Codec has been probed */
unsigned int ac97_registered:1; /* Codec has been AC97 registered */
unsigned int ac97_created:1; /* Codec has been created by SoC */
unsigned int sysfs_registered:1; /* codec has been sysfs registered */
unsigned int cache_init:1; /* codec cache has been initialized */
u32 cache_only; /* Suppress writes to hardware */
u32 cache_sync; /* Cache needs to be synced to hardware */
/* codec IO */
void *control_data; /* codec control (i2c/3wire) data */
......@@ -503,22 +568,39 @@ struct snd_soc_codec_driver {
pm_message_t state);
int (*resume)(struct snd_soc_codec *);
/* Default DAPM setup, added after probe() is run */
const struct snd_soc_dapm_widget *dapm_widgets;
int num_dapm_widgets;
const struct snd_soc_dapm_route *dapm_routes;
int num_dapm_routes;
/* codec wide operations */
int (*set_sysclk)(struct snd_soc_codec *codec,
int clk_id, unsigned int freq, int dir);
int (*set_pll)(struct snd_soc_codec *codec, int pll_id, int source,
unsigned int freq_in, unsigned int freq_out);
/* codec IO */
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
int (*display_register)(struct snd_soc_codec *, char *,
size_t, unsigned int);
int (*volatile_register)(unsigned int);
int (*readable_register)(unsigned int);
int (*volatile_register)(struct snd_soc_codec *, unsigned int);
int (*readable_register)(struct snd_soc_codec *, unsigned int);
short reg_cache_size;
short reg_cache_step;
short reg_word_size;
const void *reg_cache_default;
short reg_access_size;
const struct snd_soc_reg_access *reg_access_default;
enum snd_soc_compress_type compress_type;
/* codec bias level */
int (*set_bias_level)(struct snd_soc_codec *,
enum snd_soc_bias_level level);
void (*seq_notifier)(struct snd_soc_dapm_context *,
enum snd_soc_dapm_type, int);
};
/* SoC platform interface */
......@@ -617,15 +699,16 @@ struct snd_soc_card {
bool instantiated;
int (*probe)(struct platform_device *pdev);
int (*remove)(struct platform_device *pdev);
int (*probe)(struct snd_soc_card *card);
int (*late_probe)(struct snd_soc_card *card);
int (*remove)(struct snd_soc_card *card);
/* the pre and post PM functions are used to do any PM work before and
* after the codec and DAI's do any PM work. */
int (*suspend_pre)(struct platform_device *pdev, pm_message_t state);
int (*suspend_post)(struct platform_device *pdev, pm_message_t state);
int (*resume_pre)(struct platform_device *pdev);
int (*resume_post)(struct platform_device *pdev);
int (*suspend_pre)(struct snd_soc_card *card);
int (*suspend_post)(struct snd_soc_card *card);
int (*resume_pre)(struct snd_soc_card *card);
int (*resume_post)(struct snd_soc_card *card);
/* callbacks */
int (*set_bias_level)(struct snd_soc_card *,
......@@ -654,6 +737,14 @@ struct snd_soc_card {
struct snd_soc_pcm_runtime *rtd_aux;
int num_aux_rtd;
/*
* Card-specific routes and widgets.
*/
struct snd_soc_dapm_widget *dapm_widgets;
int num_dapm_widgets;
struct snd_soc_dapm_route *dapm_routes;
int num_dapm_routes;
struct work_struct deferred_resume_work;
/* lists of probed devices belonging to this card */
......@@ -665,11 +756,16 @@ struct snd_soc_card {
struct list_head paths;
struct list_head dapm_list;
/* Generic DAPM context for the card */
struct snd_soc_dapm_context dapm;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_card_root;
struct dentry *debugfs_pop_time;
#endif
u32 pop_time;
void *drvdata;
};
/* SoC machine DAI configuration, glues a codec and cpu DAI together */
......@@ -721,6 +817,17 @@ unsigned int snd_soc_write(struct snd_soc_codec *codec,
/* device driver data */
static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card,
void *data)
{
card->drvdata = data;
}
static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card)
{
return card->drvdata;
}
static inline void snd_soc_codec_set_drvdata(struct snd_soc_codec *codec,
void *data)
{
......@@ -754,6 +861,22 @@ static inline void *snd_soc_pcm_get_drvdata(struct snd_soc_pcm_runtime *rtd)
return dev_get_drvdata(&rtd->dev);
}
static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card)
{
INIT_LIST_HEAD(&card->dai_dev_list);
INIT_LIST_HEAD(&card->codec_dev_list);
INIT_LIST_HEAD(&card->platform_dev_list);
INIT_LIST_HEAD(&card->widgets);
INIT_LIST_HEAD(&card->paths);
INIT_LIST_HEAD(&card->dapm_list);
}
#include <sound/soc-dai.h>
#ifdef CONFIG_DEBUG_FS
extern struct dentry *snd_soc_debugfs_root;
#endif
extern const struct dev_pm_ops snd_soc_pm_ops;
#endif
/*
* tlv320aic32x4.h -- TLV320AIC32X4 Soc Audio driver platform data
*
* Copyright 2011 Vista Silicon S.L.
*
* Author: Javier Martin <javier.martin@vista-silicon.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _AIC32X4_PDATA_H
#define _AIC32X4_PDATA_H
#define AIC32X4_PWR_MICBIAS_2075_LDOIN 0x00000001
#define AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE 0x00000002
#define AIC32X4_PWR_AIC32X4_LDO_ENABLE 0x00000004
#define AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36 0x00000008
#define AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED 0x00000010
#define AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K 0x00000001
#define AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K 0x00000002
struct aic32x4_pdata {
u32 power_cfg;
u32 micpga_routing;
bool swapdacs;
};
#endif
......@@ -32,6 +32,21 @@
#define WM8903_MICBIAS_ENA_SHIFT 0 /* MICBIAS_ENA */
#define WM8903_MICBIAS_ENA_WIDTH 1 /* MICBIAS_ENA */
/*
* WM8903_GPn_FN values
*
* See datasheets for list of valid values per pin
*/
#define WM8903_GPn_FN_GPIO_OUTPUT 0
#define WM8903_GPn_FN_BCLK 1
#define WM8903_GPn_FN_IRQ_OUTPT 2
#define WM8903_GPn_FN_GPIO_INPUT 3
#define WM8903_GPn_FN_MICBIAS_CURRENT_DETECT 4
#define WM8903_GPn_FN_MICBIAS_SHORT_DETECT 5
#define WM8903_GPn_FN_DMIC_LR_CLK_OUTPUT 6
#define WM8903_GPn_FN_FLL_LOCK_OUTPUT 8
#define WM8903_GPn_FN_FLL_CLOCK_OUTPUT 9
/*
* R116 (0x74) - GPIO Control 1
*/
......@@ -227,6 +242,8 @@
#define WM8903_GP5_DB_SHIFT 0 /* GP5_DB */
#define WM8903_GP5_DB_WIDTH 1 /* GP5_DB */
#define WM8903_NUM_GPIO 5
struct wm8903_platform_data {
bool irq_active_low; /* Set if IRQ active low, default high */
......@@ -239,7 +256,8 @@ struct wm8903_platform_data {
int micdet_delay; /* Delay after microphone detection (ms) */
u32 gpio_cfg[5]; /* Default register values for GPIO pin mux */
int gpio_base;
u32 gpio_cfg[WM8903_NUM_GPIO]; /* Default register values for GPIO pin mux */
};
#endif
......@@ -17,9 +17,12 @@ struct wm9081_retune_mobile_setting {
u16 config[20];
};
struct wm9081_retune_mobile_config {
struct wm9081_retune_mobile_setting *configs;
int num_configs;
struct wm9081_pdata {
bool irq_high; /* IRQ is active high */
bool irq_cmos; /* IRQ is in CMOS mode */
struct wm9081_retune_mobile_setting *retune_configs;
int num_retune_configs;
};
#endif
......@@ -229,6 +229,31 @@ TRACE_EVENT(snd_soc_jack_notify,
TP_printk("jack=%s %x", __get_str(name), (int)__entry->val)
);
TRACE_EVENT(snd_soc_cache_sync,
TP_PROTO(struct snd_soc_codec *codec, const char *type,
const char *status),
TP_ARGS(codec, type, status),
TP_STRUCT__entry(
__string( name, codec->name )
__string( status, status )
__string( type, type )
__field( int, id )
),
TP_fast_assign(
__assign_str(name, codec->name);
__assign_str(status, status);
__assign_str(type, type);
__entry->id = codec->id;
),
TP_printk("codec=%s.%d type=%s status=%s", __get_str(name),
(int)__entry->id, __get_str(type), __get_str(status))
);
#endif /* _TRACE_ASOC_H */
/* This part must be outside protection */
......
......@@ -465,6 +465,52 @@ static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file,
return ret;
}
/**
* snd_ctl_activate_id - activate/inactivate the control of the given id
* @card: the card instance
* @id: the control id to activate/inactivate
* @active: non-zero to activate
*
* Finds the control instance with the given id, and activate or
* inactivate the control together with notification, if changed.
*
* Returns 0 if unchanged, 1 if changed, or a negative error code on failure.
*/
int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
int active)
{
struct snd_kcontrol *kctl;
struct snd_kcontrol_volatile *vd;
unsigned int index_offset;
int ret;
down_write(&card->controls_rwsem);
kctl = snd_ctl_find_id(card, id);
if (kctl == NULL) {
ret = -ENOENT;
goto unlock;
}
index_offset = snd_ctl_get_ioff(kctl, &kctl->id);
vd = &kctl->vd[index_offset];
ret = 0;
if (active) {
if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE))
goto unlock;
vd->access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
} else {
if (vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE)
goto unlock;
vd->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
}
ret = 1;
unlock:
up_write(&card->controls_rwsem);
if (ret > 0)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, id);
return ret;
}
EXPORT_SYMBOL_GPL(snd_ctl_activate_id);
/**
* snd_ctl_rename_id - replace the id of a control on the card
* @card: the card instance
......
......@@ -50,10 +50,12 @@ source "sound/soc/jz4740/Kconfig"
source "sound/soc/nuc900/Kconfig"
source "sound/soc/omap/Kconfig"
source "sound/soc/kirkwood/Kconfig"
source "sound/soc/mid-x86/Kconfig"
source "sound/soc/pxa/Kconfig"
source "sound/soc/samsung/Kconfig"
source "sound/soc/s6000/Kconfig"
source "sound/soc/sh/Kconfig"
source "sound/soc/tegra/Kconfig"
source "sound/soc/txx9/Kconfig"
# Supported codecs
......
......@@ -10,6 +10,7 @@ obj-$(CONFIG_SND_SOC) += ep93xx/
obj-$(CONFIG_SND_SOC) += fsl/
obj-$(CONFIG_SND_SOC) += imx/
obj-$(CONFIG_SND_SOC) += jz4740/
obj-$(CONFIG_SND_SOC) += mid-x86/
obj-$(CONFIG_SND_SOC) += nuc900/
obj-$(CONFIG_SND_SOC) += omap/
obj-$(CONFIG_SND_SOC) += kirkwood/
......@@ -17,4 +18,5 @@ obj-$(CONFIG_SND_SOC) += pxa/
obj-$(CONFIG_SND_SOC) += samsung/
obj-$(CONFIG_SND_SOC) += s6000/
obj-$(CONFIG_SND_SOC) += sh/
obj-$(CONFIG_SND_SOC) += tegra/
obj-$(CONFIG_SND_SOC) += txx9/
......@@ -26,17 +26,24 @@ config SND_SOC_ALL_CODECS
select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
select SND_SOC_CS42L51 if I2C
select SND_SOC_CS4270 if I2C
select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
select SND_SOC_CX20442
select SND_SOC_DA7210 if I2C
select SND_SOC_DFBMCS320
select SND_SOC_JZ4740_CODEC if SOC_JZ4740
select SND_SOC_LM4857 if I2C
select SND_SOC_MAX98088 if I2C
select SND_SOC_MAX9850 if I2C
select SND_SOC_MAX9877 if I2C
select SND_SOC_PCM3008
select SND_SOC_SGTL5000 if I2C
select SND_SOC_SN95031 if INTEL_SCU_IPC
select SND_SOC_SPDIF
select SND_SOC_SSM2602 if I2C
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
select SND_SOC_TLV320AIC23 if I2C
select SND_SOC_TLV320AIC26 if SPI_MASTER
select SND_SOC_TVL320AIC32X4 if I2C
select SND_SOC_TLV320AIC3X if I2C
select SND_SOC_TPA6130A2 if I2C
select SND_SOC_TLV320DAC33 if I2C
......@@ -76,6 +83,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_WM8985 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8990 if I2C
select SND_SOC_WM8991 if I2C
select SND_SOC_WM8993 if I2C
select SND_SOC_WM8994 if MFD_WM8994
select SND_SOC_WM8995 if SND_SOC_I2C_AND_SPI
......@@ -155,6 +163,9 @@ config SND_SOC_CS4270_VD33_ERRATA
bool
depends on SND_SOC_CS4270
config SND_SOC_CS4271
tristate
config SND_SOC_CX20442
tristate
......@@ -167,15 +178,28 @@ config SND_SOC_L3
config SND_SOC_DA7210
tristate
config SND_SOC_DFBMCS320
tristate
config SND_SOC_DMIC
tristate
config SND_SOC_MAX98088
tristate
config SND_SOC_MAX9850
tristate
config SND_SOC_PCM3008
tristate
#Freescale sgtl5000 codec
config SND_SOC_SGTL5000
tristate
config SND_SOC_SN95031
tristate
config SND_SOC_SPDIF
tristate
......@@ -192,6 +216,9 @@ config SND_SOC_TLV320AIC26
tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE
depends on SPI
config SND_SOC_TVL320AIC32X4
tristate
config SND_SOC_TLV320AIC3X
tristate
......@@ -304,6 +331,9 @@ config SND_SOC_WM8988
config SND_SOC_WM8990
tristate
config SND_SOC_WM8991
tristate
config SND_SOC_WM8993
tristate
......@@ -326,6 +356,9 @@ config SND_SOC_WM9713
tristate
# Amp
config SND_SOC_LM4857
tristate
config SND_SOC_MAX9877
tristate
......@@ -337,4 +370,3 @@ config SND_SOC_WM2000
config SND_SOC_WM9090
tristate
......@@ -12,19 +12,25 @@ snd-soc-ak4671-objs := ak4671.o
snd-soc-cq93vc-objs := cq93vc.o
snd-soc-cs42l51-objs := cs42l51.o
snd-soc-cs4270-objs := cs4270.o
snd-soc-cs4271-objs := cs4271.o
snd-soc-cx20442-objs := cx20442.o
snd-soc-da7210-objs := da7210.o
snd-soc-dfbmcs320-objs := dfbmcs320.o
snd-soc-dmic-objs := dmic.o
snd-soc-l3-objs := l3.o
snd-soc-max98088-objs := max98088.o
snd-soc-max9850-objs := max9850.o
snd-soc-pcm3008-objs := pcm3008.o
snd-soc-sgtl5000-objs := sgtl5000.o
snd-soc-alc5623-objs := alc5623.o
snd-soc-sn95031-objs := sn95031.o
snd-soc-spdif-objs := spdif_transciever.o
snd-soc-ssm2602-objs := ssm2602.o
snd-soc-stac9766-objs := stac9766.o
snd-soc-tlv320aic23-objs := tlv320aic23.o
snd-soc-tlv320aic26-objs := tlv320aic26.o
snd-soc-tlv320aic3x-objs := tlv320aic3x.o
snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o
snd-soc-tlv320dac33-objs := tlv320dac33.o
snd-soc-twl4030-objs := twl4030.o
snd-soc-twl6040-objs := twl6040.o
......@@ -61,6 +67,7 @@ snd-soc-wm8978-objs := wm8978.o
snd-soc-wm8985-objs := wm8985.o
snd-soc-wm8988-objs := wm8988.o
snd-soc-wm8990-objs := wm8990.o
snd-soc-wm8991-objs := wm8991.o
snd-soc-wm8993-objs := wm8993.o
snd-soc-wm8994-objs := wm8994.o wm8994-tables.o
snd-soc-wm8995-objs := wm8995.o
......@@ -72,6 +79,7 @@ snd-soc-wm-hubs-objs := wm_hubs.o
snd-soc-jz4740-codec-objs := jz4740.o
# Amp
snd-soc-lm4857-objs := lm4857.o
snd-soc-max9877-objs := max9877.o
snd-soc-tpa6130a2-objs := tpa6130a2.o
snd-soc-wm2000-objs := wm2000.o
......@@ -88,23 +96,29 @@ obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o
obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o
obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o
obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o
obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o
obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o
obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o
obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o
obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o
obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o
obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
obj-$(CONFIG_SND_SOC_TVL320AIC32X4) += snd-soc-tlv320aic32x4.o
obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o
obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
......@@ -141,6 +155,7 @@ obj-$(CONFIG_SND_SOC_WM8978) += snd-soc-wm8978.o
obj-$(CONFIG_SND_SOC_WM8985) += snd-soc-wm8985.o
obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o
obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o
obj-$(CONFIG_SND_SOC_WM8991) += snd-soc-wm8991.o
obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o
obj-$(CONFIG_SND_SOC_WM8994) += snd-soc-wm8994.o
obj-$(CONFIG_SND_SOC_WM8995) += snd-soc-wm8995.o
......@@ -151,6 +166,7 @@ obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o
obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o
# Amp
obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o
obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o
......
......@@ -294,7 +294,6 @@ static struct spi_driver ak4104_spi_driver = {
static int __init ak4104_init(void)
{
pr_info("Asahi Kasei AK4104 ALSA SoC Codec Driver\n");
return spi_register_driver(&ak4104_spi_driver);
}
module_init(ak4104_init);
......
......@@ -116,6 +116,12 @@
#define BCKO_MASK (1 << 3)
#define BCKO_64 BCKO_MASK
#define DIF_MASK (3 << 0)
#define DSP (0 << 0)
#define RIGHT_J (1 << 0)
#define LEFT_J (2 << 0)
#define I2S (3 << 0)
/* MD_CTL2 */
#define FS0 (1 << 0)
#define FS1 (1 << 1)
......@@ -354,6 +360,24 @@ static int ak4642_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
snd_soc_update_bits(codec, PW_MGMT2, MS, data);
snd_soc_update_bits(codec, MD_CTL1, BCKO_MASK, bcko);
/* format type */
data = 0;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_LEFT_J:
data = LEFT_J;
break;
case SND_SOC_DAIFMT_I2S:
data = I2S;
break;
/* FIXME
* Please add RIGHT_J / DSP support here
*/
default:
return -EINVAL;
break;
}
snd_soc_update_bits(codec, MD_CTL1, DIF_MASK, data);
return 0;
}
......
......@@ -193,12 +193,12 @@ static struct cs4270_mode_ratios cs4270_mode_ratios[] = {
/* The number of MCLK/LRCK ratios supported by the CS4270 */
#define NUM_MCLK_RATIOS ARRAY_SIZE(cs4270_mode_ratios)
static int cs4270_reg_is_readable(unsigned int reg)
static int cs4270_reg_is_readable(struct snd_soc_codec *codec, unsigned int reg)
{
return (reg >= CS4270_FIRSTREG) && (reg <= CS4270_LASTREG);
}
static int cs4270_reg_is_volatile(unsigned int reg)
static int cs4270_reg_is_volatile(struct snd_soc_codec *codec, unsigned int reg)
{
/* Unreadable registers are considered volatile */
if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG))
......@@ -719,7 +719,7 @@ static int cs4270_i2c_remove(struct i2c_client *i2c_client)
/*
* cs4270_id - I2C device IDs supported by this driver
*/
static struct i2c_device_id cs4270_id[] = {
static const struct i2c_device_id cs4270_id[] = {
{"cs4270", 0},
{}
};
......@@ -743,8 +743,6 @@ static struct i2c_driver cs4270_i2c_driver = {
static int __init cs4270_init(void)
{
pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n");
return i2c_add_driver(&cs4270_i2c_driver);
}
module_init(cs4270_init);
......
/*
* CS4271 ASoC codec driver
*
* Copyright (c) 2010 Alexander Sverdlin <subaparts@yandex.ru>
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This driver support CS4271 codec being master or slave, working
* in control port mode, connected either via SPI or I2C.
* The data format accepted is I2S or left-justified.
* DAPM support not implemented.
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <sound/cs4271.h>
#define CS4271_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE)
#define CS4271_PCM_RATES SNDRV_PCM_RATE_8000_192000
/*
* CS4271 registers
* High byte represents SPI chip address (0x10) + write command (0)
* Low byte - codec register address
*/
#define CS4271_MODE1 0x2001 /* Mode Control 1 */
#define CS4271_DACCTL 0x2002 /* DAC Control */
#define CS4271_DACVOL 0x2003 /* DAC Volume & Mixing Control */
#define CS4271_VOLA 0x2004 /* DAC Channel A Volume Control */
#define CS4271_VOLB 0x2005 /* DAC Channel B Volume Control */
#define CS4271_ADCCTL 0x2006 /* ADC Control */
#define CS4271_MODE2 0x2007 /* Mode Control 2 */
#define CS4271_CHIPID 0x2008 /* Chip ID */
#define CS4271_FIRSTREG CS4271_MODE1
#define CS4271_LASTREG CS4271_MODE2
#define CS4271_NR_REGS ((CS4271_LASTREG & 0xFF) + 1)
/* Bit masks for the CS4271 registers */
#define CS4271_MODE1_MODE_MASK 0xC0
#define CS4271_MODE1_MODE_1X 0x00
#define CS4271_MODE1_MODE_2X 0x80
#define CS4271_MODE1_MODE_4X 0xC0
#define CS4271_MODE1_DIV_MASK 0x30
#define CS4271_MODE1_DIV_1 0x00
#define CS4271_MODE1_DIV_15 0x10
#define CS4271_MODE1_DIV_2 0x20
#define CS4271_MODE1_DIV_3 0x30
#define CS4271_MODE1_MASTER 0x08
#define CS4271_MODE1_DAC_DIF_MASK 0x07
#define CS4271_MODE1_DAC_DIF_LJ 0x00
#define CS4271_MODE1_DAC_DIF_I2S 0x01
#define CS4271_MODE1_DAC_DIF_RJ16 0x02
#define CS4271_MODE1_DAC_DIF_RJ24 0x03
#define CS4271_MODE1_DAC_DIF_RJ20 0x04
#define CS4271_MODE1_DAC_DIF_RJ18 0x05
#define CS4271_DACCTL_AMUTE 0x80
#define CS4271_DACCTL_IF_SLOW 0x40
#define CS4271_DACCTL_DEM_MASK 0x30
#define CS4271_DACCTL_DEM_DIS 0x00
#define CS4271_DACCTL_DEM_441 0x10
#define CS4271_DACCTL_DEM_48 0x20
#define CS4271_DACCTL_DEM_32 0x30
#define CS4271_DACCTL_SVRU 0x08
#define CS4271_DACCTL_SRD 0x04
#define CS4271_DACCTL_INVA 0x02
#define CS4271_DACCTL_INVB 0x01
#define CS4271_DACVOL_BEQUA 0x40
#define CS4271_DACVOL_SOFT 0x20
#define CS4271_DACVOL_ZEROC 0x10
#define CS4271_DACVOL_ATAPI_MASK 0x0F
#define CS4271_DACVOL_ATAPI_M_M 0x00
#define CS4271_DACVOL_ATAPI_M_BR 0x01
#define CS4271_DACVOL_ATAPI_M_BL 0x02
#define CS4271_DACVOL_ATAPI_M_BLR2 0x03
#define CS4271_DACVOL_ATAPI_AR_M 0x04
#define CS4271_DACVOL_ATAPI_AR_BR 0x05
#define CS4271_DACVOL_ATAPI_AR_BL 0x06
#define CS4271_DACVOL_ATAPI_AR_BLR2 0x07
#define CS4271_DACVOL_ATAPI_AL_M 0x08
#define CS4271_DACVOL_ATAPI_AL_BR 0x09
#define CS4271_DACVOL_ATAPI_AL_BL 0x0A
#define CS4271_DACVOL_ATAPI_AL_BLR2 0x0B
#define CS4271_DACVOL_ATAPI_ALR2_M 0x0C
#define CS4271_DACVOL_ATAPI_ALR2_BR 0x0D
#define CS4271_DACVOL_ATAPI_ALR2_BL 0x0E
#define CS4271_DACVOL_ATAPI_ALR2_BLR2 0x0F
#define CS4271_VOLA_MUTE 0x80
#define CS4271_VOLA_VOL_MASK 0x7F
#define CS4271_VOLB_MUTE 0x80
#define CS4271_VOLB_VOL_MASK 0x7F
#define CS4271_ADCCTL_DITHER16 0x20
#define CS4271_ADCCTL_ADC_DIF_MASK 0x10
#define CS4271_ADCCTL_ADC_DIF_LJ 0x00
#define CS4271_ADCCTL_ADC_DIF_I2S 0x10
#define CS4271_ADCCTL_MUTEA 0x08
#define CS4271_ADCCTL_MUTEB 0x04
#define CS4271_ADCCTL_HPFDA 0x02
#define CS4271_ADCCTL_HPFDB 0x01
#define CS4271_MODE2_LOOP 0x10
#define CS4271_MODE2_MUTECAEQUB 0x08
#define CS4271_MODE2_FREEZE 0x04
#define CS4271_MODE2_CPEN 0x02
#define CS4271_MODE2_PDN 0x01
#define CS4271_CHIPID_PART_MASK 0xF0
#define CS4271_CHIPID_REV_MASK 0x0F
/*
* Default CS4271 power-up configuration
* Array contains non-existing in hw register at address 0
* Array do not include Chip ID, as codec driver does not use
* registers read operations at all
*/
static const u8 cs4271_dflt_reg[CS4271_NR_REGS] = {
0,
0,
CS4271_DACCTL_AMUTE,
CS4271_DACVOL_SOFT | CS4271_DACVOL_ATAPI_AL_BR,
0,
0,
0,
0,
};
struct cs4271_private {
/* SND_SOC_I2C or SND_SOC_SPI */
enum snd_soc_control_type bus_type;
void *control_data;
unsigned int mclk;
bool master;
bool deemph;
/* Current sample rate for de-emphasis control */
int rate;
/* GPIO driving Reset pin, if any */
int gpio_nreset;
/* GPIO that disable serial bus, if any */
int gpio_disable;
};
/*
* @freq is the desired MCLK rate
* MCLK rate should (c) be the sample rate, multiplied by one of the
* ratios listed in cs4271_mclk_fs_ratios table
*/
static int cs4271_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_codec *codec = codec_dai->codec;
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
cs4271->mclk = freq;
return 0;
}
static int cs4271_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int format)
{
struct snd_soc_codec *codec = codec_dai->codec;
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
unsigned int val = 0;
int ret;
switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
cs4271->master = 0;
break;
case SND_SOC_DAIFMT_CBM_CFM:
cs4271->master = 1;
val |= CS4271_MODE1_MASTER;
break;
default:
dev_err(codec->dev, "Invalid DAI format\n");
return -EINVAL;
}
switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_LEFT_J:
val |= CS4271_MODE1_DAC_DIF_LJ;
ret = snd_soc_update_bits(codec, CS4271_ADCCTL,
CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_LJ);
if (ret < 0)
return ret;
break;
case SND_SOC_DAIFMT_I2S:
val |= CS4271_MODE1_DAC_DIF_I2S;
ret = snd_soc_update_bits(codec, CS4271_ADCCTL,
CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_I2S);
if (ret < 0)
return ret;
break;
default:
dev_err(codec->dev, "Invalid DAI format\n");
return -EINVAL;
}
ret = snd_soc_update_bits(codec, CS4271_MODE1,
CS4271_MODE1_DAC_DIF_MASK | CS4271_MODE1_MASTER, val);
if (ret < 0)
return ret;
return 0;
}
static int cs4271_deemph[] = {0, 44100, 48000, 32000};
static int cs4271_set_deemph(struct snd_soc_codec *codec)
{
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
int i, ret;
int val = CS4271_DACCTL_DEM_DIS;
if (cs4271->deemph) {
/* Find closest de-emphasis freq */
val = 1;
for (i = 2; i < ARRAY_SIZE(cs4271_deemph); i++)
if (abs(cs4271_deemph[i] - cs4271->rate) <
abs(cs4271_deemph[val] - cs4271->rate))
val = i;
val <<= 4;
}
ret = snd_soc_update_bits(codec, CS4271_DACCTL,
CS4271_DACCTL_DEM_MASK, val);
if (ret < 0)
return ret;
return 0;
}
static int cs4271_get_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = cs4271->deemph;
return 0;
}
static int cs4271_put_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
cs4271->deemph = ucontrol->value.enumerated.item[0];
return cs4271_set_deemph(codec);
}
struct cs4271_clk_cfg {
bool master; /* codec mode */
u8 speed_mode; /* codec speed mode: 1x, 2x, 4x */
unsigned short ratio; /* MCLK / sample rate */
u8 ratio_mask; /* ratio bit mask for Master mode */
};
static struct cs4271_clk_cfg cs4271_clk_tab[] = {
{1, CS4271_MODE1_MODE_1X, 256, CS4271_MODE1_DIV_1},
{1, CS4271_MODE1_MODE_1X, 384, CS4271_MODE1_DIV_15},
{1, CS4271_MODE1_MODE_1X, 512, CS4271_MODE1_DIV_2},
{1, CS4271_MODE1_MODE_1X, 768, CS4271_MODE1_DIV_3},
{1, CS4271_MODE1_MODE_2X, 128, CS4271_MODE1_DIV_1},
{1, CS4271_MODE1_MODE_2X, 192, CS4271_MODE1_DIV_15},
{1, CS4271_MODE1_MODE_2X, 256, CS4271_MODE1_DIV_2},
{1, CS4271_MODE1_MODE_2X, 384, CS4271_MODE1_DIV_3},
{1, CS4271_MODE1_MODE_4X, 64, CS4271_MODE1_DIV_1},
{1, CS4271_MODE1_MODE_4X, 96, CS4271_MODE1_DIV_15},
{1, CS4271_MODE1_MODE_4X, 128, CS4271_MODE1_DIV_2},
{1, CS4271_MODE1_MODE_4X, 192, CS4271_MODE1_DIV_3},
{0, CS4271_MODE1_MODE_1X, 256, CS4271_MODE1_DIV_1},
{0, CS4271_MODE1_MODE_1X, 384, CS4271_MODE1_DIV_1},
{0, CS4271_MODE1_MODE_1X, 512, CS4271_MODE1_DIV_1},
{0, CS4271_MODE1_MODE_1X, 768, CS4271_MODE1_DIV_2},
{0, CS4271_MODE1_MODE_1X, 1024, CS4271_MODE1_DIV_2},
{0, CS4271_MODE1_MODE_2X, 128, CS4271_MODE1_DIV_1},
{0, CS4271_MODE1_MODE_2X, 192, CS4271_MODE1_DIV_1},
{0, CS4271_MODE1_MODE_2X, 256, CS4271_MODE1_DIV_1},
{0, CS4271_MODE1_MODE_2X, 384, CS4271_MODE1_DIV_2},
{0, CS4271_MODE1_MODE_2X, 512, CS4271_MODE1_DIV_2},
{0, CS4271_MODE1_MODE_4X, 64, CS4271_MODE1_DIV_1},
{0, CS4271_MODE1_MODE_4X, 96, CS4271_MODE1_DIV_1},
{0, CS4271_MODE1_MODE_4X, 128, CS4271_MODE1_DIV_1},
{0, CS4271_MODE1_MODE_4X, 192, CS4271_MODE1_DIV_2},
{0, CS4271_MODE1_MODE_4X, 256, CS4271_MODE1_DIV_2},
};
#define CS4171_NR_RATIOS ARRAY_SIZE(cs4271_clk_tab)
static int cs4271_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec;
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
int i, ret;
unsigned int ratio, val;
cs4271->rate = params_rate(params);
/* Configure DAC */
if (cs4271->rate < 50000)
val = CS4271_MODE1_MODE_1X;
else if (cs4271->rate < 100000)
val = CS4271_MODE1_MODE_2X;
else
val = CS4271_MODE1_MODE_4X;
ratio = cs4271->mclk / cs4271->rate;
for (i = 0; i < CS4171_NR_RATIOS; i++)
if ((cs4271_clk_tab[i].master == cs4271->master) &&
(cs4271_clk_tab[i].speed_mode == val) &&
(cs4271_clk_tab[i].ratio == ratio))
break;
if (i == CS4171_NR_RATIOS) {
dev_err(codec->dev, "Invalid sample rate\n");
return -EINVAL;
}
val |= cs4271_clk_tab[i].ratio_mask;
ret = snd_soc_update_bits(codec, CS4271_MODE1,
CS4271_MODE1_MODE_MASK | CS4271_MODE1_DIV_MASK, val);
if (ret < 0)
return ret;
return cs4271_set_deemph(codec);
}
static int cs4271_digital_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
int ret;
int val_a = 0;
int val_b = 0;
if (mute) {
val_a = CS4271_VOLA_MUTE;
val_b = CS4271_VOLB_MUTE;
}
ret = snd_soc_update_bits(codec, CS4271_VOLA, CS4271_VOLA_MUTE, val_a);
if (ret < 0)
return ret;
ret = snd_soc_update_bits(codec, CS4271_VOLB, CS4271_VOLB_MUTE, val_b);
if (ret < 0)
return ret;
return 0;
}
/* CS4271 controls */
static DECLARE_TLV_DB_SCALE(cs4271_dac_tlv, -12700, 100, 0);
static const struct snd_kcontrol_new cs4271_snd_controls[] = {
SOC_DOUBLE_R_TLV("Master Playback Volume", CS4271_VOLA, CS4271_VOLB,
0, 0x7F, 1, cs4271_dac_tlv),
SOC_SINGLE("Digital Loopback Switch", CS4271_MODE2, 4, 1, 0),
SOC_SINGLE("Soft Ramp Switch", CS4271_DACVOL, 5, 1, 0),
SOC_SINGLE("Zero Cross Switch", CS4271_DACVOL, 4, 1, 0),
SOC_SINGLE_BOOL_EXT("De-emphasis Switch", 0,
cs4271_get_deemph, cs4271_put_deemph),
SOC_SINGLE("Auto-Mute Switch", CS4271_DACCTL, 7, 1, 0),
SOC_SINGLE("Slow Roll Off Filter Switch", CS4271_DACCTL, 6, 1, 0),
SOC_SINGLE("Soft Volume Ramp-Up Switch", CS4271_DACCTL, 3, 1, 0),
SOC_SINGLE("Soft Ramp-Down Switch", CS4271_DACCTL, 2, 1, 0),
SOC_SINGLE("Left Channel Inversion Switch", CS4271_DACCTL, 1, 1, 0),
SOC_SINGLE("Right Channel Inversion Switch", CS4271_DACCTL, 0, 1, 0),
SOC_DOUBLE("Master Capture Switch", CS4271_ADCCTL, 3, 2, 1, 1),
SOC_SINGLE("Dither 16-Bit Data Switch", CS4271_ADCCTL, 5, 1, 0),
SOC_DOUBLE("High Pass Filter Switch", CS4271_ADCCTL, 1, 0, 1, 1),
SOC_DOUBLE_R("Master Playback Switch", CS4271_VOLA, CS4271_VOLB,
7, 1, 1),
};
static struct snd_soc_dai_ops cs4271_dai_ops = {
.hw_params = cs4271_hw_params,
.set_sysclk = cs4271_set_dai_sysclk,
.set_fmt = cs4271_set_dai_fmt,
.digital_mute = cs4271_digital_mute,
};
static struct snd_soc_dai_driver cs4271_dai = {
.name = "cs4271-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 2,
.rates = CS4271_PCM_RATES,
.formats = CS4271_PCM_FORMATS,
},
.capture = {
.stream_name = "Capture",
.channels_min = 2,
.channels_max = 2,
.rates = CS4271_PCM_RATES,
.formats = CS4271_PCM_FORMATS,
},
.ops = &cs4271_dai_ops,
.symmetric_rates = 1,
};
#ifdef CONFIG_PM
static int cs4271_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
{
int ret;
/* Set power-down bit */
ret = snd_soc_update_bits(codec, CS4271_MODE2, 0, CS4271_MODE2_PDN);
if (ret < 0)
return ret;
return 0;
}
static int cs4271_soc_resume(struct snd_soc_codec *codec)
{
int ret;
/* Restore codec state */
ret = snd_soc_cache_sync(codec);
if (ret < 0)
return ret;
/* then disable the power-down bit */
ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0);
if (ret < 0)
return ret;
return 0;
}
#else
#define cs4271_soc_suspend NULL
#define cs4271_soc_resume NULL
#endif /* CONFIG_PM */
static int cs4271_probe(struct snd_soc_codec *codec)
{
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
struct cs4271_platform_data *cs4271plat = codec->dev->platform_data;
int ret;
int gpio_nreset = -EINVAL;
codec->control_data = cs4271->control_data;
if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset))
gpio_nreset = cs4271plat->gpio_nreset;
if (gpio_nreset >= 0)
if (gpio_request(gpio_nreset, "CS4271 Reset"))
gpio_nreset = -EINVAL;
if (gpio_nreset >= 0) {
/* Reset codec */
gpio_direction_output(gpio_nreset, 0);
udelay(1);
gpio_set_value(gpio_nreset, 1);
/* Give the codec time to wake up */
udelay(1);
}
cs4271->gpio_nreset = gpio_nreset;
/*
* In case of I2C, chip address specified in board data.
* So cache IO operations use 8 bit codec register address.
* In case of SPI, chip address and register address
* passed together as 16 bit value.
* Anyway, register address is masked with 0xFF inside
* soc-cache code.
*/
if (cs4271->bus_type == SND_SOC_SPI)
ret = snd_soc_codec_set_cache_io(codec, 16, 8,
cs4271->bus_type);
else
ret = snd_soc_codec_set_cache_io(codec, 8, 8,
cs4271->bus_type);
if (ret) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
ret = snd_soc_update_bits(codec, CS4271_MODE2, 0,
CS4271_MODE2_PDN | CS4271_MODE2_CPEN);
if (ret < 0)
return ret;
ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0);
if (ret < 0)
return ret;
/* Power-up sequence requires 85 uS */
udelay(85);
return snd_soc_add_controls(codec, cs4271_snd_controls,
ARRAY_SIZE(cs4271_snd_controls));
}
static int cs4271_remove(struct snd_soc_codec *codec)
{
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
int gpio_nreset;
gpio_nreset = cs4271->gpio_nreset;
if (gpio_is_valid(gpio_nreset)) {
/* Set codec to the reset state */
gpio_set_value(gpio_nreset, 0);
gpio_free(gpio_nreset);
}
return 0;
};
static struct snd_soc_codec_driver soc_codec_dev_cs4271 = {
.probe = cs4271_probe,
.remove = cs4271_remove,
.suspend = cs4271_soc_suspend,
.resume = cs4271_soc_resume,
.reg_cache_default = cs4271_dflt_reg,
.reg_cache_size = ARRAY_SIZE(cs4271_dflt_reg),
.reg_word_size = sizeof(cs4271_dflt_reg[0]),
.compress_type = SND_SOC_FLAT_COMPRESSION,
};
#if defined(CONFIG_SPI_MASTER)
static int __devinit cs4271_spi_probe(struct spi_device *spi)
{
struct cs4271_private *cs4271;
cs4271 = devm_kzalloc(&spi->dev, sizeof(*cs4271), GFP_KERNEL);
if (!cs4271)
return -ENOMEM;
spi_set_drvdata(spi, cs4271);
cs4271->control_data = spi;
cs4271->bus_type = SND_SOC_SPI;
return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271,
&cs4271_dai, 1);
}
static int __devexit cs4271_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
}
static struct spi_driver cs4271_spi_driver = {
.driver = {
.name = "cs4271",
.owner = THIS_MODULE,
},
.probe = cs4271_spi_probe,
.remove = __devexit_p(cs4271_spi_remove),
};
#endif /* defined(CONFIG_SPI_MASTER) */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static const struct i2c_device_id cs4271_i2c_id[] = {
{"cs4271", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id);
static int __devinit cs4271_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct cs4271_private *cs4271;
cs4271 = devm_kzalloc(&client->dev, sizeof(*cs4271), GFP_KERNEL);
if (!cs4271)
return -ENOMEM;
i2c_set_clientdata(client, cs4271);
cs4271->control_data = client;
cs4271->bus_type = SND_SOC_I2C;
return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271,
&cs4271_dai, 1);
}
static int __devexit cs4271_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
}
static struct i2c_driver cs4271_i2c_driver = {
.driver = {
.name = "cs4271",
.owner = THIS_MODULE,
},
.id_table = cs4271_i2c_id,
.probe = cs4271_i2c_probe,
.remove = __devexit_p(cs4271_i2c_remove),
};
#endif /* defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) */
/*
* We only register our serial bus driver here without
* assignment to particular chip. So if any of the below
* fails, there is some problem with I2C or SPI subsystem.
* In most cases this module will be compiled with support
* of only one serial bus.
*/
static int __init cs4271_modinit(void)
{
int ret;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&cs4271_i2c_driver);
if (ret) {
pr_err("Failed to register CS4271 I2C driver: %d\n", ret);
return ret;
}
#endif
#if defined(CONFIG_SPI_MASTER)
ret = spi_register_driver(&cs4271_spi_driver);
if (ret) {
pr_err("Failed to register CS4271 SPI driver: %d\n", ret);
return ret;
}
#endif
return 0;
}
module_init(cs4271_modinit);
static void __exit cs4271_modexit(void)
{
#if defined(CONFIG_SPI_MASTER)
spi_unregister_driver(&cs4271_spi_driver);
#endif
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&cs4271_i2c_driver);
#endif
}
module_exit(cs4271_modexit);
MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>");
MODULE_DESCRIPTION("Cirrus Logic CS4271 ALSA SoC Codec Driver");
MODULE_LICENSE("GPL");
/*
* Driver for the DFBM-CS320 bluetooth module
* Copyright 2011 Lars-Peter Clausen <lars@metafoo.de>
*
* 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/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <sound/soc.h>
static struct snd_soc_dai_driver dfbmcs320_dai = {
.name = "dfbmcs320-pcm",
.playback = {
.channels_min = 1,
.channels_max = 1,
.rates = SNDRV_PCM_RATE_8000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.capture = {
.channels_min = 1,
.channels_max = 1,
.rates = SNDRV_PCM_RATE_8000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
};
static struct snd_soc_codec_driver soc_codec_dev_dfbmcs320;
static int __devinit dfbmcs320_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_dfbmcs320,
&dfbmcs320_dai, 1);
}
static int __devexit dfbmcs320_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
}
static struct platform_driver dfmcs320_driver = {
.driver = {
.name = "dfbmcs320",
.owner = THIS_MODULE,
},
.probe = dfbmcs320_probe,
.remove = __devexit_p(dfbmcs320_remove),
};
static int __init dfbmcs320_init(void)
{
return platform_driver_register(&dfmcs320_driver);
}
module_init(dfbmcs320_init);
static void __exit dfbmcs320_exit(void)
{
platform_driver_unregister(&dfmcs320_driver);
}
module_exit(dfbmcs320_exit);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("ASoC DFBM-CS320 bluethooth module driver");
MODULE_LICENSE("GPL");
/*
* LM4857 AMP driver
*
* Copyright 2007 Wolfson Microelectronics PLC.
* Author: Graeme Gregory
* graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
* Copyright 2011 Lars-Peter Clausen <lars@metafoo.de>
*
* 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/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/soc.h>
#include <sound/tlv.h>
struct lm4857 {
struct i2c_client *i2c;
uint8_t mode;
};
static const uint8_t lm4857_default_regs[] = {
0x00, 0x00, 0x00, 0x00,
};
/* The register offsets in the cache array */
#define LM4857_MVOL 0
#define LM4857_LVOL 1
#define LM4857_RVOL 2
#define LM4857_CTRL 3
/* the shifts required to set these bits */
#define LM4857_3D 5
#define LM4857_WAKEUP 5
#define LM4857_EPGAIN 4
static int lm4857_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
uint8_t data;
int ret;
ret = snd_soc_cache_write(codec, reg, value);
if (ret < 0)
return ret;
data = (reg << 6) | value;
ret = i2c_master_send(codec->control_data, &data, 1);
if (ret != 1) {
dev_err(codec->dev, "Failed to write register: %d\n", ret);
return ret;
}
return 0;
}
static unsigned int lm4857_read(struct snd_soc_codec *codec,
unsigned int reg)
{
unsigned int val;
int ret;
ret = snd_soc_cache_read(codec, reg, &val);
if (ret)
return -1;
return val;
}
static int lm4857_get_mode(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = lm4857->mode;
return 0;
}
static int lm4857_set_mode(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
uint8_t value = ucontrol->value.integer.value[0];
lm4857->mode = value;
if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, value + 6);
return 1;
}
static int lm4857_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
switch (level) {
case SND_SOC_BIAS_ON:
snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, lm4857->mode + 6);
break;
case SND_SOC_BIAS_STANDBY:
snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, 0);
break;
default:
break;
}
codec->dapm.bias_level = level;
return 0;
}
static const char *lm4857_mode[] = {
"Earpiece",
"Loudspeaker",
"Loudspeaker + Headphone",
"Headphone",
};
static const struct soc_enum lm4857_mode_enum =
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lm4857_mode), lm4857_mode);
static const struct snd_soc_dapm_widget lm4857_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("IN"),
SND_SOC_DAPM_OUTPUT("LS"),
SND_SOC_DAPM_OUTPUT("HP"),
SND_SOC_DAPM_OUTPUT("EP"),
};
static const DECLARE_TLV_DB_SCALE(stereo_tlv, -4050, 150, 0);
static const DECLARE_TLV_DB_SCALE(mono_tlv, -3450, 150, 0);
static const struct snd_kcontrol_new lm4857_controls[] = {
SOC_SINGLE_TLV("Left Playback Volume", LM4857_LVOL, 0, 31, 0,
stereo_tlv),
SOC_SINGLE_TLV("Right Playback Volume", LM4857_RVOL, 0, 31, 0,
stereo_tlv),
SOC_SINGLE_TLV("Mono Playback Volume", LM4857_MVOL, 0, 31, 0,
mono_tlv),
SOC_SINGLE("Spk 3D Playback Switch", LM4857_LVOL, LM4857_3D, 1, 0),
SOC_SINGLE("HP 3D Playback Switch", LM4857_RVOL, LM4857_3D, 1, 0),
SOC_SINGLE("Fast Wakeup Playback Switch", LM4857_CTRL,
LM4857_WAKEUP, 1, 0),
SOC_SINGLE("Earpiece 6dB Playback Switch", LM4857_CTRL,
LM4857_EPGAIN, 1, 0),
SOC_ENUM_EXT("Mode", lm4857_mode_enum,
lm4857_get_mode, lm4857_set_mode),
};
/* There is a demux inbetween the the input signal and the output signals.
* Currently there is no easy way to model it in ASoC and since it does not make
* much of a difference in practice simply connect the input direclty to the
* outputs. */
static const struct snd_soc_dapm_route lm4857_routes[] = {
{"LS", NULL, "IN"},
{"HP", NULL, "IN"},
{"EP", NULL, "IN"},
};
static int lm4857_probe(struct snd_soc_codec *codec)
{
struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret;
codec->control_data = lm4857->i2c;
ret = snd_soc_add_controls(codec, lm4857_controls,
ARRAY_SIZE(lm4857_controls));
if (ret)
return ret;
ret = snd_soc_dapm_new_controls(dapm, lm4857_dapm_widgets,
ARRAY_SIZE(lm4857_dapm_widgets));
if (ret)
return ret;
ret = snd_soc_dapm_add_routes(dapm, lm4857_routes,
ARRAY_SIZE(lm4857_routes));
if (ret)
return ret;
snd_soc_dapm_new_widgets(dapm);
return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_lm4857 = {
.write = lm4857_write,
.read = lm4857_read,
.probe = lm4857_probe,
.reg_cache_size = ARRAY_SIZE(lm4857_default_regs),
.reg_word_size = sizeof(uint8_t),
.reg_cache_default = lm4857_default_regs,
.set_bias_level = lm4857_set_bias_level,
};
static int __devinit lm4857_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct lm4857 *lm4857;
int ret;
lm4857 = kzalloc(sizeof(*lm4857), GFP_KERNEL);
if (!lm4857)
return -ENOMEM;
i2c_set_clientdata(i2c, lm4857);
lm4857->i2c = i2c;
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_lm4857, NULL, 0);
if (ret) {
kfree(lm4857);
return ret;
}
return 0;
}
static int __devexit lm4857_i2c_remove(struct i2c_client *i2c)
{
struct lm4857 *lm4857 = i2c_get_clientdata(i2c);
snd_soc_unregister_codec(&i2c->dev);
kfree(lm4857);
return 0;
}
static const struct i2c_device_id lm4857_i2c_id[] = {
{ "lm4857", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm4857_i2c_id);
static struct i2c_driver lm4857_i2c_driver = {
.driver = {
.name = "lm4857",
.owner = THIS_MODULE,
},
.probe = lm4857_i2c_probe,
.remove = __devexit_p(lm4857_i2c_remove),
.id_table = lm4857_i2c_id,
};
static int __init lm4857_init(void)
{
return i2c_add_driver(&lm4857_i2c_driver);
}
module_init(lm4857_init);
static void __exit lm4857_exit(void)
{
i2c_del_driver(&lm4857_i2c_driver);
}
module_exit(lm4857_exit);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("LM4857 amplifier driver");
MODULE_LICENSE("GPL");
......@@ -608,7 +608,7 @@ static struct {
{ 0xFF, 0x00, 1 }, /* FF */
};
static int max98088_volatile_register(unsigned int reg)
static int max98088_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
{
return max98088_access[reg].vol;
}
......
/*
* max9850.c -- codec driver for max9850
*
* Copyright (C) 2011 taskit GmbH
*
* Author: Christian Glindkamp <christian.glindkamp@taskit.de>
*
* Initial development of this code was funded by
* MICRONIC Computer Systeme GmbH, http://www.mcsberlin.de/
*
* 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/init.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#include "max9850.h"
struct max9850_priv {
unsigned int sysclk;
};
/* max9850 register cache */
static const u8 max9850_reg[MAX9850_CACHEREGNUM] = {
0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* these registers are not used at the moment but provided for the sake of
* completeness */
static int max9850_volatile_register(struct snd_soc_codec *codec,
unsigned int reg)
{
switch (reg) {
case MAX9850_STATUSA:
case MAX9850_STATUSB:
return 1;
default:
return 0;
}
}
static const unsigned int max9850_tlv[] = {
TLV_DB_RANGE_HEAD(4),
0x18, 0x1f, TLV_DB_SCALE_ITEM(-7450, 400, 0),
0x20, 0x33, TLV_DB_SCALE_ITEM(-4150, 200, 0),
0x34, 0x37, TLV_DB_SCALE_ITEM(-150, 100, 0),
0x38, 0x3f, TLV_DB_SCALE_ITEM(250, 50, 0),
};
static const struct snd_kcontrol_new max9850_controls[] = {
SOC_SINGLE_TLV("Headphone Volume", MAX9850_VOLUME, 0, 0x3f, 1, max9850_tlv),
SOC_SINGLE("Headphone Switch", MAX9850_VOLUME, 7, 1, 1),
SOC_SINGLE("Mono Switch", MAX9850_GENERAL_PURPOSE, 2, 1, 0),
};
static const struct snd_kcontrol_new max9850_mixer_controls[] = {
SOC_DAPM_SINGLE("Line In Switch", MAX9850_ENABLE, 1, 1, 0),
};
static const struct snd_soc_dapm_widget max9850_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("Charge Pump 1", MAX9850_ENABLE, 4, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Charge Pump 2", MAX9850_ENABLE, 5, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MCLK", MAX9850_ENABLE, 6, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("SHDN", MAX9850_ENABLE, 7, 0, NULL, 0),
SND_SOC_DAPM_MIXER_NAMED_CTL("Output Mixer", MAX9850_ENABLE, 2, 0,
&max9850_mixer_controls[0],
ARRAY_SIZE(max9850_mixer_controls)),
SND_SOC_DAPM_PGA("Headphone Output", MAX9850_ENABLE, 3, 0, NULL, 0),
SND_SOC_DAPM_DAC("DAC", "HiFi Playback", MAX9850_ENABLE, 0, 0),
SND_SOC_DAPM_OUTPUT("OUTL"),
SND_SOC_DAPM_OUTPUT("HPL"),
SND_SOC_DAPM_OUTPUT("OUTR"),
SND_SOC_DAPM_OUTPUT("HPR"),
SND_SOC_DAPM_MIXER("Line Input", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_INPUT("INL"),
SND_SOC_DAPM_INPUT("INR"),
};
static const struct snd_soc_dapm_route intercon[] = {
/* output mixer */
{"Output Mixer", NULL, "DAC"},
{"Output Mixer", "Line In Switch", "Line Input"},
/* outputs */
{"Headphone Output", NULL, "Output Mixer"},
{"HPL", NULL, "Headphone Output"},
{"HPR", NULL, "Headphone Output"},
{"OUTL", NULL, "Output Mixer"},
{"OUTR", NULL, "Output Mixer"},
/* inputs */
{"Line Input", NULL, "INL"},
{"Line Input", NULL, "INR"},
/* supplies */
{"Output Mixer", NULL, "Charge Pump 1"},
{"Output Mixer", NULL, "Charge Pump 2"},
{"Output Mixer", NULL, "SHDN"},
{"DAC", NULL, "MCLK"},
};
static int max9850_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
struct max9850_priv *max9850 = snd_soc_codec_get_drvdata(codec);
u64 lrclk_div;
u8 sf, da;
if (!max9850->sysclk)
return -EINVAL;
/* lrclk_div = 2^22 * rate / iclk with iclk = mclk / sf */
sf = (snd_soc_read(codec, MAX9850_CLOCK) >> 2) + 1;
lrclk_div = (1 << 22);
lrclk_div *= params_rate(params);
lrclk_div *= sf;
do_div(lrclk_div, max9850->sysclk);
snd_soc_write(codec, MAX9850_LRCLK_MSB, (lrclk_div >> 8) & 0x7f);
snd_soc_write(codec, MAX9850_LRCLK_LSB, lrclk_div & 0xff);
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
da = 0;
break;
case SNDRV_PCM_FORMAT_S20_3LE:
da = 0x2;
break;
case SNDRV_PCM_FORMAT_S24_LE:
da = 0x3;
break;
default:
return -EINVAL;
}
snd_soc_update_bits(codec, MAX9850_DIGITAL_AUDIO, 0x3, da);
return 0;
}
static int max9850_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_codec *codec = codec_dai->codec;
struct max9850_priv *max9850 = snd_soc_codec_get_drvdata(codec);
/* calculate mclk -> iclk divider */
if (freq <= 13000000)
snd_soc_write(codec, MAX9850_CLOCK, 0x0);
else if (freq <= 26000000)
snd_soc_write(codec, MAX9850_CLOCK, 0x4);
else if (freq <= 40000000)
snd_soc_write(codec, MAX9850_CLOCK, 0x8);
else
return -EINVAL;
max9850->sysclk = freq;
return 0;
}
static int max9850_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
u8 da = 0;
/* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
da |= MAX9850_MASTER;
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:
da |= MAX9850_DLY;
break;
case SND_SOC_DAIFMT_RIGHT_J:
da |= MAX9850_RTJ;
break;
case SND_SOC_DAIFMT_LEFT_J:
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:
da |= MAX9850_BCINV | MAX9850_INV;
break;
case SND_SOC_DAIFMT_IB_NF:
da |= MAX9850_BCINV;
break;
case SND_SOC_DAIFMT_NB_IF:
da |= MAX9850_INV;
break;
default:
return -EINVAL;
}
/* set da */
snd_soc_write(codec, MAX9850_DIGITAL_AUDIO, da);
return 0;
}
static int max9850_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
int ret;
switch (level) {
case SND_SOC_BIAS_ON:
break;
case SND_SOC_BIAS_PREPARE:
break;
case SND_SOC_BIAS_STANDBY:
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
ret = snd_soc_cache_sync(codec);
if (ret) {
dev_err(codec->dev,
"Failed to sync cache: %d\n", ret);
return ret;
}
}
break;
case SND_SOC_BIAS_OFF:
break;
}
codec->dapm.bias_level = level;
return 0;
}
#define MAX9850_RATES SNDRV_PCM_RATE_8000_48000
#define MAX9850_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE)
static struct snd_soc_dai_ops max9850_dai_ops = {
.hw_params = max9850_hw_params,
.set_sysclk = max9850_set_dai_sysclk,
.set_fmt = max9850_set_dai_fmt,
};
static struct snd_soc_dai_driver max9850_dai = {
.name = "max9850-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
.channels_max = 2,
.rates = MAX9850_RATES,
.formats = MAX9850_FORMATS
},
.ops = &max9850_dai_ops,
};
#ifdef CONFIG_PM
static int max9850_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
max9850_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int max9850_resume(struct snd_soc_codec *codec)
{
max9850_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
#else
#define max9850_suspend NULL
#define max9850_resume NULL
#endif
static int max9850_probe(struct snd_soc_codec *codec)
{
struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret;
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
/* enable zero-detect */
snd_soc_update_bits(codec, MAX9850_GENERAL_PURPOSE, 1, 1);
/* enable slew-rate control */
snd_soc_update_bits(codec, MAX9850_VOLUME, 0x40, 0x40);
/* set slew-rate 125ms */
snd_soc_update_bits(codec, MAX9850_CHARGE_PUMP, 0xff, 0xc0);
snd_soc_dapm_new_controls(dapm, max9850_dapm_widgets,
ARRAY_SIZE(max9850_dapm_widgets));
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
snd_soc_add_controls(codec, max9850_controls,
ARRAY_SIZE(max9850_controls));
return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_max9850 = {
.probe = max9850_probe,
.suspend = max9850_suspend,
.resume = max9850_resume,
.set_bias_level = max9850_set_bias_level,
.reg_cache_size = ARRAY_SIZE(max9850_reg),
.reg_word_size = sizeof(u8),
.reg_cache_default = max9850_reg,
.volatile_register = max9850_volatile_register,
};
static int __devinit max9850_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct max9850_priv *max9850;
int ret;
max9850 = kzalloc(sizeof(struct max9850_priv), GFP_KERNEL);
if (max9850 == NULL)
return -ENOMEM;
i2c_set_clientdata(i2c, max9850);
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_max9850, &max9850_dai, 1);
if (ret < 0)
kfree(max9850);
return ret;
}
static __devexit int max9850_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
kfree(i2c_get_clientdata(client));
return 0;
}
static const struct i2c_device_id max9850_i2c_id[] = {
{ "max9850", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, max9850_i2c_id);
static struct i2c_driver max9850_i2c_driver = {
.driver = {
.name = "max9850",
.owner = THIS_MODULE,
},
.probe = max9850_i2c_probe,
.remove = __devexit_p(max9850_i2c_remove),
.id_table = max9850_i2c_id,
};
static int __init max9850_init(void)
{
return i2c_add_driver(&max9850_i2c_driver);
}
module_init(max9850_init);
static void __exit max9850_exit(void)
{
i2c_del_driver(&max9850_i2c_driver);
}
module_exit(max9850_exit);
MODULE_AUTHOR("Christian Glindkamp <christian.glindkamp@taskit.de>");
MODULE_DESCRIPTION("ASoC MAX9850 codec driver");
MODULE_LICENSE("GPL");
/*
* max9850.h -- codec driver for max9850
*
* Copyright (C) 2011 taskit GmbH
* Author: Christian Glindkamp <christian.glindkamp@taskit.de>
*
* 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 _MAX9850_H
#define _MAX9850_H
#define MAX9850_STATUSA 0x00
#define MAX9850_STATUSB 0x01
#define MAX9850_VOLUME 0x02
#define MAX9850_GENERAL_PURPOSE 0x03
#define MAX9850_INTERRUPT 0x04
#define MAX9850_ENABLE 0x05
#define MAX9850_CLOCK 0x06
#define MAX9850_CHARGE_PUMP 0x07
#define MAX9850_LRCLK_MSB 0x08
#define MAX9850_LRCLK_LSB 0x09
#define MAX9850_DIGITAL_AUDIO 0x0a
#define MAX9850_CACHEREGNUM 11
/* MAX9850_DIGITAL_AUDIO */
#define MAX9850_MASTER (1<<7)
#define MAX9850_INV (1<<6)
#define MAX9850_BCINV (1<<5)
#define MAX9850_DLY (1<<3)
#define MAX9850_RTJ (1<<2)
#endif
此差异已折叠。
/*
* sgtl5000.h - SGTL5000 audio codec interface
*
* Copyright 2010-2011 Freescale Semiconductor, Inc.
*
* 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 _SGTL5000_H
#define _SGTL5000_H
/*
* Register values.
*/
#define SGTL5000_CHIP_ID 0x0000
#define SGTL5000_CHIP_DIG_POWER 0x0002
#define SGTL5000_CHIP_CLK_CTRL 0x0004
#define SGTL5000_CHIP_I2S_CTRL 0x0006
#define SGTL5000_CHIP_SSS_CTRL 0x000a
#define SGTL5000_CHIP_ADCDAC_CTRL 0x000e
#define SGTL5000_CHIP_DAC_VOL 0x0010
#define SGTL5000_CHIP_PAD_STRENGTH 0x0014
#define SGTL5000_CHIP_ANA_ADC_CTRL 0x0020
#define SGTL5000_CHIP_ANA_HP_CTRL 0x0022
#define SGTL5000_CHIP_ANA_CTRL 0x0024
#define SGTL5000_CHIP_LINREG_CTRL 0x0026
#define SGTL5000_CHIP_REF_CTRL 0x0028
#define SGTL5000_CHIP_MIC_CTRL 0x002a
#define SGTL5000_CHIP_LINE_OUT_CTRL 0x002c
#define SGTL5000_CHIP_LINE_OUT_VOL 0x002e
#define SGTL5000_CHIP_ANA_POWER 0x0030
#define SGTL5000_CHIP_PLL_CTRL 0x0032
#define SGTL5000_CHIP_CLK_TOP_CTRL 0x0034
#define SGTL5000_CHIP_ANA_STATUS 0x0036
#define SGTL5000_CHIP_SHORT_CTRL 0x003c
#define SGTL5000_CHIP_ANA_TEST2 0x003a
#define SGTL5000_DAP_CTRL 0x0100
#define SGTL5000_DAP_PEQ 0x0102
#define SGTL5000_DAP_BASS_ENHANCE 0x0104
#define SGTL5000_DAP_BASS_ENHANCE_CTRL 0x0106
#define SGTL5000_DAP_AUDIO_EQ 0x0108
#define SGTL5000_DAP_SURROUND 0x010a
#define SGTL5000_DAP_FLT_COEF_ACCESS 0x010c
#define SGTL5000_DAP_COEF_WR_B0_MSB 0x010e
#define SGTL5000_DAP_COEF_WR_B0_LSB 0x0110
#define SGTL5000_DAP_EQ_BASS_BAND0 0x0116
#define SGTL5000_DAP_EQ_BASS_BAND1 0x0118
#define SGTL5000_DAP_EQ_BASS_BAND2 0x011a
#define SGTL5000_DAP_EQ_BASS_BAND3 0x011c
#define SGTL5000_DAP_EQ_BASS_BAND4 0x011e
#define SGTL5000_DAP_MAIN_CHAN 0x0120
#define SGTL5000_DAP_MIX_CHAN 0x0122
#define SGTL5000_DAP_AVC_CTRL 0x0124
#define SGTL5000_DAP_AVC_THRESHOLD 0x0126
#define SGTL5000_DAP_AVC_ATTACK 0x0128
#define SGTL5000_DAP_AVC_DECAY 0x012a
#define SGTL5000_DAP_COEF_WR_B1_MSB 0x012c
#define SGTL5000_DAP_COEF_WR_B1_LSB 0x012e
#define SGTL5000_DAP_COEF_WR_B2_MSB 0x0130
#define SGTL5000_DAP_COEF_WR_B2_LSB 0x0132
#define SGTL5000_DAP_COEF_WR_A1_MSB 0x0134
#define SGTL5000_DAP_COEF_WR_A1_LSB 0x0136
#define SGTL5000_DAP_COEF_WR_A2_MSB 0x0138
#define SGTL5000_DAP_COEF_WR_A2_LSB 0x013a
/*
* Field Definitions.
*/
/*
* SGTL5000_CHIP_ID
*/
#define SGTL5000_PARTID_MASK 0xff00
#define SGTL5000_PARTID_SHIFT 8
#define SGTL5000_PARTID_WIDTH 8
#define SGTL5000_PARTID_PART_ID 0xa0
#define SGTL5000_REVID_MASK 0x00ff
#define SGTL5000_REVID_SHIFT 0
#define SGTL5000_REVID_WIDTH 8
/*
* SGTL5000_CHIP_DIG_POWER
*/
#define SGTL5000_ADC_EN 0x0040
#define SGTL5000_DAC_EN 0x0020
#define SGTL5000_DAP_POWERUP 0x0010
#define SGTL5000_I2S_OUT_POWERUP 0x0002
#define SGTL5000_I2S_IN_POWERUP 0x0001
/*
* SGTL5000_CHIP_CLK_CTRL
*/
#define SGTL5000_RATE_MODE_MASK 0x0030
#define SGTL5000_RATE_MODE_SHIFT 4
#define SGTL5000_RATE_MODE_WIDTH 2
#define SGTL5000_RATE_MODE_DIV_1 0
#define SGTL5000_RATE_MODE_DIV_2 1
#define SGTL5000_RATE_MODE_DIV_4 2
#define SGTL5000_RATE_MODE_DIV_6 3
#define SGTL5000_SYS_FS_MASK 0x000c
#define SGTL5000_SYS_FS_SHIFT 2
#define SGTL5000_SYS_FS_WIDTH 2
#define SGTL5000_SYS_FS_32k 0x0
#define SGTL5000_SYS_FS_44_1k 0x1
#define SGTL5000_SYS_FS_48k 0x2
#define SGTL5000_SYS_FS_96k 0x3
#define SGTL5000_MCLK_FREQ_MASK 0x0003
#define SGTL5000_MCLK_FREQ_SHIFT 0
#define SGTL5000_MCLK_FREQ_WIDTH 2
#define SGTL5000_MCLK_FREQ_256FS 0x0
#define SGTL5000_MCLK_FREQ_384FS 0x1
#define SGTL5000_MCLK_FREQ_512FS 0x2
#define SGTL5000_MCLK_FREQ_PLL 0x3
/*
* SGTL5000_CHIP_I2S_CTRL
*/
#define SGTL5000_I2S_SCLKFREQ_MASK 0x0100
#define SGTL5000_I2S_SCLKFREQ_SHIFT 8
#define SGTL5000_I2S_SCLKFREQ_WIDTH 1
#define SGTL5000_I2S_SCLKFREQ_64FS 0x0
#define SGTL5000_I2S_SCLKFREQ_32FS 0x1 /* Not for RJ mode */
#define SGTL5000_I2S_MASTER 0x0080
#define SGTL5000_I2S_SCLK_INV 0x0040
#define SGTL5000_I2S_DLEN_MASK 0x0030
#define SGTL5000_I2S_DLEN_SHIFT 4
#define SGTL5000_I2S_DLEN_WIDTH 2
#define SGTL5000_I2S_DLEN_32 0x0
#define SGTL5000_I2S_DLEN_24 0x1
#define SGTL5000_I2S_DLEN_20 0x2
#define SGTL5000_I2S_DLEN_16 0x3
#define SGTL5000_I2S_MODE_MASK 0x000c
#define SGTL5000_I2S_MODE_SHIFT 2
#define SGTL5000_I2S_MODE_WIDTH 2
#define SGTL5000_I2S_MODE_I2S_LJ 0x0
#define SGTL5000_I2S_MODE_RJ 0x1
#define SGTL5000_I2S_MODE_PCM 0x2
#define SGTL5000_I2S_LRALIGN 0x0002
#define SGTL5000_I2S_LRPOL 0x0001 /* set for which mode */
/*
* SGTL5000_CHIP_SSS_CTRL
*/
#define SGTL5000_DAP_MIX_LRSWAP 0x4000
#define SGTL5000_DAP_LRSWAP 0x2000
#define SGTL5000_DAC_LRSWAP 0x1000
#define SGTL5000_I2S_OUT_LRSWAP 0x0400
#define SGTL5000_DAP_MIX_SEL_MASK 0x0300
#define SGTL5000_DAP_MIX_SEL_SHIFT 8
#define SGTL5000_DAP_MIX_SEL_WIDTH 2
#define SGTL5000_DAP_MIX_SEL_ADC 0x0
#define SGTL5000_DAP_MIX_SEL_I2S_IN 0x1
#define SGTL5000_DAP_SEL_MASK 0x00c0
#define SGTL5000_DAP_SEL_SHIFT 6
#define SGTL5000_DAP_SEL_WIDTH 2
#define SGTL5000_DAP_SEL_ADC 0x0
#define SGTL5000_DAP_SEL_I2S_IN 0x1
#define SGTL5000_DAC_SEL_MASK 0x0030
#define SGTL5000_DAC_SEL_SHIFT 4
#define SGTL5000_DAC_SEL_WIDTH 2
#define SGTL5000_DAC_SEL_ADC 0x0
#define SGTL5000_DAC_SEL_I2S_IN 0x1
#define SGTL5000_DAC_SEL_DAP 0x3
#define SGTL5000_I2S_OUT_SEL_MASK 0x0003
#define SGTL5000_I2S_OUT_SEL_SHIFT 0
#define SGTL5000_I2S_OUT_SEL_WIDTH 2
#define SGTL5000_I2S_OUT_SEL_ADC 0x0
#define SGTL5000_I2S_OUT_SEL_I2S_IN 0x1
#define SGTL5000_I2S_OUT_SEL_DAP 0x3
/*
* SGTL5000_CHIP_ADCDAC_CTRL
*/
#define SGTL5000_VOL_BUSY_DAC_RIGHT 0x2000
#define SGTL5000_VOL_BUSY_DAC_LEFT 0x1000
#define SGTL5000_DAC_VOL_RAMP_EN 0x0200
#define SGTL5000_DAC_VOL_RAMP_EXPO 0x0100
#define SGTL5000_DAC_MUTE_RIGHT 0x0008
#define SGTL5000_DAC_MUTE_LEFT 0x0004
#define SGTL5000_ADC_HPF_FREEZE 0x0002
#define SGTL5000_ADC_HPF_BYPASS 0x0001
/*
* SGTL5000_CHIP_DAC_VOL
*/
#define SGTL5000_DAC_VOL_RIGHT_MASK 0xff00
#define SGTL5000_DAC_VOL_RIGHT_SHIFT 8
#define SGTL5000_DAC_VOL_RIGHT_WIDTH 8
#define SGTL5000_DAC_VOL_LEFT_MASK 0x00ff
#define SGTL5000_DAC_VOL_LEFT_SHIFT 0
#define SGTL5000_DAC_VOL_LEFT_WIDTH 8
/*
* SGTL5000_CHIP_PAD_STRENGTH
*/
#define SGTL5000_PAD_I2S_LRCLK_MASK 0x0300
#define SGTL5000_PAD_I2S_LRCLK_SHIFT 8
#define SGTL5000_PAD_I2S_LRCLK_WIDTH 2
#define SGTL5000_PAD_I2S_SCLK_MASK 0x00c0
#define SGTL5000_PAD_I2S_SCLK_SHIFT 6
#define SGTL5000_PAD_I2S_SCLK_WIDTH 2
#define SGTL5000_PAD_I2S_DOUT_MASK 0x0030
#define SGTL5000_PAD_I2S_DOUT_SHIFT 4
#define SGTL5000_PAD_I2S_DOUT_WIDTH 2
#define SGTL5000_PAD_I2C_SDA_MASK 0x000c
#define SGTL5000_PAD_I2C_SDA_SHIFT 2
#define SGTL5000_PAD_I2C_SDA_WIDTH 2
#define SGTL5000_PAD_I2C_SCL_MASK 0x0003
#define SGTL5000_PAD_I2C_SCL_SHIFT 0
#define SGTL5000_PAD_I2C_SCL_WIDTH 2
/*
* SGTL5000_CHIP_ANA_ADC_CTRL
*/
#define SGTL5000_ADC_VOL_M6DB 0x0100
#define SGTL5000_ADC_VOL_RIGHT_MASK 0x00f0
#define SGTL5000_ADC_VOL_RIGHT_SHIFT 4
#define SGTL5000_ADC_VOL_RIGHT_WIDTH 4
#define SGTL5000_ADC_VOL_LEFT_MASK 0x000f
#define SGTL5000_ADC_VOL_LEFT_SHIFT 0
#define SGTL5000_ADC_VOL_LEFT_WIDTH 4
/*
* SGTL5000_CHIP_ANA_HP_CTRL
*/
#define SGTL5000_HP_VOL_RIGHT_MASK 0x7f00
#define SGTL5000_HP_VOL_RIGHT_SHIFT 8
#define SGTL5000_HP_VOL_RIGHT_WIDTH 7
#define SGTL5000_HP_VOL_LEFT_MASK 0x007f
#define SGTL5000_HP_VOL_LEFT_SHIFT 0
#define SGTL5000_HP_VOL_LEFT_WIDTH 7
/*
* SGTL5000_CHIP_ANA_CTRL
*/
#define SGTL5000_LINE_OUT_MUTE 0x0100
#define SGTL5000_HP_SEL_MASK 0x0040
#define SGTL5000_HP_SEL_SHIFT 6
#define SGTL5000_HP_SEL_WIDTH 1
#define SGTL5000_HP_SEL_DAC 0x0
#define SGTL5000_HP_SEL_LINE_IN 0x1
#define SGTL5000_HP_ZCD_EN 0x0020
#define SGTL5000_HP_MUTE 0x0010
#define SGTL5000_ADC_SEL_MASK 0x0004
#define SGTL5000_ADC_SEL_SHIFT 2
#define SGTL5000_ADC_SEL_WIDTH 1
#define SGTL5000_ADC_SEL_MIC 0x0
#define SGTL5000_ADC_SEL_LINE_IN 0x1
#define SGTL5000_ADC_ZCD_EN 0x0002
#define SGTL5000_ADC_MUTE 0x0001
/*
* SGTL5000_CHIP_LINREG_CTRL
*/
#define SGTL5000_VDDC_MAN_ASSN_MASK 0x0040
#define SGTL5000_VDDC_MAN_ASSN_SHIFT 6
#define SGTL5000_VDDC_MAN_ASSN_WIDTH 1
#define SGTL5000_VDDC_MAN_ASSN_VDDA 0x0
#define SGTL5000_VDDC_MAN_ASSN_VDDIO 0x1
#define SGTL5000_VDDC_ASSN_OVRD 0x0020
#define SGTL5000_LINREG_VDDD_MASK 0x000f
#define SGTL5000_LINREG_VDDD_SHIFT 0
#define SGTL5000_LINREG_VDDD_WIDTH 4
/*
* SGTL5000_CHIP_REF_CTRL
*/
#define SGTL5000_ANA_GND_MASK 0x01f0
#define SGTL5000_ANA_GND_SHIFT 4
#define SGTL5000_ANA_GND_WIDTH 5
#define SGTL5000_ANA_GND_BASE 800 /* mv */
#define SGTL5000_ANA_GND_STP 25 /*mv */
#define SGTL5000_BIAS_CTRL_MASK 0x000e
#define SGTL5000_BIAS_CTRL_SHIFT 1
#define SGTL5000_BIAS_CTRL_WIDTH 3
#define SGTL5000_SMALL_POP 0x0001
/*
* SGTL5000_CHIP_MIC_CTRL
*/
#define SGTL5000_BIAS_R_MASK 0x0200
#define SGTL5000_BIAS_R_SHIFT 8
#define SGTL5000_BIAS_R_WIDTH 2
#define SGTL5000_BIAS_R_off 0x0
#define SGTL5000_BIAS_R_2K 0x1
#define SGTL5000_BIAS_R_4k 0x2
#define SGTL5000_BIAS_R_8k 0x3
#define SGTL5000_BIAS_VOLT_MASK 0x0070
#define SGTL5000_BIAS_VOLT_SHIFT 4
#define SGTL5000_BIAS_VOLT_WIDTH 3
#define SGTL5000_MIC_GAIN_MASK 0x0003
#define SGTL5000_MIC_GAIN_SHIFT 0
#define SGTL5000_MIC_GAIN_WIDTH 2
/*
* SGTL5000_CHIP_LINE_OUT_CTRL
*/
#define SGTL5000_LINE_OUT_CURRENT_MASK 0x0f00
#define SGTL5000_LINE_OUT_CURRENT_SHIFT 8
#define SGTL5000_LINE_OUT_CURRENT_WIDTH 4
#define SGTL5000_LINE_OUT_CURRENT_180u 0x0
#define SGTL5000_LINE_OUT_CURRENT_270u 0x1
#define SGTL5000_LINE_OUT_CURRENT_360u 0x3
#define SGTL5000_LINE_OUT_CURRENT_450u 0x7
#define SGTL5000_LINE_OUT_CURRENT_540u 0xf
#define SGTL5000_LINE_OUT_GND_MASK 0x003f
#define SGTL5000_LINE_OUT_GND_SHIFT 0
#define SGTL5000_LINE_OUT_GND_WIDTH 6
#define SGTL5000_LINE_OUT_GND_BASE 800 /* mv */
#define SGTL5000_LINE_OUT_GND_STP 25
#define SGTL5000_LINE_OUT_GND_MAX 0x23
/*
* SGTL5000_CHIP_LINE_OUT_VOL
*/
#define SGTL5000_LINE_OUT_VOL_RIGHT_MASK 0x1f00
#define SGTL5000_LINE_OUT_VOL_RIGHT_SHIFT 8
#define SGTL5000_LINE_OUT_VOL_RIGHT_WIDTH 5
#define SGTL5000_LINE_OUT_VOL_LEFT_MASK 0x001f
#define SGTL5000_LINE_OUT_VOL_LEFT_SHIFT 0
#define SGTL5000_LINE_OUT_VOL_LEFT_WIDTH 5
/*
* SGTL5000_CHIP_ANA_POWER
*/
#define SGTL5000_DAC_STEREO 0x4000
#define SGTL5000_LINREG_SIMPLE_POWERUP 0x2000
#define SGTL5000_STARTUP_POWERUP 0x1000
#define SGTL5000_VDDC_CHRGPMP_POWERUP 0x0800
#define SGTL5000_PLL_POWERUP 0x0400
#define SGTL5000_LINEREG_D_POWERUP 0x0200
#define SGTL5000_VCOAMP_POWERUP 0x0100
#define SGTL5000_VAG_POWERUP 0x0080
#define SGTL5000_ADC_STEREO 0x0040
#define SGTL5000_REFTOP_POWERUP 0x0020
#define SGTL5000_HP_POWERUP 0x0010
#define SGTL5000_DAC_POWERUP 0x0008
#define SGTL5000_CAPLESS_HP_POWERUP 0x0004
#define SGTL5000_ADC_POWERUP 0x0002
#define SGTL5000_LINE_OUT_POWERUP 0x0001
/*
* SGTL5000_CHIP_PLL_CTRL
*/
#define SGTL5000_PLL_INT_DIV_MASK 0xf800
#define SGTL5000_PLL_INT_DIV_SHIFT 11
#define SGTL5000_PLL_INT_DIV_WIDTH 5
#define SGTL5000_PLL_FRAC_DIV_MASK 0x0700
#define SGTL5000_PLL_FRAC_DIV_SHIFT 0
#define SGTL5000_PLL_FRAC_DIV_WIDTH 11
/*
* SGTL5000_CHIP_CLK_TOP_CTRL
*/
#define SGTL5000_INT_OSC_EN 0x0800
#define SGTL5000_INPUT_FREQ_DIV2 0x0008
/*
* SGTL5000_CHIP_ANA_STATUS
*/
#define SGTL5000_HP_LRSHORT 0x0200
#define SGTL5000_CAPLESS_SHORT 0x0100
#define SGTL5000_PLL_LOCKED 0x0010
/*
* SGTL5000_CHIP_SHORT_CTRL
*/
#define SGTL5000_LVLADJR_MASK 0x7000
#define SGTL5000_LVLADJR_SHIFT 12
#define SGTL5000_LVLADJR_WIDTH 3
#define SGTL5000_LVLADJL_MASK 0x0700
#define SGTL5000_LVLADJL_SHIFT 8
#define SGTL5000_LVLADJL_WIDTH 3
#define SGTL5000_LVLADJC_MASK 0x0070
#define SGTL5000_LVLADJC_SHIFT 4
#define SGTL5000_LVLADJC_WIDTH 3
#define SGTL5000_LR_SHORT_MOD_MASK 0x000c
#define SGTL5000_LR_SHORT_MOD_SHIFT 2
#define SGTL5000_LR_SHORT_MOD_WIDTH 2
#define SGTL5000_CM_SHORT_MOD_MASK 0x0003
#define SGTL5000_CM_SHORT_MOD_SHIFT 0
#define SGTL5000_CM_SHORT_MOD_WIDTH 2
/*
*SGTL5000_CHIP_ANA_TEST2
*/
#define SGTL5000_MONO_DAC 0x1000
/*
* SGTL5000_DAP_CTRL
*/
#define SGTL5000_DAP_MIX_EN 0x0010
#define SGTL5000_DAP_EN 0x0001
#define SGTL5000_SYSCLK 0x00
#define SGTL5000_LRCLK 0x01
#endif
此差异已折叠。
/*
* sn95031.h - TI sn95031 Codec driver
*
* Copyright (C) 2010 Intel Corp
* Author: Vinod Koul <vinod.koul@intel.com>
* Author: Harsha Priya <priya.harsha@intel.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; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*
*/
#ifndef _SN95031_H
#define _SN95031_H
/*register map*/
#define SN95031_VAUD 0xDB
#define SN95031_VHSP 0xDC
#define SN95031_VHSN 0xDD
#define SN95031_VIHF 0xC9
#define SN95031_AUDPLLCTRL 0x240
#define SN95031_DMICBUF0123 0x241
#define SN95031_DMICBUF45 0x242
#define SN95031_DMICGPO 0x244
#define SN95031_DMICMUX 0x245
#define SN95031_DMICLK 0x246
#define SN95031_MICBIAS 0x247
#define SN95031_ADCCONFIG 0x248
#define SN95031_MICAMP1 0x249
#define SN95031_MICAMP2 0x24A
#define SN95031_NOISEMUX 0x24B
#define SN95031_AUDIOMUX12 0x24C
#define SN95031_AUDIOMUX34 0x24D
#define SN95031_AUDIOSINC 0x24E
#define SN95031_AUDIOTXEN 0x24F
#define SN95031_HSEPRXCTRL 0x250
#define SN95031_IHFRXCTRL 0x251
#define SN95031_HSMIXER 0x256
#define SN95031_DACCONFIG 0x257
#define SN95031_SOFTMUTE 0x258
#define SN95031_HSLVOLCTRL 0x259
#define SN95031_HSRVOLCTRL 0x25A
#define SN95031_IHFLVOLCTRL 0x25B
#define SN95031_IHFRVOLCTRL 0x25C
#define SN95031_DRIVEREN 0x25D
#define SN95031_LOCTL 0x25E
#define SN95031_VIB1C1 0x25F
#define SN95031_VIB1C2 0x260
#define SN95031_VIB1C3 0x261
#define SN95031_VIB1SPIPCM1 0x262
#define SN95031_VIB1SPIPCM2 0x263
#define SN95031_VIB1C5 0x264
#define SN95031_VIB2C1 0x265
#define SN95031_VIB2C2 0x266
#define SN95031_VIB2C3 0x267
#define SN95031_VIB2SPIPCM1 0x268
#define SN95031_VIB2SPIPCM2 0x269
#define SN95031_VIB2C5 0x26A
#define SN95031_BTNCTRL1 0x26B
#define SN95031_BTNCTRL2 0x26C
#define SN95031_PCM1TXSLOT01 0x26D
#define SN95031_PCM1TXSLOT23 0x26E
#define SN95031_PCM1TXSLOT45 0x26F
#define SN95031_PCM1RXSLOT0_3 0x270
#define SN95031_PCM1RXSLOT45 0x271
#define SN95031_PCM2TXSLOT01 0x272
#define SN95031_PCM2TXSLOT23 0x273
#define SN95031_PCM2TXSLOT45 0x274
#define SN95031_PCM2RXSLOT01 0x275
#define SN95031_PCM2RXSLOT23 0x276
#define SN95031_PCM2RXSLOT45 0x277
#define SN95031_PCM1C1 0x278
#define SN95031_PCM1C2 0x279
#define SN95031_PCM1C3 0x27A
#define SN95031_PCM2C1 0x27B
#define SN95031_PCM2C2 0x27C
/*end codec register defn*/
/*vendor defn these are not part of avp*/
#define SN95031_SSR2 0x381
#define SN95031_SSR3 0x382
#define SN95031_SSR5 0x384
#define SN95031_SSR6 0x385
/* ADC registers */
#define SN95031_ADC1CNTL1 0x1C0
#define SN95031_ADC_ENBL 0x10
#define SN95031_ADC_START 0x08
#define SN95031_ADC1CNTL3 0x1C2
#define SN95031_ADCTHERM_ENBL 0x04
#define SN95031_ADCRRDATA_ENBL 0x05
#define SN95031_STOPBIT_MASK 16
#define SN95031_ADCTHERM_MASK 4
#define SN95031_ADC_CHANLS_MAX 15 /* Number of ADC channels */
#define SN95031_ADC_LOOP_MAX (SN95031_ADC_CHANLS_MAX - 1)
#define SN95031_ADC_NO_LOOP 0x07
#define SN95031_AUDIO_GPIO_CTRL 0x070
/* ADC channel code values */
#define SN95031_AUDIO_DETECT_CODE 0x06
/* ADC base addresses */
#define SN95031_ADC_CHNL_START_ADDR 0x1C5 /* increments by 1 */
#define SN95031_ADC_DATA_START_ADDR 0x1D4 /* increments by 2 */
/* multipier to convert to mV */
#define SN95031_ADC_ONE_LSB_MULTIPLIER 2346
struct mfld_jack_data {
int intr_id;
int micbias_vol;
struct snd_soc_jack *mfld_jack;
};
extern void sn95031_jack_detection(struct mfld_jack_data *jack_data);
#endif
此差异已折叠。
/*
* tlv320aic32x4.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 _TLV320AIC32X4_H
#define _TLV320AIC32X4_H
/* tlv320aic32x4 register space (in decimal to match datasheet) */
#define AIC32X4_PAGE1 128
#define AIC32X4_PSEL 0
#define AIC32X4_RESET 1
#define AIC32X4_CLKMUX 4
#define AIC32X4_PLLPR 5
#define AIC32X4_PLLJ 6
#define AIC32X4_PLLDMSB 7
#define AIC32X4_PLLDLSB 8
#define AIC32X4_NDAC 11
#define AIC32X4_MDAC 12
#define AIC32X4_DOSRMSB 13
#define AIC32X4_DOSRLSB 14
#define AIC32X4_NADC 18
#define AIC32X4_MADC 19
#define AIC32X4_AOSR 20
#define AIC32X4_CLKMUX2 25
#define AIC32X4_CLKOUTM 26
#define AIC32X4_IFACE1 27
#define AIC32X4_IFACE2 28
#define AIC32X4_IFACE3 29
#define AIC32X4_BCLKN 30
#define AIC32X4_IFACE4 31
#define AIC32X4_IFACE5 32
#define AIC32X4_IFACE6 33
#define AIC32X4_DOUTCTL 53
#define AIC32X4_DINCTL 54
#define AIC32X4_DACSPB 60
#define AIC32X4_ADCSPB 61
#define AIC32X4_DACSETUP 63
#define AIC32X4_DACMUTE 64
#define AIC32X4_LDACVOL 65
#define AIC32X4_RDACVOL 66
#define AIC32X4_ADCSETUP 81
#define AIC32X4_ADCFGA 82
#define AIC32X4_LADCVOL 83
#define AIC32X4_RADCVOL 84
#define AIC32X4_LAGC1 86
#define AIC32X4_LAGC2 87
#define AIC32X4_LAGC3 88
#define AIC32X4_LAGC4 89
#define AIC32X4_LAGC5 90
#define AIC32X4_LAGC6 91
#define AIC32X4_LAGC7 92
#define AIC32X4_RAGC1 94
#define AIC32X4_RAGC2 95
#define AIC32X4_RAGC3 96
#define AIC32X4_RAGC4 97
#define AIC32X4_RAGC5 98
#define AIC32X4_RAGC6 99
#define AIC32X4_RAGC7 100
#define AIC32X4_PWRCFG (AIC32X4_PAGE1 + 1)
#define AIC32X4_LDOCTL (AIC32X4_PAGE1 + 2)
#define AIC32X4_OUTPWRCTL (AIC32X4_PAGE1 + 9)
#define AIC32X4_CMMODE (AIC32X4_PAGE1 + 10)
#define AIC32X4_HPLROUTE (AIC32X4_PAGE1 + 12)
#define AIC32X4_HPRROUTE (AIC32X4_PAGE1 + 13)
#define AIC32X4_LOLROUTE (AIC32X4_PAGE1 + 14)
#define AIC32X4_LORROUTE (AIC32X4_PAGE1 + 15)
#define AIC32X4_HPLGAIN (AIC32X4_PAGE1 + 16)
#define AIC32X4_HPRGAIN (AIC32X4_PAGE1 + 17)
#define AIC32X4_LOLGAIN (AIC32X4_PAGE1 + 18)
#define AIC32X4_LORGAIN (AIC32X4_PAGE1 + 19)
#define AIC32X4_HEADSTART (AIC32X4_PAGE1 + 20)
#define AIC32X4_MICBIAS (AIC32X4_PAGE1 + 51)
#define AIC32X4_LMICPGAPIN (AIC32X4_PAGE1 + 52)
#define AIC32X4_LMICPGANIN (AIC32X4_PAGE1 + 54)
#define AIC32X4_RMICPGAPIN (AIC32X4_PAGE1 + 55)
#define AIC32X4_RMICPGANIN (AIC32X4_PAGE1 + 57)
#define AIC32X4_FLOATINGINPUT (AIC32X4_PAGE1 + 58)
#define AIC32X4_LMICPGAVOL (AIC32X4_PAGE1 + 59)
#define AIC32X4_RMICPGAVOL (AIC32X4_PAGE1 + 60)
#define AIC32X4_FREQ_12000000 12000000
#define AIC32X4_FREQ_24000000 24000000
#define AIC32X4_FREQ_25000000 25000000
#define AIC32X4_WORD_LEN_16BITS 0x00
#define AIC32X4_WORD_LEN_20BITS 0x01
#define AIC32X4_WORD_LEN_24BITS 0x02
#define AIC32X4_WORD_LEN_32BITS 0x03
#define AIC32X4_I2S_MODE 0x00
#define AIC32X4_DSP_MODE 0x01
#define AIC32X4_RIGHT_JUSTIFIED_MODE 0x02
#define AIC32X4_LEFT_JUSTIFIED_MODE 0x03
#define AIC32X4_AVDDWEAKDISABLE 0x08
#define AIC32X4_LDOCTLEN 0x01
#define AIC32X4_LDOIN_18_36 0x01
#define AIC32X4_LDOIN2HP 0x02
#define AIC32X4_DACSPBLOCK_MASK 0x1f
#define AIC32X4_ADCSPBLOCK_MASK 0x1f
#define AIC32X4_PLLJ_SHIFT 6
#define AIC32X4_DOSRMSB_SHIFT 4
#define AIC32X4_PLLCLKIN 0x03
#define AIC32X4_MICBIAS_LDOIN 0x08
#define AIC32X4_MICBIAS_2075V 0x60
#define AIC32X4_LMICPGANIN_IN2R_10K 0x10
#define AIC32X4_RMICPGANIN_IN1L_10K 0x10
#define AIC32X4_LMICPGAVOL_NOGAIN 0x80
#define AIC32X4_RMICPGAVOL_NOGAIN 0x80
#define AIC32X4_BCLKMASTER 0x08
#define AIC32X4_WCLKMASTER 0x04
#define AIC32X4_PLLEN (0x01 << 7)
#define AIC32X4_NDACEN (0x01 << 7)
#define AIC32X4_MDACEN (0x01 << 7)
#define AIC32X4_NADCEN (0x01 << 7)
#define AIC32X4_MADCEN (0x01 << 7)
#define AIC32X4_BCLKEN (0x01 << 7)
#define AIC32X4_DACEN (0x03 << 6)
#define AIC32X4_RDAC2LCHN (0x02 << 2)
#define AIC32X4_LDAC2RCHN (0x02 << 4)
#define AIC32X4_LDAC2LCHN (0x01 << 4)
#define AIC32X4_RDAC2RCHN (0x01 << 2)
#define AIC32X4_SSTEP2WCLK 0x01
#define AIC32X4_MUTEON 0x0C
#define AIC32X4_DACMOD2BCLK 0x01
#endif /* _TLV320AIC32X4_H */
......@@ -1615,6 +1615,7 @@ static const struct i2c_device_id tlv320dac33_i2c_id[] = {
},
{ },
};
MODULE_DEVICE_TABLE(i2c, tlv320dac33_i2c_id);
static struct i2c_driver tlv320dac33_i2c_driver = {
.driver = {
......
......@@ -724,8 +724,8 @@ static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
return 0;
}
void twl6040_hs_jack_report(struct snd_soc_codec *codec,
struct snd_soc_jack *jack, int report)
static void twl6040_hs_jack_report(struct snd_soc_codec *codec,
struct snd_soc_jack *jack, int report)
{
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
int status;
......
......@@ -836,24 +836,25 @@ static void wm2000_i2c_shutdown(struct i2c_client *i2c)
}
#ifdef CONFIG_PM
static int wm2000_i2c_suspend(struct i2c_client *i2c, pm_message_t mesg)
static int wm2000_i2c_suspend(struct device *dev)
{
struct i2c_client *i2c = to_i2c_client(dev);
struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
return wm2000_anc_transition(wm2000, ANC_OFF);
}
static int wm2000_i2c_resume(struct i2c_client *i2c)
static int wm2000_i2c_resume(struct device *dev)
{
struct i2c_client *i2c = to_i2c_client(dev);
struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
return wm2000_anc_set_mode(wm2000);
}
#else
#define wm2000_i2c_suspend NULL
#define wm2000_i2c_resume NULL
#endif
static SIMPLE_DEV_PM_OPS(wm2000_pm, wm2000_i2c_suspend, wm2000_i2c_resume);
static const struct i2c_device_id wm2000_i2c_id[] = {
{ "wm2000", 0 },
{ }
......@@ -864,11 +865,10 @@ static struct i2c_driver wm2000_i2c_driver = {
.driver = {
.name = "wm2000",
.owner = THIS_MODULE,
.pm = &wm2000_pm,
},
.probe = wm2000_i2c_probe,
.remove = __devexit_p(wm2000_i2c_remove),
.suspend = wm2000_i2c_suspend,
.resume = wm2000_i2c_resume,
.shutdown = wm2000_i2c_shutdown,
.id_table = wm2000_i2c_id,
};
......
......@@ -58,7 +58,7 @@ static const u16 wm8523_reg[WM8523_REGISTER_COUNT] = {
0x0000, /* R8 - ZERO_DETECT */
};
static int wm8523_volatile_register(unsigned int reg)
static int wm8523_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
{
switch (reg) {
case WM8523_DEVICE_ID:
......@@ -414,7 +414,6 @@ static int wm8523_resume(struct snd_soc_codec *codec)
static int wm8523_probe(struct snd_soc_codec *codec)
{
struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
u16 *reg_cache = codec->reg_cache;
int ret, i;
codec->hw_write = (hw_write_t)i2c_master_send;
......@@ -471,8 +470,9 @@ static int wm8523_probe(struct snd_soc_codec *codec)
}
/* Change some default settings - latch VU and enable ZC */
reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
snd_soc_update_bits(codec, WM8523_DAC_GAINR,
WM8523_DACR_VU, WM8523_DACR_VU);
snd_soc_update_bits(codec, WM8523_DAC_CTRL3, WM8523_ZC, WM8523_ZC);
wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
......
......@@ -421,7 +421,6 @@ static int wm8741_resume(struct snd_soc_codec *codec)
static int wm8741_probe(struct snd_soc_codec *codec)
{
struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
u16 *reg_cache = codec->reg_cache;
int ret = 0;
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type);
......@@ -437,10 +436,14 @@ static int wm8741_probe(struct snd_soc_codec *codec)
}
/* Change some default settings - latch VU */
reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL;
reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM;
reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL;
reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM;
snd_soc_update_bits(codec, WM8741_DACLLSB_ATTENUATION,
WM8741_UPDATELL, WM8741_UPDATELL);
snd_soc_update_bits(codec, WM8741_DACLMSB_ATTENUATION,
WM8741_UPDATELM, WM8741_UPDATELM);
snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION,
WM8741_UPDATERL, WM8741_UPDATERL);
snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION,
WM8741_UPDATERM, WM8741_UPDATERM);
snd_soc_add_controls(codec, wm8741_snd_controls,
ARRAY_SIZE(wm8741_snd_controls));
......
此差异已折叠。
......@@ -175,7 +175,7 @@ static int txsrc_put(struct snd_kcontrol *kcontrol,
return 0;
}
static int wm8804_volatile(unsigned int reg)
static int wm8804_volatile(struct snd_soc_codec *codec, unsigned int reg)
{
switch (reg) {
case WM8804_RST_DEVID1:
......
......@@ -180,7 +180,7 @@ static const u16 wm8900_reg_defaults[WM8900_MAXREG] = {
/* Remaining registers all zero */
};
static int wm8900_volatile_register(unsigned int reg)
static int wm8900_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
{
switch (reg) {
case WM8900_REG_ID:
......
此差异已折叠。
......@@ -75,6 +75,14 @@ extern int wm8903_mic_detect(struct snd_soc_codec *codec,
#define WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0 0x41
#define WM8903_DC_SERVO_0 0x43
#define WM8903_DC_SERVO_2 0x45
#define WM8903_DC_SERVO_4 0x47
#define WM8903_DC_SERVO_5 0x48
#define WM8903_DC_SERVO_6 0x49
#define WM8903_DC_SERVO_7 0x4A
#define WM8903_DC_SERVO_READBACK_1 0x51
#define WM8903_DC_SERVO_READBACK_2 0x52
#define WM8903_DC_SERVO_READBACK_3 0x53
#define WM8903_DC_SERVO_READBACK_4 0x54
#define WM8903_ANALOGUE_HP_0 0x5A
#define WM8903_ANALOGUE_LINEOUT_0 0x5E
#define WM8903_CHARGE_PUMP_0 0x62
......
......@@ -596,7 +596,7 @@ static struct {
{ 0x003F, 0x003F, 0 }, /* R248 - FLL NCO Test 1 */
};
static int wm8904_volatile_register(unsigned int reg)
static int wm8904_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
{
return wm8904_access[reg].vol;
}
......@@ -2436,19 +2436,28 @@ static int wm8904_probe(struct snd_soc_codec *codec)
}
/* Change some default settings - latch VU and enable ZC */
reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU;
reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU;
reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU;
reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU;
reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU |
WM8904_HPOUTLZC;
reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU |
WM8904_HPOUTRZC;
reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU |
WM8904_LINEOUTLZC;
reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU |
WM8904_LINEOUTRZC;
reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE;
snd_soc_update_bits(codec, WM8904_ADC_DIGITAL_VOLUME_LEFT,
WM8904_ADC_VU, WM8904_ADC_VU);
snd_soc_update_bits(codec, WM8904_ADC_DIGITAL_VOLUME_RIGHT,
WM8904_ADC_VU, WM8904_ADC_VU);
snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_VOLUME_LEFT,
WM8904_DAC_VU, WM8904_DAC_VU);
snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_VOLUME_RIGHT,
WM8904_DAC_VU, WM8904_DAC_VU);
snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT1_LEFT,
WM8904_HPOUT_VU | WM8904_HPOUTLZC,
WM8904_HPOUT_VU | WM8904_HPOUTLZC);
snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT1_RIGHT,
WM8904_HPOUT_VU | WM8904_HPOUTRZC,
WM8904_HPOUT_VU | WM8904_HPOUTRZC);
snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT2_LEFT,
WM8904_LINEOUT_VU | WM8904_LINEOUTLZC,
WM8904_LINEOUT_VU | WM8904_LINEOUTLZC);
snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT2_RIGHT,
WM8904_LINEOUT_VU | WM8904_LINEOUTRZC,
WM8904_LINEOUT_VU | WM8904_LINEOUTRZC);
snd_soc_update_bits(codec, WM8904_CLOCK_RATES_0,
WM8904_SR_MODE, 0);
/* Apply configuration from the platform data. */
if (wm8904->pdata) {
......@@ -2469,10 +2478,12 @@ static int wm8904_probe(struct snd_soc_codec *codec)
/* Set Class W by default - this will be managed by the Class
* G widget at runtime where bypass paths are available.
*/
reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR;
snd_soc_update_bits(codec, WM8904_CLASS_W_0,
WM8904_CP_DYN_PWR, WM8904_CP_DYN_PWR);
/* Use normal bias source */
reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL;
snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0,
WM8904_POBCTRL, 0);
wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
......
......@@ -934,16 +934,27 @@ static int wm8955_probe(struct snd_soc_codec *codec)
}
/* Change some default settings - latch VU and enable ZC */
reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU;
reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU;
reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC;
reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC;
reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC;
reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC;
reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC;
snd_soc_update_bits(codec, WM8955_LEFT_DAC_VOLUME,
WM8955_LDVU, WM8955_LDVU);
snd_soc_update_bits(codec, WM8955_RIGHT_DAC_VOLUME,
WM8955_RDVU, WM8955_RDVU);
snd_soc_update_bits(codec, WM8955_LOUT1_VOLUME,
WM8955_LO1VU | WM8955_LO1ZC,
WM8955_LO1VU | WM8955_LO1ZC);
snd_soc_update_bits(codec, WM8955_ROUT1_VOLUME,
WM8955_RO1VU | WM8955_RO1ZC,
WM8955_RO1VU | WM8955_RO1ZC);
snd_soc_update_bits(codec, WM8955_LOUT2_VOLUME,
WM8955_LO2VU | WM8955_LO2ZC,
WM8955_LO2VU | WM8955_LO2ZC);
snd_soc_update_bits(codec, WM8955_ROUT2_VOLUME,
WM8955_RO2VU | WM8955_RO2ZC,
WM8955_RO2VU | WM8955_RO2ZC);
snd_soc_update_bits(codec, WM8955_MONOOUT_VOLUME,
WM8955_MOZC, WM8955_MOZC);
/* Also enable adaptive bass boost by default */
reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB;
snd_soc_update_bits(codec, WM8955_BASS_CONTROL, WM8955_BB, WM8955_BB);
/* Set platform data values */
if (pdata) {
......
......@@ -291,7 +291,7 @@ struct wm8961_priv {
int sysclk;
};
static int wm8961_volatile_register(unsigned int reg)
static int wm8961_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
{
switch (reg) {
case WM8961_SOFTWARE_RESET:
......
......@@ -1938,7 +1938,7 @@ static const struct wm8962_reg_access {
[21139] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21139 - VSS_XTS32_0 */
};
static int wm8962_volatile_register(unsigned int reg)
static int wm8962_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
{
if (wm8962_reg_access[reg].vol)
return 1;
......@@ -1946,7 +1946,7 @@ static int wm8962_volatile_register(unsigned int reg)
return 0;
}
static int wm8962_readable_register(unsigned int reg)
static int wm8962_readable_register(struct snd_soc_codec *codec, unsigned int reg)
{
if (wm8962_reg_access[reg].read)
return 1;
......@@ -3635,7 +3635,7 @@ static void wm8962_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
struct snd_soc_codec *codec = wm8962->codec;
snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset,
WM8962_GP2_LVL, value << WM8962_GP2_LVL_SHIFT);
WM8962_GP2_LVL, !!value << WM8962_GP2_LVL_SHIFT);
}
static int wm8962_gpio_direction_out(struct gpio_chip *chip,
......@@ -3822,16 +3822,26 @@ static int wm8962_probe(struct snd_soc_codec *codec)
}
/* Latch volume update bits */
reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU;
reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU;
reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU;
reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU;
reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU;
reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU;
reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU;
reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU;
reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU;
reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU;
snd_soc_update_bits(codec, WM8962_LEFT_INPUT_VOLUME,
WM8962_IN_VU, WM8962_IN_VU);
snd_soc_update_bits(codec, WM8962_RIGHT_INPUT_VOLUME,
WM8962_IN_VU, WM8962_IN_VU);
snd_soc_update_bits(codec, WM8962_LEFT_ADC_VOLUME,
WM8962_ADC_VU, WM8962_ADC_VU);
snd_soc_update_bits(codec, WM8962_RIGHT_ADC_VOLUME,
WM8962_ADC_VU, WM8962_ADC_VU);
snd_soc_update_bits(codec, WM8962_LEFT_DAC_VOLUME,
WM8962_DAC_VU, WM8962_DAC_VU);
snd_soc_update_bits(codec, WM8962_RIGHT_DAC_VOLUME,
WM8962_DAC_VU, WM8962_DAC_VU);
snd_soc_update_bits(codec, WM8962_SPKOUTL_VOLUME,
WM8962_SPKOUT_VU, WM8962_SPKOUT_VU);
snd_soc_update_bits(codec, WM8962_SPKOUTR_VOLUME,
WM8962_SPKOUT_VU, WM8962_SPKOUT_VU);
snd_soc_update_bits(codec, WM8962_HPOUTL_VOLUME,
WM8962_HPOUT_VU, WM8962_HPOUT_VU);
snd_soc_update_bits(codec, WM8962_HPOUTR_VOLUME,
WM8962_HPOUT_VU, WM8962_HPOUT_VU);
wm8962_add_widgets(codec);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册