Commit 7b8ab38e authored by Mark Brown's avatar Mark Brown

Merge tag 'asoc-v3.18' into asoc-linus

ASoC: Updates for v3.18

 - More componentisation work from Lars-Peter, this time mainly
   cleaning up the suspend and bias level transition callbacks.
 - Real system support for the Intel drivers and a bunch of fixes and
   enhancements for the associated CODEC drivers, this is going to need
   a lot quirks over time due to the lack of any firmware description of
   the boards.
 - Jack detect support for simple card from Dylan Reid.
 - A bunch of small fixes and enhancements for the Freescale drivers.
 - New drivers for Analog Devices SSM4567, Cirrus Logic CS35L32, Everest
   Semiconductor ES8328 and Freescale cards using the ASRC in newer i.MX
   processors.

# gpg: Signature made Mon 06 Oct 2014 12:49:37 BST using RSA key ID 5D5487D0
# gpg: Good signature from "Mark Brown <broonie@sirena.org.uk>"
# gpg:                 aka "Mark Brown <broonie@debian.org>"
# gpg:                 aka "Mark Brown <broonie@kernel.org>"
# gpg:                 aka "Mark Brown <broonie@tardis.ed.ac.uk>"
# gpg:                 aka "Mark Brown <broonie@linaro.org>"
# gpg:                 aka "Mark Brown <Mark.Brown@linaro.org>"
parents 1db1d4ee a5448c88
Device-Tree binding for regmap
The endianness mode of CPU & Device scenarios:
Index Device Endianness properties
---------------------------------------------------
1 BE 'big-endian'
2 LE 'little-endian'
For one device driver, which will run in different scenarios above
on different SoCs using the devicetree, we need one way to simplify
this.
Required properties:
- {big,little}-endian: these are boolean properties, if absent
meaning that the CPU and the Device are in the same endianness mode,
these properties are for register values and all the buffers only.
Examples:
Scenario 1 : CPU in LE mode & device in LE mode.
dev: dev@40031000 {
compatible = "name";
reg = <0x40031000 0x1000>;
...
};
Scenario 2 : CPU in LE mode & device in BE mode.
dev: dev@40031000 {
compatible = "name";
reg = <0x40031000 0x1000>;
...
big-endian;
};
Scenario 3 : CPU in BE mode & device in BE mode.
dev: dev@40031000 {
compatible = "name";
reg = <0x40031000 0x1000>;
...
};
Scenario 4 : CPU in BE mode & device in LE mode.
dev: dev@40031000 {
compatible = "name";
reg = <0x40031000 0x1000>;
...
little-endian;
};
Analog Devices SSM2602, SSM2603 and SSM2604 I2S audio CODEC devices
SSM2602 support both I2C and SPI as the configuration interface,
the selection is made by the MODE strap-in pin.
SSM2603 and SSM2604 only support I2C as the configuration interface.
Required properties:
- compatible : One of "adi,ssm2602", "adi,ssm2603" or "adi,ssm2604"
- reg : the I2C address of the device for I2C, the chip select
number for SPI.
Example:
ssm2602: ssm2602@1a {
compatible = "adi,ssm2602";
reg = <0x1a>;
};
CS35L32 audio CODEC
Required properties:
- compatible : "cirrus,cs35l32"
- reg : the I2C address of the device for I2C. Address is determined by the level
of the AD0 pin. Level 0 is 0x40 while Level 1 is 0x41.
- VA-supply, VP-supply : power supplies for the device,
as covered in Documentation/devicetree/bindings/regulator/regulator.txt.
Optional properties:
- reset-gpios : a GPIO spec for the reset pin. If specified, it will be
deasserted before communication to the codec starts.
- cirrus,boost-manager : Boost voltage control.
0 = Automatically managed. Boost-converter output voltage is the higher
of the two: Class G or adaptive LED voltage.
1 = Automatically managed irrespective of audio, adapting for low-power
dissipation when LEDs are ON, and operating in Fixed-Boost Bypass Mode
if LEDs are OFF (VBST = VP).
2 = (Default) Boost voltage fixed in Bypass Mode (VBST = VP).
3 = Boost voltage fixed at 5 V.
- cirrus,sdout-datacfg : Data configuration for dual CS35L32 applications only.
Determines the data packed in a two-CS35L32 configuration.
0 = Left/right channels VMON[11:0], IMON[11:0], VPMON[7:0].
1 = Left/right channels VMON[11:0], IMON[11:0], STATUS.
2 = (Default) left/right channels VMON[15:0], IMON [15:0].
3 = Left/right channels VPMON[7:0], STATUS.
- cirrus,sdout-share : SDOUT sharing. Determines whether one or two CS35L32
devices are on board sharing SDOUT.
0 = (Default) One IC.
1 = Two IC's.
- cirrus,battery-recovery : Low battery nominal recovery threshold, rising VP.
0 = 3.1V
1 = 3.2V
2 = 3.3V (Default)
3 = 3.4V
- cirrus,battery-threshold : Low battery nominal threshold, falling VP.
0 = 3.1V
1 = 3.2V
2 = 3.3V
3 = 3.4V (Default)
4 = 3.5V
5 = 3.6V
Example:
codec: codec@40 {
compatible = "cirrus,cs35l32";
reg = <0x40>;
reset-gpios = <&gpio 10 0>;
cirrus,boost-manager = <0x03>;
cirrus,sdout-datacfg = <0x02>;
VA-supply = <&reg_audio>;
};
Everest ES8328 audio CODEC
This device supports both I2C and SPI.
Required properties:
- compatible : "everest,es8328"
- DVDD-supply : Regulator providing digital core supply voltage 1.8 - 3.6V
- AVDD-supply : Regulator providing analog supply voltage 3.3V
- PVDD-supply : Regulator providing digital IO supply voltage 1.8 - 3.6V
- IPVDD-supply : Regulator providing analog output voltage 3.3V
- clocks : A 22.5792 or 11.2896 MHz clock
- reg : the I2C address of the device for I2C, the chip select number for SPI
Pins on the device (for linking into audio routes):
* LOUT1
* LOUT2
* ROUT1
* ROUT2
* LINPUT1
* RINPUT1
* LINPUT2
* RINPUT2
* Mic Bias
Example:
codec: es8328@11 {
compatible = "everest,es8328";
DVDD-supply = <&reg_3p3v>;
AVDD-supply = <&reg_3p3v>;
PVDD-supply = <&reg_3p3v>;
HPVDD-supply = <&reg_3p3v>;
clocks = <&clks 169>;
reg = <0x11>;
};
......@@ -7,7 +7,8 @@ other DSPs. It has up to six transmitters and four receivers.
Required properties:
- compatible : Compatible list, must contain "fsl,imx35-esai".
- compatible : Compatible list, must contain "fsl,imx35-esai" or
"fsl,vf610-esai"
- reg : Offset and length of the register set for the device.
......
......@@ -58,13 +58,7 @@ Optional properties:
Documentation/devicetree/bindings/dma/dma.txt.
- dma-names: Two dmas have to be defined, "tx" and "rx", if fsl,imx-fiq
is not defined.
- fsl,mode: The operating mode for the SSI interface.
"i2s-slave" - I2S mode, SSI is clock slave
"i2s-master" - I2S mode, SSI is clock master
"lj-slave" - left-justified mode, SSI is clock slave
"lj-master" - l.j. mode, SSI is clock master
"rj-slave" - right-justified mode, SSI is clock slave
"rj-master" - r.j., SSI is clock master
- fsl,mode: The operating mode for the AC97 interface only.
"ac97-slave" - AC97 mode, SSI is clock slave
"ac97-master" - AC97 mode, SSI is clock master
......
Freescale Generic ASoC Sound Card with ASRC support
The Freescale Generic ASoC Sound Card can be used, ideally, for all Freescale
SoCs connecting with external CODECs.
The idea of this generic sound card is a bit like ASoC Simple Card. However,
for Freescale SoCs (especially those released in recent years), most of them
have ASRC (Documentation/devicetree/bindings/sound/fsl,asrc.txt) inside. And
this is a specific feature that might be painstakingly controlled and merged
into the Simple Card.
So having this generic sound card allows all Freescale SoC users to benefit
from the simplification of a new card support and the capability of the wide
sample rates support through ASRC.
Note: The card is initially designed for those sound cards who use I2S and
PCM DAI formats. However, it'll be also possible to support those non
I2S/PCM type sound cards, such as S/PDIF audio and HDMI audio, as long
as the driver has been properly upgraded.
The compatible list for this generic sound card currently:
"fsl,imx-audio-cs42888"
"fsl,imx-audio-wm8962"
(compatible with Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt)
"fsl,imx-audio-sgtl5000"
(compatible with Documentation/devicetree/bindings/sound/imx-audio-sgtl5000.txt)
Required properties:
- compatible : Contains one of entries in the compatible list.
- model : The user-visible name of this sound complex
- audio-cpu : The phandle of an CPU DAI controller
- audio-codec : The phandle of an audio codec
- audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the
connection's sink, the second being the connection's
source. There're a few pre-designed board connectors:
* Line Out Jack
* Line In Jack
* Headphone Jack
* Mic Jack
* Ext Spk
* AMIC (stands for Analog Microphone Jack)
* DMIC (stands for Digital Microphone Jack)
Note: The "Mic Jack" and "AMIC" are redundant while
coexsiting in order to support the old bindings
of wm8962 and sgtl5000.
Optional properties:
- audio-asrc : The phandle of ASRC. It can be absent if there's no
need to add ASRC support via DPCM.
Example:
sound-cs42888 {
compatible = "fsl,imx-audio-cs42888";
model = "cs42888-audio";
audio-cpu = <&esai>;
audio-asrc = <&asrc>;
audio-codec = <&cs42888>;
audio-routing =
"Line Out Jack", "AOUT1L",
"Line Out Jack", "AOUT1R",
"Line Out Jack", "AOUT2L",
"Line Out Jack", "AOUT2R",
"Line Out Jack", "AOUT3L",
"Line Out Jack", "AOUT3R",
"Line Out Jack", "AOUT4L",
"Line Out Jack", "AOUT4R",
"AIN1L", "Line In Jack",
"AIN1R", "Line In Jack",
"AIN2L", "Line In Jack",
"AIN2R", "Line In Jack";
};
......@@ -18,12 +18,26 @@ Required properties:
- pinctrl-names: Must contain a "default" entry.
- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
See ../pinctrl/pinctrl-bindings.txt for details of the property values.
- big-endian-regs: If this property is absent, the little endian mode will
be in use as default, or the big endian mode will be in use for all the
device registers.
- big-endian-data: If this property is absent, the little endian mode will
be in use as default, or the big endian mode will be in use for all the
fifo data.
- big-endian: Boolean property, required if all the FTM_PWM registers
are big-endian rather than little-endian.
- lsb-first: Configures whether the LSB or the MSB is transmitted first for
the fifo data. If this property is absent, the MSB is transmitted first as
default, or the LSB is transmitted first.
- fsl,sai-synchronous-rx: This is a boolean property. If present, indicating
that SAI will work in the synchronous mode (sync Tx with Rx) which means
both the transimitter and receiver will send and receive data by following
receiver's bit clocks and frame sync clocks.
- fsl,sai-asynchronous: This is a boolean property. If present, indicating
that SAI will work in the asynchronous mode, which means both transimitter
and receiver will send and receive data by following their own bit clocks
and frame sync clocks separately.
Note:
- If both fsl,sai-asynchronous and fsl,sai-synchronous-rx are absent, the
default synchronous mode (sync Rx with Tx) will be used, which means both
transimitter and receiver will send and receive data by following clocks
of transimitter.
- fsl,sai-asynchronous and fsl,sai-synchronous-rx are exclusive.
Example:
sai2: sai@40031000 {
......@@ -38,6 +52,6 @@ sai2: sai@40031000 {
dma-names = "tx", "rx";
dmas = <&edma0 0 VF610_EDMA_MUXID0_SAI2_TX>,
<&edma0 0 VF610_EDMA_MUXID0_SAI2_RX>;
big-endian-regs;
big-endian-data;
big-endian;
lsb-first;
};
Freescale i.MX audio complex with ES8328 codec
Required properties:
- compatible : "fsl,imx-audio-es8328"
- model : The user-visible name of this sound complex
- ssi-controller : The phandle of the i.MX SSI controller
- jack-gpio : Optional GPIO for headphone jack
- audio-amp-supply : Power regulator for speaker amps
- audio-codec : The phandle of the ES8328 audio codec
- audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the
connection's sink, the second being the connection's
source. Valid names could be power supplies, ES8328
pins, and the jacks on the board:
Power supplies:
* audio-amp
ES8328 pins:
* LOUT1
* LOUT2
* ROUT1
* ROUT2
* LINPUT1
* LINPUT2
* RINPUT1
* RINPUT2
* Mic PGA
Board connectors:
* Headphone
* Speaker
* Mic Jack
- mux-int-port : The internal port of the i.MX audio muxer (AUDMUX)
- mux-ext-port : The external port of the i.MX audio muxer (AUDMIX)
Note: The AUDMUX port numbering should start at 1, which is consistent with
hardware manual.
Example:
sound {
compatible = "fsl,imx-audio-es8328";
model = "imx-audio-es8328";
ssi-controller = <&ssi1>;
audio-codec = <&codec>;
jack-gpio = <&gpio5 15 0>;
audio-amp-supply = <&reg_audio_amp>;
audio-routing =
"Speaker", "LOUT2",
"Speaker", "ROUT2",
"Speaker", "audio-amp",
"Headphone", "ROUT1",
"Headphone", "LOUT1",
"LINPUT1", "Mic Jack",
"RINPUT1", "Mic Jack",
"Mic Jack", "Mic Bias";
mux-int-port = <1>;
mux-ext-port = <3>;
};
......@@ -25,6 +25,7 @@ Required properties:
Optional properties:
- nvidia,hp-det-gpios : The GPIO that detect headphones are plugged in
- nvidia,mic-det-gpios : The GPIO that detect microphones are plugged in
Example:
......
RT5677 audio CODEC
This device supports I2C only.
Required properties:
- compatible : "realtek,rt5677".
- reg : The I2C address of the device.
- interrupts : The CODEC's interrupt output.
- gpio-controller : Indicates this device is a GPIO controller.
- #gpio-cells : Should be two. The first cell is the pin number and the
second cell is used to specify optional parameters (currently unused).
Optional properties:
- realtek,pow-ldo2-gpio : The GPIO that controls the CODEC's POW_LDO2 pin.
- realtek,in1-differential
- realtek,in2-differential
- realtek,lout1-differential
- realtek,lout2-differential
- realtek,lout3-differential
Boolean. Indicate MIC1/2 input and LOUT1/2/3 outputs are differential,
rather than single-ended.
Pins on the device (for linking into audio routes):
* IN1P
* IN1N
* IN2P
* IN2N
* MICBIAS1
* DMIC1
* DMIC2
* DMIC3
* DMIC4
* LOUT1
* LOUT2
* LOUT3
Example:
rt5677 {
compatible = "realtek,rt5677";
reg = <0x2c>;
interrupt-parent = <&gpio>;
interrupts = <TEGRA_GPIO(W, 3) GPIO_ACTIVE_HIGH>;
gpio-controller;
#gpio-cells = <2>;
realtek,pow-ldo2-gpio =
<&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>;
realtek,in1-differential = "true";
};
......@@ -17,6 +17,10 @@ Optional properties:
source.
- simple-audio-card,mclk-fs : Multiplication factor between stream rate and codec
mclk.
- simple-audio-card,hp-det-gpio : Reference to GPIO that signals when
headphones are attached.
- simple-audio-card,mic-det-gpio : Reference to GPIO that signals when
a microphone is attached.
Optional subnodes:
......
Analog Devices SSM4567 audio amplifier
This device supports I2C only.
Required properties:
- compatible : Must be "adi,ssm4567"
- reg : the I2C address of the device. This will either be 0x34 (LR_SEL/ADDR connected to AGND),
0x35 (LR_SEL/ADDR connected to IOVDD) or 0x36 (LR_SEL/ADDR open).
Example:
ssm4567: ssm4567@34 {
compatible = "adi,ssm4567";
reg = <0x34>;
};
......@@ -48,6 +48,7 @@ epfl Ecole Polytechnique Fédérale de Lausanne
epson Seiko Epson Corp.
est ESTeem Wireless Modems
eukrea Eukréa Electromatique
everest Everest Semiconductor Co. Ltd.
excito Excito
fsl Freescale Semiconductor
GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc.
......
......@@ -168,6 +168,8 @@ static struct regmap_bus regmap_i2c = {
.write = regmap_i2c_write,
.gather_write = regmap_i2c_gather_write,
.read = regmap_i2c_read,
.reg_format_endian_default = REGMAP_ENDIAN_BIG,
.val_format_endian_default = REGMAP_ENDIAN_BIG,
};
static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
......
......@@ -109,6 +109,8 @@ static struct regmap_bus regmap_spi = {
.async_alloc = regmap_spi_async_alloc,
.read = regmap_spi_read,
.read_flag_mask = 0x80,
.reg_format_endian_default = REGMAP_ENDIAN_BIG,
.val_format_endian_default = REGMAP_ENDIAN_BIG,
};
/**
......
......@@ -15,6 +15,7 @@
#include <linux/export.h>
#include <linux/mutex.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/rbtree.h>
#include <linux/sched.h>
......@@ -448,6 +449,66 @@ int regmap_attach_dev(struct device *dev, struct regmap *map,
}
EXPORT_SYMBOL_GPL(regmap_attach_dev);
static enum regmap_endian regmap_get_reg_endian(const struct regmap_bus *bus,
const struct regmap_config *config)
{
enum regmap_endian endian;
/* Retrieve the endianness specification from the regmap config */
endian = config->reg_format_endian;
/* If the regmap config specified a non-default value, use that */
if (endian != REGMAP_ENDIAN_DEFAULT)
return endian;
/* Retrieve the endianness specification from the bus config */
if (bus && bus->reg_format_endian_default)
endian = bus->reg_format_endian_default;
/* If the bus specified a non-default value, use that */
if (endian != REGMAP_ENDIAN_DEFAULT)
return endian;
/* Use this if no other value was found */
return REGMAP_ENDIAN_BIG;
}
static enum regmap_endian regmap_get_val_endian(struct device *dev,
const struct regmap_bus *bus,
const struct regmap_config *config)
{
struct device_node *np = dev->of_node;
enum regmap_endian endian;
/* Retrieve the endianness specification from the regmap config */
endian = config->val_format_endian;
/* If the regmap config specified a non-default value, use that */
if (endian != REGMAP_ENDIAN_DEFAULT)
return endian;
/* Parse the device's DT node for an endianness specification */
if (of_property_read_bool(np, "big-endian"))
endian = REGMAP_ENDIAN_BIG;
else if (of_property_read_bool(np, "little-endian"))
endian = REGMAP_ENDIAN_LITTLE;
/* If the endianness was specified in DT, use that */
if (endian != REGMAP_ENDIAN_DEFAULT)
return endian;
/* Retrieve the endianness specification from the bus config */
if (bus && bus->val_format_endian_default)
endian = bus->val_format_endian_default;
/* If the bus specified a non-default value, use that */
if (endian != REGMAP_ENDIAN_DEFAULT)
return endian;
/* Use this if no other value was found */
return REGMAP_ENDIAN_BIG;
}
/**
* regmap_init(): Initialise register map
*
......@@ -551,17 +612,8 @@ struct regmap *regmap_init(struct device *dev,
map->reg_read = _regmap_bus_read;
}
reg_endian = config->reg_format_endian;
if (reg_endian == REGMAP_ENDIAN_DEFAULT)
reg_endian = bus->reg_format_endian_default;
if (reg_endian == REGMAP_ENDIAN_DEFAULT)
reg_endian = REGMAP_ENDIAN_BIG;
val_endian = config->val_format_endian;
if (val_endian == REGMAP_ENDIAN_DEFAULT)
val_endian = bus->val_format_endian_default;
if (val_endian == REGMAP_ENDIAN_DEFAULT)
val_endian = REGMAP_ENDIAN_BIG;
reg_endian = regmap_get_reg_endian(bus, config);
val_endian = regmap_get_val_endian(dev, bus, config);
switch (config->reg_bits + map->reg_shift) {
case 2:
......
#ifndef __DT_CS35L32_H
#define __DT_CS35L32_H
#define CS35L32_BOOST_MGR_AUTO 0
#define CS35L32_BOOST_MGR_AUTO_AUDIO 1
#define CS35L32_BOOST_MGR_BYPASS 2
#define CS35L32_BOOST_MGR_FIXED 3
#define CS35L32_DATA_CFG_LR_VP 0
#define CS35L32_DATA_CFG_LR_STAT 1
#define CS35L32_DATA_CFG_LR 2
#define CS35L32_DATA_CFG_LR_VPSTAT 3
#define CS35L32_BATT_THRESH_3_1V 0
#define CS35L32_BATT_THRESH_3_2V 1
#define CS35L32_BATT_THRESH_3_3V 2
#define CS35L32_BATT_THRESH_3_4V 3
#define CS35L32_BATT_RECOV_3_1V 0
#define CS35L32_BATT_RECOV_3_2V 1
#define CS35L32_BATT_RECOV_3_3V 2
#define CS35L32_BATT_RECOV_3_4V 3
#define CS35L32_BATT_RECOV_3_5V 4
#define CS35L32_BATT_RECOV_3_6V 5
#endif /* __DT_CS35L32_H */
......@@ -20,6 +20,9 @@ struct rt5645_platform_data {
/* 0 = IN2N; 1 = GPIO5; 2 = GPIO11 */
unsigned int dmic2_data_pin;
/* 0 = IN2P; 1 = GPIO6; 2 = GPIO10; 3 = GPIO12 */
unsigned int hp_det_gpio;
bool gpio_hp_det_active_high;
};
#endif
......@@ -12,10 +12,21 @@
#ifndef __LINUX_SND_RT5677_H
#define __LINUX_SND_RT5677_H
enum rt5677_dmic2_clk {
RT5677_DMIC_CLK1 = 0,
RT5677_DMIC_CLK2 = 1,
};
struct rt5677_platform_data {
/* IN1 IN2 can optionally be differential */
/* IN1/IN2/LOUT1/LOUT2/LOUT3 can optionally be differential */
bool in1_diff;
bool in2_diff;
bool lout1_diff;
bool lout2_diff;
bool lout3_diff;
/* DMIC2 clock source selection */
enum rt5677_dmic2_clk dmic2_clk_pin;
};
#endif
......@@ -432,6 +432,7 @@ int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
const char *pin);
void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card);
unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol);
/* Mostly internal - should not normally be used */
void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm);
......@@ -587,13 +588,13 @@ struct snd_soc_dapm_context {
enum snd_soc_bias_level suspend_bias_level;
struct delayed_work delayed_work;
unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
/* Go to BIAS_OFF in suspend if the DAPM context is idle */
unsigned int suspend_bias_off:1;
void (*seq_notifier)(struct snd_soc_dapm_context *,
enum snd_soc_dapm_type, int);
struct device *dev; /* from parent - for debug */
struct snd_soc_component *component; /* parent component */
struct snd_soc_codec *codec; /* parent codec */
struct snd_soc_card *card; /* parent card */
/* used during DAPM updates */
......
......@@ -690,6 +690,17 @@ struct snd_soc_compr_ops {
struct snd_soc_component_driver {
const char *name;
/* Default control and setup, added after probe() is run */
const struct snd_kcontrol_new *controls;
unsigned int num_controls;
const struct snd_soc_dapm_widget *dapm_widgets;
unsigned int num_dapm_widgets;
const struct snd_soc_dapm_route *dapm_routes;
unsigned int num_dapm_routes;
int (*probe)(struct snd_soc_component *);
void (*remove)(struct snd_soc_component *);
/* DT */
int (*of_xlate_dai_name)(struct snd_soc_component *component,
struct of_phandle_args *args,
......@@ -697,6 +708,10 @@ struct snd_soc_component_driver {
void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type,
int subseq);
int (*stream_event)(struct snd_soc_component *, int event);
/* probe ordering - for components with runtime dependencies */
int probe_order;
int remove_order;
};
struct snd_soc_component {
......@@ -710,6 +725,7 @@ struct snd_soc_component {
unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
unsigned int registered_as_component:1;
unsigned int probed:1;
struct list_head list;
......@@ -728,9 +744,35 @@ struct snd_soc_component {
struct mutex io_mutex;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_root;
#endif
/*
* DO NOT use any of the fields below in drivers, they are temporary and
* are going to be removed again soon. If you use them in driver code the
* driver will be marked as BROKEN when these fields are removed.
*/
/* Don't use these, use snd_soc_component_get_dapm() */
struct snd_soc_dapm_context dapm;
struct snd_soc_dapm_context *dapm_ptr;
const struct snd_kcontrol_new *controls;
unsigned int num_controls;
const struct snd_soc_dapm_widget *dapm_widgets;
unsigned int num_dapm_widgets;
const struct snd_soc_dapm_route *dapm_routes;
unsigned int num_dapm_routes;
struct snd_soc_codec *codec;
int (*probe)(struct snd_soc_component *);
void (*remove)(struct snd_soc_component *);
#ifdef CONFIG_DEBUG_FS
void (*init_debugfs)(struct snd_soc_component *component);
const char *debugfs_prefix;
#endif
};
/* SoC Audio Codec device */
......@@ -746,11 +788,9 @@ struct snd_soc_codec {
struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */
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 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 */
......@@ -766,7 +806,6 @@ struct snd_soc_codec {
struct snd_soc_dapm_context dapm;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_codec_root;
struct dentry *debugfs_reg;
#endif
};
......@@ -808,15 +847,12 @@ struct snd_soc_codec_driver {
int (*set_bias_level)(struct snd_soc_codec *,
enum snd_soc_bias_level level);
bool idle_bias_off;
bool suspend_bias_off;
void (*seq_notifier)(struct snd_soc_dapm_context *,
enum snd_soc_dapm_type, int);
bool ignore_pmdown_time; /* Doesn't benefit from pmdown delay */
/* probe ordering - for components with runtime dependencies */
int probe_order;
int remove_order;
};
/* SoC platform interface */
......@@ -832,14 +868,6 @@ struct snd_soc_platform_driver {
int (*pcm_new)(struct snd_soc_pcm_runtime *);
void (*pcm_free)(struct snd_pcm *);
/* Default control and setup, added after probe() is run */
const struct snd_kcontrol_new *controls;
int num_controls;
const struct snd_soc_dapm_widget *dapm_widgets;
int num_dapm_widgets;
const struct snd_soc_dapm_route *dapm_routes;
int num_dapm_routes;
/*
* For platform caused delay reporting.
* Optional.
......@@ -853,13 +881,6 @@ struct snd_soc_platform_driver {
/* platform stream compress ops */
const struct snd_compr_ops *compr_ops;
/* probe ordering - for components with runtime dependencies */
int probe_order;
int remove_order;
/* platform IO - used for platform DAPM */
unsigned int (*read)(struct snd_soc_platform *, unsigned int);
int (*write)(struct snd_soc_platform *, unsigned int, unsigned int);
int (*bespoke_trigger)(struct snd_pcm_substream *, int);
};
......@@ -874,15 +895,10 @@ struct snd_soc_platform {
const struct snd_soc_platform_driver *driver;
unsigned int suspended:1; /* platform is suspended */
unsigned int probed:1;
struct list_head list;
struct snd_soc_component component;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_platform_root;
#endif
};
struct snd_soc_dai_link {
......@@ -897,7 +913,7 @@ struct snd_soc_dai_link {
* only for codec to codec links, or systems using device tree.
*/
const char *cpu_name;
const struct device_node *cpu_of_node;
struct device_node *cpu_of_node;
/*
* You MAY specify the DAI name of the CPU DAI. If this information is
* omitted, the CPU-side DAI is matched using .cpu_name/.cpu_of_node
......@@ -909,7 +925,7 @@ struct snd_soc_dai_link {
* DT/OF node, but not both.
*/
const char *codec_name;
const struct device_node *codec_of_node;
struct device_node *codec_of_node;
/* You MUST specify the DAI name within the codec */
const char *codec_dai_name;
......@@ -922,7 +938,7 @@ struct snd_soc_dai_link {
* do not need a platform.
*/
const char *platform_name;
const struct device_node *platform_of_node;
struct device_node *platform_of_node;
int be_id; /* optional ID for machine driver BE identification */
const struct snd_soc_pcm_stream *params;
......@@ -994,7 +1010,7 @@ struct snd_soc_aux_dev {
const struct device_node *codec_of_node;
/* codec/machine specific init - e.g. add machine controls */
int (*init)(struct snd_soc_dapm_context *dapm);
int (*init)(struct snd_soc_component *component);
};
/* SoC card */
......@@ -1112,6 +1128,7 @@ struct snd_soc_pcm_runtime {
struct snd_soc_platform *platform;
struct snd_soc_dai *codec_dai;
struct snd_soc_dai *cpu_dai;
struct snd_soc_component *component; /* Only valid for AUX dev rtds */
struct snd_soc_dai **codec_dais;
unsigned int num_codecs;
......@@ -1260,9 +1277,6 @@ void snd_soc_component_async_complete(struct snd_soc_component *component);
int snd_soc_component_test_bits(struct snd_soc_component *component,
unsigned int reg, unsigned int mask, unsigned int value);
int snd_soc_component_init_io(struct snd_soc_component *component,
struct regmap *regmap);
/* device driver data */
static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card,
......@@ -1276,26 +1290,37 @@ static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card)
return card->drvdata;
}
static inline void snd_soc_component_set_drvdata(struct snd_soc_component *c,
void *data)
{
dev_set_drvdata(c->dev, data);
}
static inline void *snd_soc_component_get_drvdata(struct snd_soc_component *c)
{
return dev_get_drvdata(c->dev);
}
static inline void snd_soc_codec_set_drvdata(struct snd_soc_codec *codec,
void *data)
{
dev_set_drvdata(codec->dev, data);
snd_soc_component_set_drvdata(&codec->component, data);
}
static inline void *snd_soc_codec_get_drvdata(struct snd_soc_codec *codec)
{
return dev_get_drvdata(codec->dev);
return snd_soc_component_get_drvdata(&codec->component);
}
static inline void snd_soc_platform_set_drvdata(struct snd_soc_platform *platform,
void *data)
{
dev_set_drvdata(platform->dev, data);
snd_soc_component_set_drvdata(&platform->component, data);
}
static inline void *snd_soc_platform_get_drvdata(struct snd_soc_platform *platform)
{
return dev_get_drvdata(platform->dev);
return snd_soc_component_get_drvdata(&platform->component);
}
static inline void snd_soc_pcm_set_drvdata(struct snd_soc_pcm_runtime *rtd,
......
......@@ -175,7 +175,7 @@ TRACE_EVENT(snd_soc_dapm_output_path,
__entry->path_sink = (long)path->sink;
),
TP_printk("%c%s -> %s -> %s\n",
TP_printk("%c%s -> %s -> %s",
(int) __entry->path_sink &&
(int) __entry->path_connect ? '*' : ' ',
__get_str(wname), __get_str(pname), __get_str(psname))
......@@ -204,7 +204,7 @@ TRACE_EVENT(snd_soc_dapm_input_path,
__entry->path_source = (long)path->source;
),
TP_printk("%c%s <- %s <- %s\n",
TP_printk("%c%s <- %s <- %s",
(int) __entry->path_source &&
(int) __entry->path_connect ? '*' : ' ',
__get_str(wname), __get_str(pname), __get_str(psname))
......@@ -226,7 +226,7 @@ TRACE_EVENT(snd_soc_dapm_connected,
__entry->stream = stream;
),
TP_printk("%s: found %d paths\n",
TP_printk("%s: found %d paths",
__entry->stream ? "capture" : "playback", __entry->paths)
);
......
......@@ -1337,8 +1337,6 @@ static int pm860x_probe(struct snd_soc_codec *codec)
}
}
pm860x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
out:
......@@ -1354,7 +1352,6 @@ static int pm860x_remove(struct snd_soc_codec *codec)
for (i = 3; i >= 0; i--)
free_irq(pm860x->irq[i], pm860x);
pm860x_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
......
......@@ -43,6 +43,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_ALC5623 if I2C
select SND_SOC_ALC5632 if I2C
select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
select SND_SOC_CS35L32 if I2C
select SND_SOC_CS42L51_I2C if I2C
select SND_SOC_CS42L52 if I2C && INPUT
select SND_SOC_CS42L56 if I2C && INPUT
......@@ -56,7 +57,10 @@ config SND_SOC_ALL_CODECS
select SND_SOC_DA7213 if I2C
select SND_SOC_DA732X if I2C
select SND_SOC_DA9055 if I2C
select SND_SOC_DMIC
select SND_SOC_BT_SCO
select SND_SOC_ES8328_SPI if SPI_MASTER
select SND_SOC_ES8328_I2C if I2C
select SND_SOC_ISABELLE if I2C
select SND_SOC_JZ4740_CODEC
select SND_SOC_LM4857 if I2C
......@@ -90,6 +94,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_SSM2518 if I2C
select SND_SOC_SSM2602_SPI if SPI_MASTER
select SND_SOC_SSM2602_I2C if I2C
select SND_SOC_SSM4567 if I2C
select SND_SOC_STA32X if I2C
select SND_SOC_STA350 if I2C
select SND_SOC_STA529 if I2C
......@@ -323,6 +328,10 @@ config SND_SOC_ALC5632
config SND_SOC_CQ0093VC
tristate
config SND_SOC_CS35L32
tristate "Cirrus Logic CS35L32 CODEC"
depends on I2C
config SND_SOC_CS42L51
tristate
......@@ -405,6 +414,17 @@ config SND_SOC_DMIC
config SND_SOC_HDMI_CODEC
tristate "HDMI stub CODEC"
config SND_SOC_ES8328
tristate "Everest Semi ES8328 CODEC"
config SND_SOC_ES8328_I2C
tristate
select SND_SOC_ES8328
config SND_SOC_ES8328_SPI
tristate
select SND_SOC_ES8328
config SND_SOC_ISABELLE
tristate
......@@ -464,6 +484,7 @@ config SND_SOC_RL6231
config SND_SOC_RT286
tristate
depends on I2C
config SND_SOC_RT5631
tristate
......@@ -520,12 +541,20 @@ config SND_SOC_SSM2602
tristate
config SND_SOC_SSM2602_SPI
tristate "Analog Devices SSM2602 CODEC - SPI"
depends on SPI_MASTER
select SND_SOC_SSM2602
tristate
select REGMAP_SPI
config SND_SOC_SSM2602_I2C
tristate "Analog Devices SSM2602 CODEC - I2C"
depends on I2C
select SND_SOC_SSM2602
tristate
select REGMAP_I2C
config SND_SOC_SSM4567
tristate "Analog Devices ssm4567 amplifier driver support"
depends on I2C
config SND_SOC_STA32X
tristate
......@@ -712,7 +741,8 @@ config SND_SOC_WM8974
tristate
config SND_SOC_WM8978
tristate
tristate "Wolfson Microelectronics WM8978 codec"
depends on I2C
config SND_SOC_WM8983
tristate
......
......@@ -32,6 +32,7 @@ snd-soc-ak4671-objs := ak4671.o
snd-soc-ak5386-objs := ak5386.o
snd-soc-arizona-objs := arizona.o
snd-soc-cq93vc-objs := cq93vc.o
snd-soc-cs35l32-objs := cs35l32.o
snd-soc-cs42l51-objs := cs42l51.o
snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o
snd-soc-cs42l52-objs := cs42l52.o
......@@ -49,6 +50,9 @@ snd-soc-da732x-objs := da732x.o
snd-soc-da9055-objs := da9055.o
snd-soc-bt-sco-objs := bt-sco.o
snd-soc-dmic-objs := dmic.o
snd-soc-es8328-objs := es8328.o
snd-soc-es8328-i2c-objs := es8328-i2c.o
snd-soc-es8328-spi-objs := es8328-spi.o
snd-soc-isabelle-objs := isabelle.o
snd-soc-jz4740-codec-objs := jz4740.o
snd-soc-l3-objs := l3.o
......@@ -91,6 +95,7 @@ snd-soc-ssm2518-objs := ssm2518.o
snd-soc-ssm2602-objs := ssm2602.o
snd-soc-ssm2602-spi-objs := ssm2602-spi.o
snd-soc-ssm2602-i2c-objs := ssm2602-i2c.o
snd-soc-ssm4567-objs := ssm4567.o
snd-soc-sta32x-objs := sta32x.o
snd-soc-sta350-objs := sta350.o
snd-soc-sta529-objs := sta529.o
......@@ -203,6 +208,7 @@ obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o
obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o
obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o
obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
obj-$(CONFIG_SND_SOC_CS35L32) += snd-soc-cs35l32.o
obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o
obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o
obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o
......@@ -220,6 +226,9 @@ obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o
obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o
obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o
obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o
obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o
obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o
obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o
obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
......@@ -258,6 +267,7 @@ obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o
obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
obj-$(CONFIG_SND_SOC_SSM2602_SPI) += snd-soc-ssm2602-spi.o
obj-$(CONFIG_SND_SOC_SSM2602_I2C) += snd-soc-ssm2602-i2c.o
obj-$(CONFIG_SND_SOC_SSM4567) += snd-soc-ssm4567.o
obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o
obj-$(CONFIG_SND_SOC_STA350) += snd-soc-sta350.o
obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o
......
......@@ -56,8 +56,7 @@
#define GPIO31_DIR_OUTPUT 0x40
/* Macrocell register definitions */
#define AB8500_CTRL3_REG 0x0200
#define AB8500_GPIO_DIR4_REG 0x1013
#define AB8500_GPIO_DIR4_REG 0x13 /* Bank AB8500_MISC */
/* Nr of FIR/IIR-coeff banks in ANC-block */
#define AB8500_NR_OF_ANC_COEFF_BANKS 2
......@@ -126,6 +125,8 @@ struct ab8500_codec_drvdata_dbg {
/* Private data for AB8500 device-driver */
struct ab8500_codec_drvdata {
struct regmap *regmap;
/* Sidetone */
long *sid_fir_values;
enum sid_state sid_status;
......@@ -166,49 +167,35 @@ static inline const char *amic_type_str(enum amic_type type)
*/
/* Read a register from the audio-bank of AB8500 */
static unsigned int ab8500_codec_read_reg(struct snd_soc_codec *codec,
unsigned int reg)
static int ab8500_codec_read_reg(void *context, unsigned int reg,
unsigned int *value)
{
struct device *dev = context;
int status;
unsigned int value = 0;
u8 value8;
status = abx500_get_register_interruptible(codec->dev, AB8500_AUDIO,
reg, &value8);
if (status < 0) {
dev_err(codec->dev,
"%s: ERROR: Register (0x%02x:0x%02x) read failed (%d).\n",
__func__, (u8)AB8500_AUDIO, (u8)reg, status);
} else {
dev_dbg(codec->dev,
"%s: Read 0x%02x from register 0x%02x:0x%02x\n",
__func__, value8, (u8)AB8500_AUDIO, (u8)reg);
value = (unsigned int)value8;
}
status = abx500_get_register_interruptible(dev, AB8500_AUDIO,
reg, &value8);
*value = (unsigned int)value8;
return value;
return status;
}
/* Write to a register in the audio-bank of AB8500 */
static int ab8500_codec_write_reg(struct snd_soc_codec *codec,
unsigned int reg, unsigned int value)
static int ab8500_codec_write_reg(void *context, unsigned int reg,
unsigned int value)
{
int status;
status = abx500_set_register_interruptible(codec->dev, AB8500_AUDIO,
reg, value);
if (status < 0)
dev_err(codec->dev,
"%s: ERROR: Register (%02x:%02x) write failed (%d).\n",
__func__, (u8)AB8500_AUDIO, (u8)reg, status);
else
dev_dbg(codec->dev,
"%s: Wrote 0x%02x into register %02x:%02x\n",
__func__, (u8)value, (u8)AB8500_AUDIO, (u8)reg);
struct device *dev = context;
return status;
return abx500_set_register_interruptible(dev, AB8500_AUDIO,
reg, value);
}
static const struct regmap_config ab8500_codec_regmap = {
.reg_read = ab8500_codec_read_reg,
.reg_write = ab8500_codec_write_reg,
};
/*
* Controls - DAPM
*/
......@@ -1968,16 +1955,16 @@ static int ab8500_audio_setup_mics(struct snd_soc_codec *codec,
dev_dbg(codec->dev, "%s: Enter.\n", __func__);
/* Set DMic-clocks to outputs */
status = abx500_get_register_interruptible(codec->dev, (u8)AB8500_MISC,
(u8)AB8500_GPIO_DIR4_REG,
status = abx500_get_register_interruptible(codec->dev, AB8500_MISC,
AB8500_GPIO_DIR4_REG,
&value8);
if (status < 0)
return status;
value = value8 | GPIO27_DIR_OUTPUT | GPIO29_DIR_OUTPUT |
GPIO31_DIR_OUTPUT;
status = abx500_set_register_interruptible(codec->dev,
(u8)AB8500_MISC,
(u8)AB8500_GPIO_DIR4_REG,
AB8500_MISC,
AB8500_GPIO_DIR4_REG,
value);
if (status < 0)
return status;
......@@ -2565,9 +2552,6 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver ab8500_codec_driver = {
.probe = ab8500_codec_probe,
.read = ab8500_codec_read_reg,
.write = ab8500_codec_write_reg,
.reg_word_size = sizeof(u8),
.controls = ab8500_ctrls,
.num_controls = ARRAY_SIZE(ab8500_ctrls),
.dapm_widgets = ab8500_dapm_widgets,
......@@ -2592,6 +2576,15 @@ static int ab8500_codec_driver_probe(struct platform_device *pdev)
drvdata->anc_status = ANC_UNCONFIGURED;
dev_set_drvdata(&pdev->dev, drvdata);
drvdata->regmap = devm_regmap_init(&pdev->dev, NULL, &pdev->dev,
&ab8500_codec_regmap);
if (IS_ERR(drvdata->regmap)) {
status = PTR_ERR(drvdata->regmap);
dev_err(&pdev->dev, "%s: Failed to allocate regmap: %d\n",
__func__, status);
return status;
}
dev_dbg(&pdev->dev, "%s: Register codec.\n", __func__);
status = snd_soc_register_codec(&pdev->dev, &ab8500_codec_driver,
ab8500_codec_dai,
......
......@@ -69,19 +69,6 @@ static struct snd_soc_dai_driver ac97_dai = {
.ops = &ac97_dai_ops,
};
static unsigned int ac97_read(struct snd_soc_codec *codec,
unsigned int reg)
{
return soc_ac97_ops->read(codec->ac97, reg);
}
static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int val)
{
soc_ac97_ops->write(codec->ac97, reg, val);
return 0;
}
static int ac97_soc_probe(struct snd_soc_codec *codec)
{
struct snd_ac97_bus *ac97_bus;
......@@ -122,8 +109,6 @@ static int ac97_soc_resume(struct snd_soc_codec *codec)
#endif
static struct snd_soc_codec_driver soc_codec_dev_ac97 = {
.write = ac97_write,
.read = ac97_read,
.probe = ac97_soc_probe,
.suspend = ac97_soc_suspend,
.resume = ac97_soc_resume,
......
......@@ -1448,29 +1448,10 @@ static int adau1373_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
static int adau1373_remove(struct snd_soc_codec *codec)
{
adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int adau1373_suspend(struct snd_soc_codec *codec)
{
struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
int ret;
ret = adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF);
regcache_cache_only(adau1373->regmap, true);
return ret;
}
static int adau1373_resume(struct snd_soc_codec *codec)
{
struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
regcache_cache_only(adau1373->regmap, false);
adau1373_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
regcache_sync(adau1373->regmap);
return 0;
......@@ -1501,8 +1482,6 @@ static const struct regmap_config adau1373_regmap_config = {
static struct snd_soc_codec_driver adau1373_codec_driver = {
.probe = adau1373_probe,
.remove = adau1373_remove,
.suspend = adau1373_suspend,
.resume = adau1373_resume,
.set_bias_level = adau1373_set_bias_level,
.idle_bias_off = true,
......
......@@ -714,9 +714,9 @@ static int adau1761_codec_probe(struct snd_soc_codec *codec)
static const struct snd_soc_codec_driver adau1761_codec_driver = {
.probe = adau1761_codec_probe,
.suspend = adau17x1_suspend,
.resume = adau17x1_resume,
.set_bias_level = adau1761_set_bias_level,
.suspend_bias_off = true,
.controls = adau1761_controls,
.num_controls = ARRAY_SIZE(adau1761_controls),
......
......@@ -446,9 +446,9 @@ static int adau1781_codec_probe(struct snd_soc_codec *codec)
static const struct snd_soc_codec_driver adau1781_codec_driver = {
.probe = adau1781_codec_probe,
.suspend = adau17x1_suspend,
.resume = adau17x1_resume,
.set_bias_level = adau1781_set_bias_level,
.suspend_bias_off = true,
.controls = adau1781_controls,
.num_controls = ARRAY_SIZE(adau1781_controls),
......
......@@ -815,13 +815,6 @@ int adau17x1_add_routes(struct snd_soc_codec *codec)
}
EXPORT_SYMBOL_GPL(adau17x1_add_routes);
int adau17x1_suspend(struct snd_soc_codec *codec)
{
codec->driver->set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
EXPORT_SYMBOL_GPL(adau17x1_suspend);
int adau17x1_resume(struct snd_soc_codec *codec)
{
struct adau *adau = snd_soc_codec_get_drvdata(codec);
......@@ -829,7 +822,6 @@ int adau17x1_resume(struct snd_soc_codec *codec)
if (adau->switch_mode)
adau->switch_mode(codec->dev);
codec->driver->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
regcache_sync(adau->regmap);
return 0;
......
......@@ -52,7 +52,6 @@ int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec,
enum adau17x1_micbias_voltage micbias);
bool adau17x1_readable_register(struct device *dev, unsigned int reg);
bool adau17x1_volatile_register(struct device *dev, unsigned int reg);
int adau17x1_suspend(struct snd_soc_codec *codec);
int adau17x1_resume(struct snd_soc_codec *codec);
extern const struct snd_soc_dai_ops adau17x1_dai_ops;
......
......@@ -812,42 +812,23 @@ static int adav80x_probe(struct snd_soc_codec *codec)
/* Disable DAC zero flag */
regmap_write(adav80x->regmap, ADAV80X_DAC_CTRL3, 0x6);
return adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
}
static int adav80x_suspend(struct snd_soc_codec *codec)
{
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
int ret;
ret = adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF);
regcache_cache_only(adav80x->regmap, true);
return ret;
return 0;
}
static int adav80x_resume(struct snd_soc_codec *codec)
{
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
regcache_cache_only(adav80x->regmap, false);
adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
regcache_sync(adav80x->regmap);
return 0;
}
static int adav80x_remove(struct snd_soc_codec *codec)
{
return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF);
}
static struct snd_soc_codec_driver adav80x_codec_driver = {
.probe = adav80x_probe,
.remove = adav80x_remove,
.suspend = adav80x_suspend,
.resume = adav80x_resume,
.set_bias_level = adav80x_set_bias_level,
.suspend_bias_off = true,
.set_pll = adav80x_set_pll,
.set_sysclk = adav80x_set_sysclk,
......
This diff is collapsed.
/*
* cs35l32.h -- CS35L32 ALSA SoC audio driver
*
* Copyright 2014 CirrusLogic, Inc.
*
* Author: Brian Austin <brian.austin@cirrus.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 __CS35L32_H__
#define __CS35L32_H__
struct cs35l32_platform_data {
/* Low Battery Threshold */
unsigned int batt_thresh;
/* Low Battery Recovery */
unsigned int batt_recov;
/* LED Current Management*/
unsigned int led_mng;
/* Audio Gain w/ LED */
unsigned int audiogain_mng;
/* Boost Management */
unsigned int boost_mng;
/* Data CFG for DUAL device */
unsigned int sdout_datacfg;
/* SDOUT Sharing */
unsigned int sdout_share;
};
#define CS35L32_CHIP_ID 0x00035A32
#define CS35L32_DEVID_AB 0x01 /* Device ID A & B [RO] */
#define CS35L32_DEVID_CD 0x02 /* Device ID C & D [RO] */
#define CS35L32_DEVID_E 0x03 /* Device ID E [RO] */
#define CS35L32_FAB_ID 0x04 /* Fab ID [RO] */
#define CS35L32_REV_ID 0x05 /* Revision ID [RO] */
#define CS35L32_PWRCTL1 0x06 /* Power Ctl 1 */
#define CS35L32_PWRCTL2 0x07 /* Power Ctl 2 */
#define CS35L32_CLK_CTL 0x08 /* Clock Ctl */
#define CS35L32_BATT_THRESHOLD 0x09 /* Low Battery Threshold */
#define CS35L32_VMON 0x0A /* Voltage Monitor [RO] */
#define CS35L32_BST_CPCP_CTL 0x0B /* Conv Peak Curr Protection CTL */
#define CS35L32_IMON_SCALING 0x0C /* IMON Scaling */
#define CS35L32_AUDIO_LED_MNGR 0x0D /* Audio/LED Pwr Manager */
#define CS35L32_ADSP_CTL 0x0F /* Serial Port Control */
#define CS35L32_CLASSD_CTL 0x10 /* Class D Amp CTL */
#define CS35L32_PROTECT_CTL 0x11 /* Protection Release CTL */
#define CS35L32_INT_MASK_1 0x12 /* Interrupt Mask 1 */
#define CS35L32_INT_MASK_2 0x13 /* Interrupt Mask 2 */
#define CS35L32_INT_MASK_3 0x14 /* Interrupt Mask 3 */
#define CS35L32_INT_STATUS_1 0x15 /* Interrupt Status 1 [RO] */
#define CS35L32_INT_STATUS_2 0x16 /* Interrupt Status 2 [RO] */
#define CS35L32_INT_STATUS_3 0x17 /* Interrupt Status 3 [RO] */
#define CS35L32_LED_STATUS 0x18 /* LED Lighting Status [RO] */
#define CS35L32_FLASH_MODE 0x19 /* LED Flash Mode Current */
#define CS35L32_MOVIE_MODE 0x1A /* LED Movie Mode Current */
#define CS35L32_FLASH_TIMER 0x1B /* LED Flash Timer */
#define CS35L32_FLASH_INHIBIT 0x1C /* LED Flash Inhibit Current */
#define CS35L32_MAX_REGISTER 0x1C
#define CS35L32_MCLK_DIV2 0x01
#define CS35L32_MCLK_RATIO 0x01
#define CS35L32_MCLKDIS 0x80
#define CS35L32_PDN_ALL 0x01
#define CS35L32_PDN_AMP 0x80
#define CS35L32_PDN_BOOST 0x04
#define CS35L32_PDN_IMON 0x40
#define CS35L32_PDN_VMON 0x80
#define CS35L32_PDN_VPMON 0x20
#define CS35L32_PDN_ADSP 0x08
#define CS35L32_MCLK_DIV2_MASK 0x40
#define CS35L32_MCLK_RATIO_MASK 0x01
#define CS35L32_MCLK_MASK 0x41
#define CS35L32_ADSP_MASTER_MASK 0x40
#define CS35L32_BOOST_MASK 0x03
#define CS35L32_GAIN_MGR_MASK 0x08
#define CS35L32_ADSP_SHARE_MASK 0x08
#define CS35L32_ADSP_DATACFG_MASK 0x30
#define CS35L32_SDOUT_3ST 0x80
#define CS35L32_BATT_REC_MASK 0x0E
#define CS35L32_BATT_THRESH_MASK 0x30
#define CS35L32_RATES (SNDRV_PCM_RATE_48000)
#define CS35L32_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE)
#endif
......@@ -77,6 +77,7 @@ static bool cs4265_readable_register(struct device *dev, unsigned int reg)
case CS4265_INT_MASK:
case CS4265_STATUS_MODE_MSB:
case CS4265_STATUS_MODE_LSB:
case CS4265_CHIP_ID:
return true;
default:
return false;
......
......@@ -176,9 +176,9 @@ static bool cs42l52_volatile_register(struct device *dev, unsigned int reg)
case CS42L52_BATT_LEVEL:
case CS42L52_SPK_STATUS:
case CS42L52_CHARGE_PUMP:
return 1;
return true;
default:
return 0;
return false;
}
}
......@@ -946,20 +946,6 @@ static struct snd_soc_dai_driver cs42l52_dai = {
.ops = &cs42l52_ops,
};
static int cs42l52_suspend(struct snd_soc_codec *codec)
{
cs42l52_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int cs42l52_resume(struct snd_soc_codec *codec)
{
cs42l52_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
static int beep_rates[] = {
261, 522, 585, 667, 706, 774, 889, 1000,
1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182
......@@ -1104,8 +1090,6 @@ static int cs42l52_probe(struct snd_soc_codec *codec)
cs42l52_init_beep(codec);
cs42l52_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
cs42l52->sysclk = CS42L52_DEFAULT_CLK;
cs42l52->config.format = CS42L52_DEFAULT_FORMAT;
......@@ -1115,7 +1099,6 @@ static int cs42l52_probe(struct snd_soc_codec *codec)
static int cs42l52_remove(struct snd_soc_codec *codec)
{
cs42l52_free_beep(codec);
cs42l52_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
......@@ -1123,9 +1106,8 @@ static int cs42l52_remove(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver soc_codec_dev_cs42l52 = {
.probe = cs42l52_probe,
.remove = cs42l52_remove,
.suspend = cs42l52_suspend,
.resume = cs42l52_resume,
.set_bias_level = cs42l52_set_bias_level,
.suspend_bias_off = true,
.dapm_widgets = cs42l52_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(cs42l52_dapm_widgets),
......
......@@ -171,9 +171,9 @@ static bool cs42l56_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case CS42L56_INT_STATUS:
return 1;
return true;
default:
return 0;
return false;
}
}
......@@ -1016,20 +1016,6 @@ static struct snd_soc_dai_driver cs42l56_dai = {
.ops = &cs42l56_ops,
};
static int cs42l56_suspend(struct snd_soc_codec *codec)
{
cs42l56_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int cs42l56_resume(struct snd_soc_codec *codec)
{
cs42l56_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
static int beep_freq[] = {
261, 522, 585, 667, 706, 774, 889, 1000,
1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182
......@@ -1168,18 +1154,12 @@ static int cs42l56_probe(struct snd_soc_codec *codec)
{
cs42l56_init_beep(codec);
cs42l56_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
static int cs42l56_remove(struct snd_soc_codec *codec)
{
struct cs42l56_private *cs42l56 = snd_soc_codec_get_drvdata(codec);
cs42l56_free_beep(codec);
cs42l56_set_bias_level(codec, SND_SOC_BIAS_OFF);
regulator_bulk_free(ARRAY_SIZE(cs42l56->supplies), cs42l56->supplies);
return 0;
}
......@@ -1187,9 +1167,8 @@ static int cs42l56_remove(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver soc_codec_dev_cs42l56 = {
.probe = cs42l56_probe,
.remove = cs42l56_remove,
.suspend = cs42l56_suspend,
.resume = cs42l56_resume,
.set_bias_level = cs42l56_set_bias_level,
.suspend_bias_off = true,
.dapm_widgets = cs42l56_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(cs42l56_dapm_widgets),
......
......@@ -1330,25 +1330,10 @@ static struct snd_soc_dai_driver cs42l73_dai[] = {
}
};
static int cs42l73_suspend(struct snd_soc_codec *codec)
{
cs42l73_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int cs42l73_resume(struct snd_soc_codec *codec)
{
cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
static int cs42l73_probe(struct snd_soc_codec *codec)
{
struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec);
cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* Set Charge Pump Frequency */
if (cs42l73->pdata.chgfreq)
snd_soc_update_bits(codec, CS42L73_CPFCHC,
......@@ -1362,18 +1347,10 @@ static int cs42l73_probe(struct snd_soc_codec *codec)
return 0;
}
static int cs42l73_remove(struct snd_soc_codec *codec)
{
cs42l73_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_cs42l73 = {
.probe = cs42l73_probe,
.remove = cs42l73_remove,
.suspend = cs42l73_suspend,
.resume = cs42l73_resume,
.set_bias_level = cs42l73_set_bias_level,
.suspend_bias_off = true,
.dapm_widgets = cs42l73_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(cs42l73_dapm_widgets),
......
......@@ -35,7 +35,6 @@
struct da732x_priv {
struct regmap *regmap;
struct snd_soc_codec *codec;
unsigned int sysclk;
bool pll_en;
......@@ -217,7 +216,7 @@ static void da732x_set_charge_pump(struct snd_soc_codec *codec, int state)
snd_soc_write(codec, DA732X_REG_CP_CTRL1, DA723X_CP_DIS);
break;
default:
pr_err(KERN_ERR "Wrong charge pump state\n");
pr_err("Wrong charge pump state\n");
break;
}
}
......@@ -1508,31 +1507,7 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
static int da732x_probe(struct snd_soc_codec *codec)
{
struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = &codec->dapm;
da732x->codec = codec;
dapm->idle_bias_off = false;
da732x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
static int da732x_remove(struct snd_soc_codec *codec)
{
da732x_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_da732x = {
.probe = da732x_probe,
.remove = da732x_remove,
.set_bias_level = da732x_set_bias_level,
.controls = da732x_snd_controls,
.num_controls = ARRAY_SIZE(da732x_snd_controls),
......
/*
* es8328-i2c.c -- ES8328 ALSA SoC I2C Audio driver
*
* Copyright 2014 Sutajio Ko-Usagi PTE LTD
*
* Author: Sean Cross <xobs@kosagi.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.
*/
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <sound/soc.h>
#include "es8328.h"
static const struct i2c_device_id es8328_id[] = {
{ "everest,es8328", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, es8328_id);
static const struct of_device_id es8328_of_match[] = {
{ .compatible = "everest,es8328", },
{ }
};
MODULE_DEVICE_TABLE(of, es8328_of_match);
static int es8328_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
return es8328_probe(&i2c->dev,
devm_regmap_init_i2c(i2c, &es8328_regmap_config));
}
static int es8328_i2c_remove(struct i2c_client *i2c)
{
snd_soc_unregister_codec(&i2c->dev);
return 0;
}
static struct i2c_driver es8328_i2c_driver = {
.driver = {
.name = "es8328",
.of_match_table = es8328_of_match,
},
.probe = es8328_i2c_probe,
.remove = es8328_i2c_remove,
.id_table = es8328_id,
};
module_i2c_driver(es8328_i2c_driver);
MODULE_DESCRIPTION("ASoC ES8328 audio CODEC I2C driver");
MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>");
MODULE_LICENSE("GPL");
/*
* es8328.c -- ES8328 ALSA SoC SPI Audio driver
*
* Copyright 2014 Sutajio Ko-Usagi PTE LTD
*
* Author: Sean Cross <xobs@kosagi.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.
*/
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <sound/soc.h>
#include "es8328.h"
static const struct of_device_id es8328_of_match[] = {
{ .compatible = "everest,es8328", },
{ }
};
MODULE_DEVICE_TABLE(of, es8328_of_match);
static int es8328_spi_probe(struct spi_device *spi)
{
return es8328_probe(&spi->dev,
devm_regmap_init_spi(spi, &es8328_regmap_config));
}
static int es8328_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
}
static struct spi_driver es8328_spi_driver = {
.driver = {
.name = "es8328",
.of_match_table = es8328_of_match,
},
.probe = es8328_spi_probe,
.remove = es8328_spi_remove,
};
module_spi_driver(es8328_spi_driver);
MODULE_DESCRIPTION("ASoC ES8328 audio CODEC SPI driver");
MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>");
MODULE_LICENSE("GPL");
This diff is collapsed.
This diff is collapsed.
......@@ -293,41 +293,13 @@ static int jz4740_codec_dev_probe(struct snd_soc_codec *codec)
regmap_update_bits(jz4740_codec->regmap, JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
static int jz4740_codec_dev_remove(struct snd_soc_codec *codec)
{
jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int jz4740_codec_suspend(struct snd_soc_codec *codec)
{
return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
}
static int jz4740_codec_resume(struct snd_soc_codec *codec)
{
return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
}
#else
#define jz4740_codec_suspend NULL
#define jz4740_codec_resume NULL
#endif
static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = {
.probe = jz4740_codec_dev_probe,
.remove = jz4740_codec_dev_remove,
.suspend = jz4740_codec_suspend,
.resume = jz4740_codec_resume,
.set_bias_level = jz4740_codec_set_bias_level,
.suspend_bias_off = true,
.controls = jz4740_codec_controls,
.num_controls = ARRAY_SIZE(jz4740_codec_controls),
......
......@@ -1395,18 +1395,6 @@ static struct snd_soc_dai_driver lm49453_dai[] = {
},
};
static int lm49453_suspend(struct snd_soc_codec *codec)
{
lm49453_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int lm49453_resume(struct snd_soc_codec *codec)
{
lm49453_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
/* power down chip */
static int lm49453_remove(struct snd_soc_codec *codec)
{
......@@ -1416,8 +1404,6 @@ static int lm49453_remove(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver soc_codec_dev_lm49453 = {
.remove = lm49453_remove,
.suspend = lm49453_suspend,
.resume = lm49453_resume,
.set_bias_level = lm49453_set_bias_level,
.controls = lm49453_snd_controls,
.num_controls = ARRAY_SIZE(lm49453_snd_controls),
......
......@@ -1311,8 +1311,6 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = {
{"MIC1 Input", NULL, "MIC1"},
{"MIC2 Input", NULL, "MIC2"},
{"DMICL", NULL, "DMICL_ENA"},
{"DMICR", NULL, "DMICR_ENA"},
{"DMICL", NULL, "AHPF"},
{"DMICR", NULL, "AHPF"},
......@@ -1370,6 +1368,8 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = {
{"DMIC Mux", "ADC", "ADCR"},
{"DMIC Mux", "DMIC", "DMICL"},
{"DMIC Mux", "DMIC", "DMICR"},
{"DMIC Mux", "DMIC", "DMICL_ENA"},
{"DMIC Mux", "DMIC", "DMICR_ENA"},
{"LBENL Mux", "Normal", "DMIC Mux"},
{"LBENL Mux", "Loopback", "LTENL Mux"},
......@@ -2159,12 +2159,16 @@ static void max98090_jack_work(struct work_struct *work)
static irqreturn_t max98090_interrupt(int irq, void *data)
{
struct snd_soc_codec *codec = data;
struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
struct max98090_priv *max98090 = data;
struct snd_soc_codec *codec = max98090->codec;
int ret;
unsigned int mask;
unsigned int active;
/* Treat interrupt before codec is initialized as spurious */
if (codec == NULL)
return IRQ_NONE;
dev_dbg(codec->dev, "***** max98090_interrupt *****\n");
ret = regmap_read(max98090->regmap, M98090_REG_INTERRUPT_S, &mask);
......@@ -2329,7 +2333,6 @@ static int max98090_probe(struct snd_soc_codec *codec)
max98090->lin_state = 0;
max98090->pa1en = 0;
max98090->pa2en = 0;
max98090->extmic_mux = 0;
ret = snd_soc_read(codec, M98090_REG_REVISION_ID);
if (ret < 0) {
......@@ -2367,17 +2370,6 @@ static int max98090_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, M98090_REG_JACK_DETECT,
M98090_JDETEN_MASK | M98090_JDEB_25MS);
/* Register for interrupts */
dev_dbg(codec->dev, "irq = %d\n", max98090->irq);
ret = devm_request_threaded_irq(codec->dev, max98090->irq, NULL,
max98090_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"max98090_interrupt", codec);
if (ret < 0) {
dev_err(codec->dev, "request_irq failed: %d\n",
ret);
}
/*
* Clear any old interrupts.
* An old interrupt ocurring prior to installing the ISR
......@@ -2417,6 +2409,7 @@ static int max98090_remove(struct snd_soc_codec *codec)
cancel_delayed_work_sync(&max98090->pll_det_enable_work);
cancel_work_sync(&max98090->pll_det_disable_work);
cancel_work_sync(&max98090->pll_work);
max98090->codec = NULL;
return 0;
}
......@@ -2469,7 +2462,6 @@ static int max98090_i2c_probe(struct i2c_client *i2c,
max98090->devtype = driver_data;
i2c_set_clientdata(i2c, max98090);
max98090->pdata = i2c->dev.platform_data;
max98090->irq = i2c->irq;
max98090->regmap = devm_regmap_init_i2c(i2c, &max98090_regmap);
if (IS_ERR(max98090->regmap)) {
......@@ -2478,6 +2470,15 @@ static int max98090_i2c_probe(struct i2c_client *i2c,
goto err_enable;
}
ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
max98090_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"max98090_interrupt", max98090);
if (ret < 0) {
dev_err(&i2c->dev, "request_irq failed: %d\n",
ret);
return ret;
}
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_max98090, max98090_dai,
ARRAY_SIZE(max98090_dai));
......
......@@ -11,11 +11,6 @@
#ifndef _MAX98090_H
#define _MAX98090_H
#include <linux/version.h>
/* One can override the Linux version here with an explicit version number */
#define M98090_LINUX_VERSION LINUX_VERSION_CODE
/*
* MAX98090 Register Definitions
*/
......@@ -1502,9 +1497,6 @@
#define M98090_REVID_WIDTH 8
#define M98090_REVID_NUM (1<<M98090_REVID_WIDTH)
#define M98090_BYTE1(w) ((w >> 8) & 0xff)
#define M98090_BYTE0(w) (w & 0xff)
/* Silicon revision number */
#define M98090_REVA 0x40
#define M98091_REVA 0x50
......@@ -1529,7 +1521,6 @@ struct max98090_priv {
unsigned int bclk;
unsigned int lrclk;
struct max98090_cdata dai[1];
int irq;
int jack_state;
struct delayed_work jack_work;
struct delayed_work pll_det_enable_work;
......@@ -1542,7 +1533,6 @@ struct max98090_priv {
u8 lin_state;
unsigned int pa1en;
unsigned int pa2en;
unsigned int extmic_mux;
unsigned int sidetone;
bool master;
};
......
......@@ -565,41 +565,19 @@ static struct snd_soc_dai_driver ml26124_dai = {
.symmetric_rates = 1,
};
#ifdef CONFIG_PM
static int ml26124_suspend(struct snd_soc_codec *codec)
{
ml26124_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int ml26124_resume(struct snd_soc_codec *codec)
{
ml26124_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
#else
#define ml26124_suspend NULL
#define ml26124_resume NULL
#endif
static int ml26124_probe(struct snd_soc_codec *codec)
{
/* Software Reset */
snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 1);
snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 0);
ml26124_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_ml26124 = {
.probe = ml26124_probe,
.suspend = ml26124_suspend,
.resume = ml26124_resume,
.set_bias_level = ml26124_set_bias_level,
.suspend_bias_off = true,
.dapm_widgets = ml26124_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(ml26124_dapm_widgets),
.dapm_routes = ml26124_intercon,
......
......@@ -269,6 +269,7 @@ static int rt286_hw_read(void *context, unsigned int reg, unsigned int *value)
return 0;
}
#ifdef CONFIG_PM
static void rt286_index_sync(struct snd_soc_codec *codec)
{
struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
......@@ -279,6 +280,7 @@ static void rt286_index_sync(struct snd_soc_codec *codec)
rt286->index_cache[i].def);
}
}
#endif
static int rt286_support_power_controls[] = {
RT286_DAC_OUT1,
......
......@@ -1906,6 +1906,32 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
int rt5640_dmic_enable(struct snd_soc_codec *codec,
bool dmic1_data_pin, bool dmic2_data_pin)
{
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1,
RT5640_GP2_PIN_MASK, RT5640_GP2_PIN_DMIC1_SCL);
if (dmic1_data_pin) {
regmap_update_bits(rt5640->regmap, RT5640_DMIC,
RT5640_DMIC_1_DP_MASK, RT5640_DMIC_1_DP_GPIO3);
regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1,
RT5640_GP3_PIN_MASK, RT5640_GP3_PIN_DMIC1_SDA);
}
if (dmic2_data_pin) {
regmap_update_bits(rt5640->regmap, RT5640_DMIC,
RT5640_DMIC_2_DP_MASK, RT5640_DMIC_2_DP_GPIO4);
regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1,
RT5640_GP4_PIN_MASK, RT5640_GP4_PIN_DMIC2_SDA);
}
return 0;
}
EXPORT_SYMBOL_GPL(rt5640_dmic_enable);
static int rt5640_probe(struct snd_soc_codec *codec)
{
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
......@@ -1945,6 +1971,10 @@ static int rt5640_probe(struct snd_soc_codec *codec)
return -ENODEV;
}
if (rt5640->pdata.dmic_en)
rt5640_dmic_enable(codec, rt5640->pdata.dmic1_data_pin,
rt5640->pdata.dmic2_data_pin);
return 0;
}
......@@ -2195,25 +2225,6 @@ static int rt5640_i2c_probe(struct i2c_client *i2c,
regmap_update_bits(rt5640->regmap, RT5640_IN3_IN4,
RT5640_IN_DF2, RT5640_IN_DF2);
if (rt5640->pdata.dmic_en) {
regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1,
RT5640_GP2_PIN_MASK, RT5640_GP2_PIN_DMIC1_SCL);
if (rt5640->pdata.dmic1_data_pin) {
regmap_update_bits(rt5640->regmap, RT5640_DMIC,
RT5640_DMIC_1_DP_MASK, RT5640_DMIC_1_DP_GPIO3);
regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1,
RT5640_GP3_PIN_MASK, RT5640_GP3_PIN_DMIC1_SDA);
}
if (rt5640->pdata.dmic2_data_pin) {
regmap_update_bits(rt5640->regmap, RT5640_DMIC,
RT5640_DMIC_2_DP_MASK, RT5640_DMIC_2_DP_GPIO4);
regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1,
RT5640_GP4_PIN_MASK, RT5640_GP4_PIN_DMIC2_SDA);
}
}
rt5640->hp_mute = 1;
return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5640,
......
......@@ -2097,4 +2097,7 @@ struct rt5640_priv {
bool hp_mute;
};
int rt5640_dmic_enable(struct snd_soc_codec *codec,
bool dmic1_data_pin, bool dmic2_data_pin);
#endif
......@@ -17,6 +17,7 @@
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/gpio.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
......@@ -2103,6 +2104,77 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
static int rt5645_jack_detect(struct snd_soc_codec *codec,
struct snd_soc_jack *jack)
{
struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
int gpio_state, jack_type = 0;
unsigned int val;
gpio_state = gpio_get_value(rt5645->pdata.hp_det_gpio);
dev_dbg(codec->dev, "gpio = %d(%d)\n", rt5645->pdata.hp_det_gpio,
gpio_state);
if ((rt5645->pdata.gpio_hp_det_active_high && gpio_state) ||
(!rt5645->pdata.gpio_hp_det_active_high && !gpio_state)) {
snd_soc_dapm_force_enable_pin(&codec->dapm, "micbias1");
snd_soc_dapm_force_enable_pin(&codec->dapm, "micbias2");
snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2");
snd_soc_dapm_force_enable_pin(&codec->dapm, "Mic Det Power");
snd_soc_dapm_sync(&codec->dapm);
snd_soc_write(codec, RT5645_IN1_CTRL1, 0x0006);
snd_soc_write(codec, RT5645_JD_CTRL3, 0x00b0);
snd_soc_update_bits(codec, RT5645_IN1_CTRL2,
RT5645_CBJ_MN_JD, 0);
snd_soc_update_bits(codec, RT5645_IN1_CTRL2,
RT5645_CBJ_MN_JD, RT5645_CBJ_MN_JD);
msleep(400);
val = snd_soc_read(codec, RT5645_IN1_CTRL3) & 0x7;
dev_dbg(codec->dev, "val = %d\n", val);
if (val == 1 || val == 2)
jack_type = SND_JACK_HEADSET;
else
jack_type = SND_JACK_HEADPHONE;
snd_soc_dapm_disable_pin(&codec->dapm, "micbias1");
snd_soc_dapm_disable_pin(&codec->dapm, "micbias2");
snd_soc_dapm_disable_pin(&codec->dapm, "LDO2");
snd_soc_dapm_disable_pin(&codec->dapm, "Mic Det Power");
snd_soc_dapm_sync(&codec->dapm);
}
snd_soc_jack_report(rt5645->jack, jack_type, SND_JACK_HEADSET);
return 0;
}
int rt5645_set_jack_detect(struct snd_soc_codec *codec,
struct snd_soc_jack *jack)
{
struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
rt5645->jack = jack;
rt5645_jack_detect(codec, rt5645->jack);
return 0;
}
EXPORT_SYMBOL_GPL(rt5645_set_jack_detect);
static irqreturn_t rt5645_irq(int irq, void *data)
{
struct rt5645_priv *rt5645 = data;
rt5645_jack_detect(rt5645->codec, rt5645->jack);
return IRQ_HANDLED;
}
static int rt5645_probe(struct snd_soc_codec *codec)
{
struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
......@@ -2250,6 +2322,7 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
if (rt5645 == NULL)
return -ENOMEM;
rt5645->i2c = i2c;
i2c_set_clientdata(i2c, rt5645);
if (pdata)
......@@ -2345,12 +2418,38 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
}
if (rt5645->i2c->irq) {
ret = request_threaded_irq(rt5645->i2c->irq, NULL, rt5645_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
| IRQF_ONESHOT, "rt5645", rt5645);
if (ret)
dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
}
if (gpio_is_valid(rt5645->pdata.hp_det_gpio)) {
ret = gpio_request(rt5645->pdata.hp_det_gpio, "rt5645");
if (ret)
dev_err(&i2c->dev, "Fail gpio_request hp_det_gpio\n");
ret = gpio_direction_input(rt5645->pdata.hp_det_gpio);
if (ret)
dev_err(&i2c->dev, "Fail gpio_direction hp_det_gpio\n");
}
return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645,
rt5645_dai, ARRAY_SIZE(rt5645_dai));
}
static int rt5645_i2c_remove(struct i2c_client *i2c)
{
struct rt5645_priv *rt5645 = i2c_get_clientdata(i2c);
if (i2c->irq)
free_irq(i2c->irq, rt5645);
if (gpio_is_valid(rt5645->pdata.hp_det_gpio))
gpio_free(rt5645->pdata.hp_det_gpio);
snd_soc_unregister_codec(&i2c->dev);
return 0;
......
......@@ -2166,6 +2166,8 @@ struct rt5645_priv {
struct snd_soc_codec *codec;
struct rt5645_platform_data pdata;
struct regmap *regmap;
struct i2c_client *i2c;
struct snd_soc_jack *jack;
int sysclk;
int sysclk_src;
......@@ -2178,4 +2180,7 @@ struct rt5645_priv {
int pll_out;
};
int rt5645_set_jack_detect(struct snd_soc_codec *codec,
struct snd_soc_jack *jack);
#endif /* __RT5645_H__ */
This diff is collapsed.
......@@ -382,6 +382,10 @@
#define RT5677_ST_SEL_SFT 9
#define RT5677_ST_EN (0x1 << 6)
#define RT5677_ST_EN_SFT 6
#define RT5677_ST_GAIN (0x1 << 5)
#define RT5677_ST_GAIN_SFT 5
#define RT5677_ST_VOL_MASK (0x1f << 0)
#define RT5677_ST_VOL_SFT 0
/* Analog DAC1/2/3 Source Control (0x15) */
#define RT5677_ANA_DAC3_SRC_SEL_MASK (0x3 << 4)
......@@ -1287,16 +1291,16 @@
#define RT5677_PLL1_PD_SFT 8
#define RT5677_PLL1_PD_1 (0x0 << 8)
#define RT5677_PLL1_PD_2 (0x1 << 8)
#define RT5671_DAC_OSR_MASK (0x3 << 6)
#define RT5671_DAC_OSR_SFT 6
#define RT5671_DAC_OSR_128 (0x0 << 6)
#define RT5671_DAC_OSR_64 (0x1 << 6)
#define RT5671_DAC_OSR_32 (0x2 << 6)
#define RT5671_ADC_OSR_MASK (0x3 << 4)
#define RT5671_ADC_OSR_SFT 4
#define RT5671_ADC_OSR_128 (0x0 << 4)
#define RT5671_ADC_OSR_64 (0x1 << 4)
#define RT5671_ADC_OSR_32 (0x2 << 4)
#define RT5677_DAC_OSR_MASK (0x3 << 6)
#define RT5677_DAC_OSR_SFT 6
#define RT5677_DAC_OSR_128 (0x0 << 6)
#define RT5677_DAC_OSR_64 (0x1 << 6)
#define RT5677_DAC_OSR_32 (0x2 << 6)
#define RT5677_ADC_OSR_MASK (0x3 << 4)
#define RT5677_ADC_OSR_SFT 4
#define RT5677_ADC_OSR_128 (0x0 << 4)
#define RT5677_ADC_OSR_64 (0x1 << 4)
#define RT5677_ADC_OSR_32 (0x2 << 4)
/* Global Clock Control 2 (0x81) */
#define RT5677_PLL2_PR_SRC_MASK (0x1 << 15)
......@@ -1312,18 +1316,18 @@
#define RT5677_PLL2_SRC_BCLK4 (0x4 << 12)
#define RT5677_PLL2_SRC_RCCLK (0x5 << 12)
#define RT5677_PLL2_SRC_SLIM (0x6 << 12)
#define RT5671_DSP_ASRC_O_SRC (0x3 << 10)
#define RT5671_DSP_ASRC_O_SRC_SFT 10
#define RT5671_DSP_ASRC_O_MCLK (0x0 << 10)
#define RT5671_DSP_ASRC_O_PLL1 (0x1 << 10)
#define RT5671_DSP_ASRC_O_SLIM (0x2 << 10)
#define RT5671_DSP_ASRC_O_RCCLK (0x3 << 10)
#define RT5671_DSP_ASRC_I_SRC (0x3 << 8)
#define RT5671_DSP_ASRC_I_SRC_SFT 8
#define RT5671_DSP_ASRC_I_MCLK (0x0 << 8)
#define RT5671_DSP_ASRC_I_PLL1 (0x1 << 8)
#define RT5671_DSP_ASRC_I_SLIM (0x2 << 8)
#define RT5671_DSP_ASRC_I_RCCLK (0x3 << 8)
#define RT5677_DSP_ASRC_O_SRC (0x3 << 10)
#define RT5677_DSP_ASRC_O_SRC_SFT 10
#define RT5677_DSP_ASRC_O_MCLK (0x0 << 10)
#define RT5677_DSP_ASRC_O_PLL1 (0x1 << 10)
#define RT5677_DSP_ASRC_O_SLIM (0x2 << 10)
#define RT5677_DSP_ASRC_O_RCCLK (0x3 << 10)
#define RT5677_DSP_ASRC_I_SRC (0x3 << 8)
#define RT5677_DSP_ASRC_I_SRC_SFT 8
#define RT5677_DSP_ASRC_I_MCLK (0x0 << 8)
#define RT5677_DSP_ASRC_I_PLL1 (0x1 << 8)
#define RT5677_DSP_ASRC_I_SLIM (0x2 << 8)
#define RT5677_DSP_ASRC_I_RCCLK (0x3 << 8)
#define RT5677_DSP_CLK_SRC_MASK (0x1 << 7)
#define RT5677_DSP_CLK_SRC_SFT 7
#define RT5677_DSP_CLK_SRC_PLL2 (0x0 << 7)
......@@ -1363,6 +1367,110 @@
#define RT5677_SEL_SRC_IB01 (0x1 << 0)
#define RT5677_SEL_SRC_IB01_SFT 0
/* GPIO status (0xbf) */
#define RT5677_GPIO6_STATUS_MASK (0x1 << 5)
#define RT5677_GPIO6_STATUS_SFT 5
#define RT5677_GPIO5_STATUS_MASK (0x1 << 4)
#define RT5677_GPIO5_STATUS_SFT 4
#define RT5677_GPIO4_STATUS_MASK (0x1 << 3)
#define RT5677_GPIO4_STATUS_SFT 3
#define RT5677_GPIO3_STATUS_MASK (0x1 << 2)
#define RT5677_GPIO3_STATUS_SFT 2
#define RT5677_GPIO2_STATUS_MASK (0x1 << 1)
#define RT5677_GPIO2_STATUS_SFT 1
#define RT5677_GPIO1_STATUS_MASK (0x1 << 0)
#define RT5677_GPIO1_STATUS_SFT 0
/* GPIO Control 1 (0xc0) */
#define RT5677_GPIO1_PIN_MASK (0x1 << 15)
#define RT5677_GPIO1_PIN_SFT 15
#define RT5677_GPIO1_PIN_GPIO1 (0x0 << 15)
#define RT5677_GPIO1_PIN_IRQ (0x1 << 15)
#define RT5677_IPTV_MODE_MASK (0x1 << 14)
#define RT5677_IPTV_MODE_SFT 14
#define RT5677_IPTV_MODE_GPIO (0x0 << 14)
#define RT5677_IPTV_MODE_IPTV (0x1 << 14)
#define RT5677_FUNC_MODE_MASK (0x1 << 13)
#define RT5677_FUNC_MODE_SFT 13
#define RT5677_FUNC_MODE_DMIC_GPIO (0x0 << 13)
#define RT5677_FUNC_MODE_JTAG (0x1 << 13)
/* GPIO Control 2 (0xc1) */
#define RT5677_GPIO5_DIR_MASK (0x1 << 14)
#define RT5677_GPIO5_DIR_SFT 14
#define RT5677_GPIO5_DIR_IN (0x0 << 14)
#define RT5677_GPIO5_DIR_OUT (0x1 << 14)
#define RT5677_GPIO5_OUT_MASK (0x1 << 13)
#define RT5677_GPIO5_OUT_SFT 13
#define RT5677_GPIO5_OUT_LO (0x0 << 13)
#define RT5677_GPIO5_OUT_HI (0x1 << 13)
#define RT5677_GPIO5_P_MASK (0x1 << 12)
#define RT5677_GPIO5_P_SFT 12
#define RT5677_GPIO5_P_NOR (0x0 << 12)
#define RT5677_GPIO5_P_INV (0x1 << 12)
#define RT5677_GPIO4_DIR_MASK (0x1 << 11)
#define RT5677_GPIO4_DIR_SFT 11
#define RT5677_GPIO4_DIR_IN (0x0 << 11)
#define RT5677_GPIO4_DIR_OUT (0x1 << 11)
#define RT5677_GPIO4_OUT_MASK (0x1 << 10)
#define RT5677_GPIO4_OUT_SFT 10
#define RT5677_GPIO4_OUT_LO (0x0 << 10)
#define RT5677_GPIO4_OUT_HI (0x1 << 10)
#define RT5677_GPIO4_P_MASK (0x1 << 9)
#define RT5677_GPIO4_P_SFT 9
#define RT5677_GPIO4_P_NOR (0x0 << 9)
#define RT5677_GPIO4_P_INV (0x1 << 9)
#define RT5677_GPIO3_DIR_MASK (0x1 << 8)
#define RT5677_GPIO3_DIR_SFT 8
#define RT5677_GPIO3_DIR_IN (0x0 << 8)
#define RT5677_GPIO3_DIR_OUT (0x1 << 8)
#define RT5677_GPIO3_OUT_MASK (0x1 << 7)
#define RT5677_GPIO3_OUT_SFT 7
#define RT5677_GPIO3_OUT_LO (0x0 << 7)
#define RT5677_GPIO3_OUT_HI (0x1 << 7)
#define RT5677_GPIO3_P_MASK (0x1 << 6)
#define RT5677_GPIO3_P_SFT 6
#define RT5677_GPIO3_P_NOR (0x0 << 6)
#define RT5677_GPIO3_P_INV (0x1 << 6)
#define RT5677_GPIO2_DIR_MASK (0x1 << 5)
#define RT5677_GPIO2_DIR_SFT 5
#define RT5677_GPIO2_DIR_IN (0x0 << 5)
#define RT5677_GPIO2_DIR_OUT (0x1 << 5)
#define RT5677_GPIO2_OUT_MASK (0x1 << 4)
#define RT5677_GPIO2_OUT_SFT 4
#define RT5677_GPIO2_OUT_LO (0x0 << 4)
#define RT5677_GPIO2_OUT_HI (0x1 << 4)
#define RT5677_GPIO2_P_MASK (0x1 << 3)
#define RT5677_GPIO2_P_SFT 3
#define RT5677_GPIO2_P_NOR (0x0 << 3)
#define RT5677_GPIO2_P_INV (0x1 << 3)
#define RT5677_GPIO1_DIR_MASK (0x1 << 2)
#define RT5677_GPIO1_DIR_SFT 2
#define RT5677_GPIO1_DIR_IN (0x0 << 2)
#define RT5677_GPIO1_DIR_OUT (0x1 << 2)
#define RT5677_GPIO1_OUT_MASK (0x1 << 1)
#define RT5677_GPIO1_OUT_SFT 1
#define RT5677_GPIO1_OUT_LO (0x0 << 1)
#define RT5677_GPIO1_OUT_HI (0x1 << 1)
#define RT5677_GPIO1_P_MASK (0x1 << 0)
#define RT5677_GPIO1_P_SFT 0
#define RT5677_GPIO1_P_NOR (0x0 << 0)
#define RT5677_GPIO1_P_INV (0x1 << 0)
/* GPIO Control 3 (0xc2) */
#define RT5677_GPIO6_DIR_MASK (0x1 << 2)
#define RT5677_GPIO6_DIR_SFT 2
#define RT5677_GPIO6_DIR_IN (0x0 << 2)
#define RT5677_GPIO6_DIR_OUT (0x1 << 2)
#define RT5677_GPIO6_OUT_MASK (0x1 << 1)
#define RT5677_GPIO6_OUT_SFT 1
#define RT5677_GPIO6_OUT_LO (0x0 << 1)
#define RT5677_GPIO6_OUT_HI (0x1 << 1)
#define RT5677_GPIO6_P_MASK (0x1 << 0)
#define RT5677_GPIO6_P_SFT 0
#define RT5677_GPIO6_P_NOR (0x0 << 0)
#define RT5677_GPIO6_P_INV (0x1 << 0)
/* Virtual DSP Mixer Control (0xf7 0xf8 0xf9) */
#define RT5677_DSP_IB_01_H (0x1 << 15)
#define RT5677_DSP_IB_01_H_SFT 15
......@@ -1393,6 +1501,11 @@
#define RT5677_DSP_IB_9_L (0x1 << 1)
#define RT5677_DSP_IB_9_L_SFT 1
/* General Control2 (0xfc)*/
#define RT5677_GPIO5_FUNC_MASK (0x1 << 9)
#define RT5677_GPIO5_FUNC_GPIO (0x0 << 9)
#define RT5677_GPIO5_FUNC_DMIC (0x1 << 9)
/* System Clock Source */
enum {
RT5677_SCLK_S_MCLK,
......@@ -1418,6 +1531,16 @@ enum {
RT5677_AIFS,
};
enum {
RT5677_GPIO1,
RT5677_GPIO2,
RT5677_GPIO3,
RT5677_GPIO4,
RT5677_GPIO5,
RT5677_GPIO6,
RT5677_GPIO_NUM,
};
struct rt5677_priv {
struct snd_soc_codec *codec;
struct rt5677_platform_data pdata;
......@@ -1431,6 +1554,10 @@ struct rt5677_priv {
int pll_src;
int pll_in;
int pll_out;
int pow_ldo2; /* POW_LDO2 pin */
#ifdef CONFIG_GPIOLIB
struct gpio_chip gpio_chip;
#endif
};
#endif /* __RT5677_H__ */
......@@ -626,6 +626,9 @@ static int sgtl5000_set_clock(struct snd_soc_codec *codec, int frame_rate)
} else {
dev_err(codec->dev,
"PLL not supported in slave mode\n");
dev_err(codec->dev, "%d ratio is not supported. "
"SYS_MCLK needs to be 256, 384 or 512 * fs\n",
sgtl5000->sysclk / sys_fs);
return -EINVAL;
}
}
......@@ -1073,26 +1076,6 @@ static bool sgtl5000_readable(struct device *dev, unsigned int reg)
}
}
#ifdef CONFIG_SUSPEND
static int sgtl5000_suspend(struct snd_soc_codec *codec)
{
sgtl5000_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int sgtl5000_resume(struct snd_soc_codec *codec)
{
/* Bring the codec back up to standby to enable regulators */
sgtl5000_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
#else
#define sgtl5000_suspend NULL
#define sgtl5000_resume NULL
#endif /* CONFIG_SUSPEND */
/*
* sgtl5000 has 3 internal power supplies:
* 1. VAG, normally set to vdda/2
......@@ -1352,11 +1335,6 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
*/
snd_soc_write(codec, SGTL5000_DAP_CTRL, 0);
/* leading to standby state */
ret = sgtl5000_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
if (ret)
goto err;
return 0;
err:
......@@ -1373,8 +1351,6 @@ static int sgtl5000_remove(struct snd_soc_codec *codec)
{
struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
sgtl5000_set_bias_level(codec, SND_SOC_BIAS_OFF);
regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
sgtl5000->supplies);
regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
......@@ -1387,9 +1363,8 @@ static int sgtl5000_remove(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver sgtl5000_driver = {
.probe = sgtl5000_probe,
.remove = sgtl5000_remove,
.suspend = sgtl5000_suspend,
.resume = sgtl5000_resume,
.set_bias_level = sgtl5000_set_bias_level,
.suspend_bias_off = true,
.controls = sgtl5000_snd_controls,
.num_controls = ARRAY_SIZE(sgtl5000_snd_controls),
.dapm_widgets = sgtl5000_dapm_widgets,
......@@ -1442,6 +1417,7 @@ static int sgtl5000_i2c_probe(struct i2c_client *client,
{
struct sgtl5000_priv *sgtl5000;
int ret, reg, rev;
unsigned int mclk;
sgtl5000 = devm_kzalloc(&client->dev, sizeof(struct sgtl5000_priv),
GFP_KERNEL);
......@@ -1465,6 +1441,14 @@ static int sgtl5000_i2c_probe(struct i2c_client *client,
return ret;
}
/* SGTL5000 SYS_MCLK should be between 8 and 27 MHz */
mclk = clk_get_rate(sgtl5000->mclk);
if (mclk < 8000000 || mclk > 27000000) {
dev_err(&client->dev, "Invalid SYS_CLK frequency: %u.%03uMHz\n",
mclk / 1000000, mclk / 1000 % 1000);
return -EINVAL;
}
ret = clk_prepare_enable(sgtl5000->mclk);
if (ret)
return ret;
......
......@@ -646,17 +646,6 @@ static struct snd_soc_dai_driver ssm2518_dai = {
.ops = &ssm2518_dai_ops,
};
static int ssm2518_probe(struct snd_soc_codec *codec)
{
return ssm2518_set_bias_level(codec, SND_SOC_BIAS_OFF);
}
static int ssm2518_remove(struct snd_soc_codec *codec)
{
ssm2518_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int ssm2518_set_sysclk(struct snd_soc_codec *codec, int clk_id,
int source, unsigned int freq, int dir)
{
......@@ -727,8 +716,6 @@ static int ssm2518_set_sysclk(struct snd_soc_codec *codec, int clk_id,
}
static struct snd_soc_codec_driver ssm2518_codec_driver = {
.probe = ssm2518_probe,
.remove = ssm2518_remove,
.set_bias_level = ssm2518_set_bias_level,
.set_sysclk = ssm2518_set_sysclk,
.idle_bias_off = true,
......
......@@ -41,10 +41,19 @@ static const struct i2c_device_id ssm2602_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id);
static const struct of_device_id ssm2602_of_match[] = {
{ .compatible = "adi,ssm2602", },
{ .compatible = "adi,ssm2603", },
{ .compatible = "adi,ssm2604", },
{ }
};
MODULE_DEVICE_TABLE(of, ssm2602_of_match);
static struct i2c_driver ssm2602_i2c_driver = {
.driver = {
.name = "ssm2602",
.owner = THIS_MODULE,
.of_match_table = ssm2602_of_match,
},
.probe = ssm2602_i2c_probe,
.remove = ssm2602_i2c_remove,
......
......@@ -26,10 +26,17 @@ static int ssm2602_spi_remove(struct spi_device *spi)
return 0;
}
static const struct of_device_id ssm2602_of_match[] = {
{ .compatible = "adi,ssm2602", },
{ }
};
MODULE_DEVICE_TABLE(of, ssm2602_of_match);
static struct spi_driver ssm2602_spi_driver = {
.driver = {
.name = "ssm2602",
.owner = THIS_MODULE,
.of_match_table = ssm2602_of_match,
},
.probe = ssm2602_spi_probe,
.remove = ssm2602_spi_remove,
......
......@@ -192,7 +192,7 @@ static const struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = {
};
static const unsigned int ssm2602_rates_11289600[] = {
8000, 44100, 88200,
8000, 11025, 22050, 44100, 88200,
};
static const struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = {
......@@ -237,6 +237,16 @@ static const struct ssm2602_coeff ssm2602_coeff_table[] = {
{18432000, 96000, SSM2602_COEFF_SRATE(0x7, 0x1, 0x0)},
{12000000, 96000, SSM2602_COEFF_SRATE(0x7, 0x0, 0x1)},
/* 11.025k */
{11289600, 11025, SSM2602_COEFF_SRATE(0xc, 0x0, 0x0)},
{16934400, 11025, SSM2602_COEFF_SRATE(0xc, 0x1, 0x0)},
{12000000, 11025, SSM2602_COEFF_SRATE(0xc, 0x1, 0x1)},
/* 22.05k */
{11289600, 22050, SSM2602_COEFF_SRATE(0xd, 0x0, 0x0)},
{16934400, 22050, SSM2602_COEFF_SRATE(0xd, 0x1, 0x0)},
{12000000, 22050, SSM2602_COEFF_SRATE(0xd, 0x1, 0x1)},
/* 44.1k */
{11289600, 44100, SSM2602_COEFF_SRATE(0x8, 0x0, 0x0)},
{16934400, 44100, SSM2602_COEFF_SRATE(0x8, 0x1, 0x0)},
......@@ -467,7 +477,8 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
#define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
#define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
SNDRV_PCM_RATE_96000)
......@@ -502,18 +513,11 @@ static struct snd_soc_dai_driver ssm2602_dai = {
.symmetric_samplebits = 1,
};
static int ssm2602_suspend(struct snd_soc_codec *codec)
{
ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int ssm2602_resume(struct snd_soc_codec *codec)
{
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
regcache_sync(ssm2602->regmap);
ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
......@@ -586,27 +590,14 @@ static int ssm260x_codec_probe(struct snd_soc_codec *codec)
break;
}
if (ret)
return ret;
ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
/* remove everything here */
static int ssm2602_remove(struct snd_soc_codec *codec)
{
ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
return ret;
}
static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = {
.probe = ssm260x_codec_probe,
.remove = ssm2602_remove,
.suspend = ssm2602_suspend,
.resume = ssm2602_resume,
.set_bias_level = ssm2602_set_bias_level,
.suspend_bias_off = true,
.controls = ssm260x_snd_controls,
.num_controls = ARRAY_SIZE(ssm260x_snd_controls),
......
This diff is collapsed.
......@@ -78,6 +78,44 @@ struct tas2552_data {
unsigned int mclk;
};
/* Input mux controls */
static const char *tas2552_input_texts[] = {
"Digital", "Analog"
};
static SOC_ENUM_SINGLE_DECL(tas2552_input_mux_enum, TAS2552_CFG_3, 7,
tas2552_input_texts);
static const struct snd_kcontrol_new tas2552_input_mux_control[] = {
SOC_DAPM_ENUM("Input selection", tas2552_input_mux_enum)
};
static const struct snd_soc_dapm_widget tas2552_dapm_widgets[] =
{
SND_SOC_DAPM_INPUT("IN"),
/* MUX Controls */
SND_SOC_DAPM_MUX("Input selection", SND_SOC_NOPM, 0, 0,
tas2552_input_mux_control),
SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_OUT_DRV("ClassD", TAS2552_CFG_2, 7, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("PLL", TAS2552_CFG_2, 3, 0, NULL, 0),
SND_SOC_DAPM_OUTPUT("OUT")
};
static const struct snd_soc_dapm_route tas2552_audio_map[] = {
{"DAC", NULL, "DAC IN"},
{"Input selection", "Digital", "DAC"},
{"Input selection", "Analog", "IN"},
{"ClassD", NULL, "Input selection"},
{"OUT", NULL, "ClassD"},
{"ClassD", NULL, "PLL"},
};
#ifdef CONFIG_PM_RUNTIME
static void tas2552_sw_shutdown(struct tas2552_data *tas_data, int sw_shutdown)
{
u8 cfg1_reg;
......@@ -90,6 +128,7 @@ static void tas2552_sw_shutdown(struct tas2552_data *tas_data, int sw_shutdown)
snd_soc_update_bits(tas_data->codec, TAS2552_CFG_1,
TAS2552_SWS_MASK, cfg1_reg);
}
#endif
static int tas2552_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
......@@ -101,10 +140,6 @@ static int tas2552_hw_params(struct snd_pcm_substream *substream,
int d;
u8 p, j;
/* Turn on Class D amplifier */
snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_CLASSD_EN_MASK,
TAS2552_CLASSD_EN);
if (!tas2552->mclk)
return -EINVAL;
......@@ -147,9 +182,6 @@ static int tas2552_hw_params(struct snd_pcm_substream *substream,
}
snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE,
TAS2552_PLL_ENABLE);
return 0;
}
......@@ -269,19 +301,10 @@ static const struct dev_pm_ops tas2552_pm = {
NULL)
};
static void tas2552_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, 0);
}
static struct snd_soc_dai_ops tas2552_speaker_dai_ops = {
.hw_params = tas2552_hw_params,
.set_sysclk = tas2552_set_dai_sysclk,
.set_fmt = tas2552_set_dai_fmt,
.shutdown = tas2552_shutdown,
.digital_mute = tas2552_mute,
};
......@@ -294,7 +317,7 @@ static struct snd_soc_dai_driver tas2552_dai[] = {
{
.name = "tas2552-amplifier",
.playback = {
.stream_name = "Speaker",
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000,
......@@ -312,6 +335,7 @@ static DECLARE_TLV_DB_SCALE(dac_tlv, -7, 100, 24);
static const struct snd_kcontrol_new tas2552_snd_controls[] = {
SOC_SINGLE_TLV("Speaker Driver Playback Volume",
TAS2552_PGA_GAIN, 0, 0x1f, 1, dac_tlv),
SOC_DAPM_SINGLE("Playback AMP", SND_SOC_NOPM, 0, 1, 0),
};
static const struct reg_default tas2552_init_regs[] = {
......@@ -321,6 +345,7 @@ static const struct reg_default tas2552_init_regs[] = {
static int tas2552_codec_probe(struct snd_soc_codec *codec)
{
struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret;
tas2552->codec = codec;
......@@ -362,9 +387,14 @@ static int tas2552_codec_probe(struct snd_soc_codec *codec)
goto patch_fail;
}
snd_soc_write(codec, TAS2552_CFG_2, TAS2552_CLASSD_EN |
TAS2552_BOOST_EN | TAS2552_APT_EN |
TAS2552_LIM_EN);
snd_soc_write(codec, TAS2552_CFG_2, TAS2552_BOOST_EN |
TAS2552_APT_EN | TAS2552_LIM_EN);
snd_soc_dapm_new_controls(dapm, tas2552_dapm_widgets,
ARRAY_SIZE(tas2552_dapm_widgets));
snd_soc_dapm_add_routes(dapm, tas2552_audio_map,
ARRAY_SIZE(tas2552_audio_map));
return 0;
patch_fail:
......
This diff is collapsed.
......@@ -18,7 +18,8 @@
#define AIC31XX_RATES SNDRV_PCM_RATE_8000_192000
#define AIC31XX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
| SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
| SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE \
| SNDRV_PCM_FMTBIT_S32_LE)
#define AIC31XX_STEREO_CLASS_D_BIT 0x1
......
......@@ -1121,6 +1121,7 @@ static int aic3x_regulator_event(struct notifier_block *nb,
static int aic3x_set_power(struct snd_soc_codec *codec, int power)
{
struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
unsigned int pll_c, pll_d;
int ret;
if (power) {
......@@ -1138,6 +1139,18 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
/* Sync reg_cache with the hardware */
regcache_cache_only(aic3x->regmap, false);
regcache_sync(aic3x->regmap);
/* Rewrite paired PLL D registers in case cached sync skipped
* writing one of them and thus caused other one also not
* being written
*/
pll_c = snd_soc_read(codec, AIC3X_PLL_PROGC_REG);
pll_d = snd_soc_read(codec, AIC3X_PLL_PROGD_REG);
if (pll_c == aic3x_reg[AIC3X_PLL_PROGC_REG].def ||
pll_d == aic3x_reg[AIC3X_PLL_PROGD_REG].def) {
snd_soc_write(codec, AIC3X_PLL_PROGC_REG, pll_c);
snd_soc_write(codec, AIC3X_PLL_PROGD_REG, pll_d);
}
} else {
/*
* Do soft reset to this codec instance in order to clear
......@@ -1222,20 +1235,6 @@ static struct snd_soc_dai_driver aic3x_dai = {
.symmetric_rates = 1,
};
static int aic3x_suspend(struct snd_soc_codec *codec)
{
aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int aic3x_resume(struct snd_soc_codec *codec)
{
aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
static void aic3x_mono_init(struct snd_soc_codec *codec)
{
/* DAC to Mono Line Out default volume and route to Output mixer */
......@@ -1429,8 +1428,6 @@ static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
.idle_bias_off = true,
.probe = aic3x_probe,
.remove = aic3x_remove,
.suspend = aic3x_suspend,
.resume = aic3x_resume,
.controls = aic3x_snd_controls,
.num_controls = ARRAY_SIZE(aic3x_snd_controls),
.dapm_widgets = aic3x_dapm_widgets,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment