ASoC: Updates for v3.17
This has been a pretty exciting release in terms of the framework, we've finally got support for multiple CODECs attached to a single DAI link which has been something there's been interest in as long as I've been working on ASoC. A big thanks to Benoit and Misael for their work on this. Otherwise it's been a fairly standard release for development, including more componentisation work from Lars-Peter and a good selection of both CODEC and CPU drivers. - Support for multiple CODECs attached to a single DAI, enabling systems with for example multiple DAC/speaker drivers on a single link, contributed by Benoit Cousson based on work from Misael Lopez Cruz. - Support for byte controls larger than 256 bytes based on the use of TLVs contributed by Omair Mohammed Abdullah. - More componentisation work from Lars-Peter Clausen. - The remainder of the conversions of CODEC drivers to params_width() - Drivers for Cirrus Logic CS4265, Freescale i.MX ASRC blocks, Realtek RT286 and RT5670, Rockchip RK3xxx I2S controllers and Texas Instruments TAS2552. - Lots of updates and fixes, especially to the DaVinci, Intel, Freescale, Realtek, and rcar drivers. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJT37EhAAoJELSic+t+oim9ELcP/j4ve2Zb3zqVn+md2fJNLFt6 7rD8eZTvy9XEoYVLIxNOroiM4Dl6m0FlA3gigzbpHLRUlZWH6JB1EDsn/kuB910Y E9T76HVzznUtmoEbbo2CRYelsO2I3RmlpJWYrzfkwQVAnSd+tQmWixypZzKEJcvP F+1gUA5DlTnSrDtFAcA0n5xhqczbrJ51l5l2irVf1eKdWTepixk0tMBonadb/s3V Uh+EPl2htEmjpo4fHDzcULGCQABtiPn9ebV4urQnhWMifJehk5md9WyQchaRCz8c 95ERNc+hLbrTUEALSgI46PWP497hdz4kd1B1jahLGSnWqRIgm/NwyhjqC47kgJfv 8006v4nY4+T8d1yU4kFpB72f/xL6dxI53K6jRkie2WUQy+4L7kNp3egDJ4at9MdA iFSq+XzOmN978XVlYOj/9KXVS/fpgslYYwa+omok45MbqCWg8EZbWdFwv/uXlbza ldDjPKvz5LYfnSNES30Q29TMKnqvmdbIzbgqWPnT2RR4x0mxT6MWh5yM0WBBXqNV TM791q5cgUr07+f8LeeCS5J99H0OuElqn0OPIWOcqN2MI4Qp+8ZuswBCQtZ6i1V7 oleSIPc4clchsXuRF83vD4JjZYkx7wqTOmmRHbKDB4d/LFLH3J2DHJH99CD1IX0a 4J4h5Bmi2f3CCih7KLBD =pnce -----END PGP SIGNATURE----- Merge tag 'asoc-v3.17' into asoc-linus ASoC: Updates for v3.17 This has been a pretty exciting release in terms of the framework, we've finally got support for multiple CODECs attached to a single DAI link which has been something there's been interest in as long as I've been working on ASoC. A big thanks to Benoit and Misael for their work on this. Otherwise it's been a fairly standard release for development, including more componentisation work from Lars-Peter and a good selection of both CODEC and CPU drivers. - Support for multiple CODECs attached to a single DAI, enabling systems with for example multiple DAC/speaker drivers on a single link, contributed by Benoit Cousson based on work from Misael Lopez Cruz. - Support for byte controls larger than 256 bytes based on the use of TLVs contributed by Omair Mohammed Abdullah. - More componentisation work from Lars-Peter Clausen. - The remainder of the conversions of CODEC drivers to params_width() - Drivers for Cirrus Logic CS4265, Freescale i.MX ASRC blocks, Realtek RT286 and RT5670, Rockchip RK3xxx I2S controllers and Texas Instruments TAS2552. - Lots of updates and fixes, especially to the DaVinci, Intel, Freescale, Realtek, and rcar drivers. # gpg: Signature made Mon 04 Aug 2014 17:13:21 BST using RSA key ID 7EA229BD # 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>"
This commit is contained in:
commit
543c675482
|
@ -10,10 +10,14 @@ Optional properties:
|
|||
|
||||
- reset-gpio : a GPIO spec for the reset/power down pin.
|
||||
If specified, it will be deasserted at probe time.
|
||||
- va-supply : a regulator spec, providing 5.0V
|
||||
- vd-supply : a regulator spec, providing 3.3V
|
||||
|
||||
Example:
|
||||
|
||||
spdif: ak5386@0 {
|
||||
compatible = "asahi-kasei,ak5386";
|
||||
reset-gpio = <&gpio0 23>;
|
||||
va-supply = <&vdd_5v0_reg>;
|
||||
vd-supply = <&vdd_3v3_reg>;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
CS4265 audio CODEC
|
||||
|
||||
This device supports I2C only.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "cirrus,cs4265"
|
||||
|
||||
- reg : the I2C address of the device for I2C. The I2C address depends on
|
||||
the state of the AD0 pin. If AD0 is high, the i2c address is 0x4f.
|
||||
If it is low, the i2c address is 0x4e.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- reset-gpios : a GPIO spec for the reset pin. If specified, it will be
|
||||
deasserted before communication to the codec starts.
|
||||
|
||||
Examples:
|
||||
|
||||
codec_ad0_high: cs4265@4f { /* AD0 Pin is high */
|
||||
compatible = "cirrus,cs4265";
|
||||
reg = <0x4f>;
|
||||
};
|
||||
|
||||
|
||||
codec_ad0_low: cs4265@4e { /* AD0 Pin is low */
|
||||
compatible = "cirrus,cs4265";
|
||||
reg = <0x4e>;
|
||||
};
|
|
@ -0,0 +1,60 @@
|
|||
Freescale Asynchronous Sample Rate Converter (ASRC) Controller
|
||||
|
||||
The Asynchronous Sample Rate Converter (ASRC) converts the sampling rate of a
|
||||
signal associated with an input clock into a signal associated with a different
|
||||
output clock. The driver currently works as a Front End of DPCM with other Back
|
||||
Ends Audio controller such as ESAI, SSI and SAI. It has three pairs to support
|
||||
three substreams within totally 10 channels.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : Contains "fsl,imx35-asrc" or "fsl,imx53-asrc".
|
||||
|
||||
- reg : Offset and length of the register set for the device.
|
||||
|
||||
- interrupts : Contains the spdif interrupt.
|
||||
|
||||
- dmas : Generic dma devicetree binding as described in
|
||||
Documentation/devicetree/bindings/dma/dma.txt.
|
||||
|
||||
- dma-names : Contains "rxa", "rxb", "rxc", "txa", "txb" and "txc".
|
||||
|
||||
- clocks : Contains an entry for each entry in clock-names.
|
||||
|
||||
- clock-names : Contains the following entries
|
||||
"mem" Peripheral access clock to access registers.
|
||||
"ipg" Peripheral clock to driver module.
|
||||
"asrck_<0-f>" Clock sources for input and output clock.
|
||||
|
||||
- big-endian : If this property is absent, the little endian mode
|
||||
will be in use as default. Otherwise, the big endian
|
||||
mode will be in use for all the device registers.
|
||||
|
||||
- fsl,asrc-rate : Defines a mutual sample rate used by DPCM Back Ends.
|
||||
|
||||
- fsl,asrc-width : Defines a mutual sample width used by DPCM Back Ends.
|
||||
|
||||
Example:
|
||||
|
||||
asrc: asrc@02034000 {
|
||||
compatible = "fsl,imx53-asrc";
|
||||
reg = <0x02034000 0x4000>;
|
||||
interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clks 107>, <&clks 107>, <&clks 0>,
|
||||
<&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
|
||||
<&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
|
||||
<&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
|
||||
<&clks 107>, <&clks 0>, <&clks 0>;
|
||||
clock-names = "mem", "ipg", "asrck0",
|
||||
"asrck_1", "asrck_2", "asrck_3", "asrck_4",
|
||||
"asrck_5", "asrck_6", "asrck_7", "asrck_8",
|
||||
"asrck_9", "asrck_a", "asrck_b", "asrck_c",
|
||||
"asrck_d", "asrck_e", "asrck_f";
|
||||
dmas = <&sdma 17 23 1>, <&sdma 18 23 1>, <&sdma 19 23 1>,
|
||||
<&sdma 20 23 1>, <&sdma 21 23 1>, <&sdma 22 23 1>;
|
||||
dma-names = "rxa", "rxb", "rxc",
|
||||
"txa", "txb", "txc";
|
||||
fsl,asrc-rate = <48000>;
|
||||
fsl,asrc-width = <16>;
|
||||
status = "okay";
|
||||
};
|
|
@ -4,7 +4,7 @@ This device supports I2C only.
|
|||
|
||||
Required properties:
|
||||
|
||||
- compatible : "maxim,max98090".
|
||||
- compatible : "maxim,max98090" or "maxim,max98091".
|
||||
|
||||
- reg : The I2C address of the device.
|
||||
|
||||
|
|
|
@ -13,6 +13,9 @@ Required properties:
|
|||
- rcar_sound,src : Should contain SRC feature.
|
||||
The number of SRC subnode should be same as HW.
|
||||
see below for detail.
|
||||
- rcar_sound,dvc : Should contain DVC feature.
|
||||
The number of DVC subnode should be same as HW.
|
||||
see below for detail.
|
||||
- rcar_sound,dai : DAI contents.
|
||||
The number of DAI subnode should be same as HW.
|
||||
see below for detail.
|
||||
|
@ -21,6 +24,7 @@ SSI subnode properties:
|
|||
- interrupts : Should contain SSI interrupt for PIO transfer
|
||||
- shared-pin : if shared clock pin
|
||||
- pio-transfer : use PIO transfer mode
|
||||
- no-busif : BUSIF is not ussed when [mem -> SSI] via DMA case
|
||||
|
||||
SRC subnode properties:
|
||||
no properties at this point
|
||||
|
@ -39,6 +43,11 @@ rcar_sound: rcar_sound@0xffd90000 {
|
|||
<0 0xec540000 0 0x1000>, /* SSIU */
|
||||
<0 0xec541000 0 0x1280>; /* SSI */
|
||||
|
||||
rcar_sound,dvc {
|
||||
dvc0: dvc@0 { };
|
||||
dvc1: dvc@1 { };
|
||||
};
|
||||
|
||||
rcar_sound,src {
|
||||
src0: src@0 { };
|
||||
src1: src@1 { };
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
* Rockchip I2S controller
|
||||
|
||||
The I2S bus (Inter-IC sound bus) is a serial link for digital
|
||||
audio data transfer between devices in the system.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: should be one of the followings
|
||||
- "rockchip,rk3066-i2s": for rk3066
|
||||
- "rockchip,rk3188-i2s", "rockchip,rk3066-i2s": for rk3188
|
||||
- "rockchip,rk3288-i2s", "rockchip,rk3066-i2s": for rk3288
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts: should contain the I2S interrupt.
|
||||
- #address-cells: should be 1.
|
||||
- #size-cells: should be 0.
|
||||
- dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
|
||||
Documentation/devicetree/bindings/dma/dma.txt
|
||||
- dma-names: should include "tx" and "rx".
|
||||
- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names.
|
||||
- clock-names: should contain followings:
|
||||
- "i2s_hclk": clock for I2S BUS
|
||||
- "i2s_clk" : clock for I2S controller
|
||||
|
||||
Example for rk3288 I2S controller:
|
||||
|
||||
i2s@ff890000 {
|
||||
compatible = "rockchip,rk3288-i2s", "rockchip,rk3066-i2s";
|
||||
reg = <0xff890000 0x10000>;
|
||||
interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
dmas = <&pdma1 0>, <&pdma1 1>;
|
||||
dma-names = "rx", "tx";
|
||||
clock-names = "i2s_hclk", "i2s_clk";
|
||||
clocks = <&cru HCLK_I2S0>, <&cru SCLK_I2S0>;
|
||||
};
|
|
@ -0,0 +1,35 @@
|
|||
Samsung Exynos Odroid X2/U3 audio complex with MAX98090 codec
|
||||
|
||||
Required properties:
|
||||
- compatible : "samsung,odroidx2-audio" - for Odroid X2 board,
|
||||
"samsung,odroidu3-audio" - for Odroid U3 board
|
||||
- samsung,model : the user-visible name of this sound complex
|
||||
- samsung,i2s-controller : the phandle of the I2S controller
|
||||
- samsung,audio-codec : the phandle of the MAX98090 audio codec
|
||||
- samsung,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 for sources and sinks are the MAX98090's pins (as
|
||||
documented in its binding), and the jacks on the board
|
||||
For Odroid X2:
|
||||
* Headphone Jack
|
||||
* Mic Jack
|
||||
* DMIC
|
||||
|
||||
For Odroid U3:
|
||||
* Headphone Jack
|
||||
* Speakers
|
||||
|
||||
Example:
|
||||
|
||||
sound {
|
||||
compatible = "samsung,odroidu3-audio";
|
||||
samsung,i2s-controller = <&i2s0>;
|
||||
samsung,audio-codec = <&max98090>;
|
||||
samsung,model = "Odroid-X2";
|
||||
samsung,audio-routing =
|
||||
"Headphone Jack", "HPL",
|
||||
"Headphone Jack", "HPR",
|
||||
"IN1", "Mic Jack",
|
||||
"Mic Jack", "MICBIAS";
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
* SiRF SoC USP module
|
||||
|
||||
Required properties:
|
||||
- compatible: "sirf,prima2-usp-pcm"
|
||||
- reg: Base address and size entries:
|
||||
- dmas: List of DMA controller phandle and DMA request line ordered pairs.
|
||||
- dma-names: Identifier string for each DMA request line in the dmas property.
|
||||
These strings correspond 1:1 with the ordered pairs in dmas.
|
||||
|
||||
One of the DMA channels will be responsible for transmission (should be
|
||||
named "tx") and one for reception (should be named "rx").
|
||||
|
||||
- clocks: USP controller clock source
|
||||
- pinctrl-names: Must contain a "default" entry.
|
||||
- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
|
||||
|
||||
Example:
|
||||
usp0: usp@b0080000 {
|
||||
compatible = "sirf,prima2-usp-pcm";
|
||||
reg = <0xb0080000 0x10000>;
|
||||
clocks = <&clks 28>;
|
||||
dmas = <&dmac1 1>, <&dmac1 2>;
|
||||
dma-names = "rx", "tx";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&usp0_only_utfs_pins_a>;
|
||||
};
|
||||
|
|
@ -3,15 +3,20 @@ Audio Binding for Snow boards
|
|||
Required properties:
|
||||
- compatible : Can be one of the following,
|
||||
"google,snow-audio-max98090" or
|
||||
"google,snow-audio-max98091" or
|
||||
"google,snow-audio-max98095"
|
||||
- samsung,i2s-controller: The phandle of the Samsung I2S controller
|
||||
- samsung,audio-codec: The phandle of the audio codec
|
||||
|
||||
Optional:
|
||||
- samsung,model: The name of the sound-card
|
||||
|
||||
Example:
|
||||
|
||||
sound {
|
||||
compatible = "google,snow-audio-max98095";
|
||||
|
||||
samsung,model = "Snow-I2S-MAX98095";
|
||||
samsung,i2s-controller = <&i2s0>;
|
||||
samsung,audio-codec = <&max98095>;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
Texas Instruments - tas2552 Codec module
|
||||
|
||||
The tas2552 serial control bus communicates through I2C protocols
|
||||
|
||||
Required properties:
|
||||
- compatible - One of:
|
||||
"ti,tas2552" - TAS2552
|
||||
- reg - I2C slave address
|
||||
- supply-*: Required supply regulators are:
|
||||
"vbat" battery voltage
|
||||
"iovdd" I/O Voltage
|
||||
"avdd" Analog DAC Voltage
|
||||
|
||||
Optional properties:
|
||||
- enable-gpio - gpio pin to enable/disable the device
|
||||
|
||||
Example:
|
||||
|
||||
tas2552: tas2552@41 {
|
||||
compatible = "ti,tas2552";
|
||||
reg = <0x41>;
|
||||
enable-gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
For more product information please see the link below:
|
||||
http://www.ti.com/product/TAS2552
|
|
@ -31,6 +31,9 @@ Optional properties:
|
|||
|
||||
Most systems should not set any of these properties.
|
||||
|
||||
- avdd-supply: Power supply for AVDD, providing 3.3V
|
||||
- dvdd-supply: Power supply for DVDD, providing 3.3V
|
||||
|
||||
Examples:
|
||||
|
||||
i2c_bus {
|
||||
|
@ -39,5 +42,7 @@ Examples:
|
|||
reg = <0x1b>;
|
||||
reset-gpio = <&gpio 23 0>;
|
||||
ti,charge-period = <156000>;
|
||||
avdd-supply = <&vdd_3v3_reg>;
|
||||
dvdd-supply = <&vdd_3v3_reg>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
WM8904 audio CODEC
|
||||
|
||||
This device supports I2C only.
|
||||
|
||||
Required properties:
|
||||
- compatible: "wlf,wm8904"
|
||||
- reg: the I2C address of the device.
|
||||
- clock-names: "mclk"
|
||||
- clocks: reference to
|
||||
<Documentation/devicetree/bindings/clock/clock-bindings.txt>
|
||||
|
||||
Pins on the device (for linking into audio routes):
|
||||
|
||||
* IN1L
|
||||
* IN1R
|
||||
* IN2L
|
||||
* IN2R
|
||||
* IN3L
|
||||
* IN3R
|
||||
* HPOUTL
|
||||
* HPOUTR
|
||||
* LINEOUTL
|
||||
* LINEOUTR
|
||||
* MICBIAS
|
||||
|
||||
Examples:
|
||||
|
||||
codec: wm8904@1a {
|
||||
compatible = "wlf,wm8904";
|
||||
reg = <0x1a>;
|
||||
clocks = <&pck0>;
|
||||
clock-names = "mclk";
|
||||
};
|
|
@ -7479,6 +7479,13 @@ F: drivers/rtc/
|
|||
F: include/linux/rtc.h
|
||||
F: include/uapi/linux/rtc.h
|
||||
|
||||
REALTEK AUDIO CODECS
|
||||
M: Bard Liao <bardliao@realtek.com>
|
||||
M: Oder Chiou <oder_chiou@realtek.com>
|
||||
S: Maintained
|
||||
F: sound/soc/codecs/rt*
|
||||
F: include/sound/rt*.h
|
||||
|
||||
REISERFS FILE SYSTEM
|
||||
L: reiserfs-devel@vger.kernel.org
|
||||
S: Supported
|
||||
|
|
|
@ -998,6 +998,8 @@ static struct platform_device fsi_wm8978_device = {
|
|||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &fsi_wm8978_info,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.dma_mask = &fsi_wm8978_device.dev.coherent_dma_mask,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1021,6 +1023,8 @@ static struct platform_device fsi_hdmi_device = {
|
|||
.id = 1,
|
||||
.dev = {
|
||||
.platform_data = &fsi2_hdmi_info,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.dma_mask = &fsi_hdmi_device.dev.coherent_dma_mask,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -603,6 +603,8 @@ static struct platform_device fsi_ak4648_device = {
|
|||
.name = "asoc-simple-card",
|
||||
.dev = {
|
||||
.platform_data = &fsi2_ak4648_info,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.dma_mask = &fsi_ak4648_device.dev.coherent_dma_mask,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -523,6 +523,8 @@ static struct platform_device fsi_hdmi_device = {
|
|||
.id = 1,
|
||||
.dev = {
|
||||
.platform_data = &fsi2_hdmi_info,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.dma_mask = &fsi_hdmi_device.dev.coherent_dma_mask,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -919,6 +921,8 @@ static struct platform_device fsi_ak4643_device = {
|
|||
.name = "asoc-simple-card",
|
||||
.dev = {
|
||||
.platform_data = &fsi2_ak4643_info,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.dma_mask = &fsi_ak4643_device.dev.coherent_dma_mask,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -874,6 +874,8 @@ static struct platform_device fsi_da7210_device = {
|
|||
.name = "asoc-simple-card",
|
||||
.dev = {
|
||||
.platform_data = &fsi_da7210_info,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.dma_mask = &fsi_da7210_device.dev.coherent_dma_mask,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* platform_sst_audio.h: sst audio platform data header file
|
||||
*
|
||||
* Copyright (C) 2012-14 Intel Corporation
|
||||
* Author: Jeeja KP <jeeja.kp@intel.com>
|
||||
* Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
|
||||
* Vinod Koul ,vinod.koul@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.
|
||||
*/
|
||||
#ifndef _PLATFORM_SST_AUDIO_H_
|
||||
#define _PLATFORM_SST_AUDIO_H_
|
||||
|
||||
#include <linux/sfi.h>
|
||||
|
||||
enum sst_audio_task_id_mrfld {
|
||||
SST_TASK_ID_NONE = 0,
|
||||
SST_TASK_ID_SBA = 1,
|
||||
SST_TASK_ID_MEDIA = 3,
|
||||
SST_TASK_ID_MAX = SST_TASK_ID_MEDIA,
|
||||
};
|
||||
|
||||
/* Device IDs for Merrifield are Pipe IDs,
|
||||
* ref: DSP spec v0.75 */
|
||||
enum sst_audio_device_id_mrfld {
|
||||
/* Output pipeline IDs */
|
||||
PIPE_ID_OUT_START = 0x0,
|
||||
PIPE_CODEC_OUT0 = 0x2,
|
||||
PIPE_CODEC_OUT1 = 0x3,
|
||||
PIPE_SPROT_LOOP_OUT = 0x4,
|
||||
PIPE_MEDIA_LOOP1_OUT = 0x5,
|
||||
PIPE_MEDIA_LOOP2_OUT = 0x6,
|
||||
PIPE_VOIP_OUT = 0xC,
|
||||
PIPE_PCM0_OUT = 0xD,
|
||||
PIPE_PCM1_OUT = 0xE,
|
||||
PIPE_PCM2_OUT = 0xF,
|
||||
PIPE_MEDIA0_OUT = 0x12,
|
||||
PIPE_MEDIA1_OUT = 0x13,
|
||||
/* Input Pipeline IDs */
|
||||
PIPE_ID_IN_START = 0x80,
|
||||
PIPE_CODEC_IN0 = 0x82,
|
||||
PIPE_CODEC_IN1 = 0x83,
|
||||
PIPE_SPROT_LOOP_IN = 0x84,
|
||||
PIPE_MEDIA_LOOP1_IN = 0x85,
|
||||
PIPE_MEDIA_LOOP2_IN = 0x86,
|
||||
PIPE_VOIP_IN = 0x8C,
|
||||
PIPE_PCM0_IN = 0x8D,
|
||||
PIPE_PCM1_IN = 0x8E,
|
||||
PIPE_MEDIA0_IN = 0x8F,
|
||||
PIPE_MEDIA1_IN = 0x90,
|
||||
PIPE_MEDIA2_IN = 0x91,
|
||||
PIPE_RSVD = 0xFF,
|
||||
};
|
||||
|
||||
/* The stream map for each platform consists of an array of the below
|
||||
* stream map structure.
|
||||
*/
|
||||
struct sst_dev_stream_map {
|
||||
u8 dev_num; /* device id */
|
||||
u8 subdev_num; /* substream */
|
||||
u8 direction;
|
||||
u8 device_id; /* fw id */
|
||||
u8 task_id; /* fw task */
|
||||
u8 status;
|
||||
};
|
||||
|
||||
struct sst_platform_data {
|
||||
/* Intel software platform id*/
|
||||
struct sst_dev_stream_map *pdev_strm_map;
|
||||
unsigned int strm_map_size;
|
||||
};
|
||||
|
||||
int add_sst_platform_device(void);
|
||||
#endif
|
||||
|
|
@ -982,6 +982,7 @@ static void __init edma_chan_init(struct edma_cc *ecc,
|
|||
|
||||
#define EDMA_DMA_BUSWIDTHS (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
|
||||
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
|
||||
BIT(DMA_SLAVE_BUSWIDTH_3_BYTES) | \
|
||||
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES))
|
||||
|
||||
static int edma_dma_device_slave_caps(struct dma_chan *dchan,
|
||||
|
|
|
@ -83,16 +83,26 @@ EXPORT_SYMBOL(ssc_free);
|
|||
|
||||
static struct atmel_ssc_platform_data at91rm9200_config = {
|
||||
.use_dma = 0,
|
||||
.has_fslen_ext = 0,
|
||||
};
|
||||
|
||||
static struct atmel_ssc_platform_data at91sam9rl_config = {
|
||||
.use_dma = 0,
|
||||
.has_fslen_ext = 1,
|
||||
};
|
||||
|
||||
static struct atmel_ssc_platform_data at91sam9g45_config = {
|
||||
.use_dma = 1,
|
||||
.has_fslen_ext = 1,
|
||||
};
|
||||
|
||||
static const struct platform_device_id atmel_ssc_devtypes[] = {
|
||||
{
|
||||
.name = "at91rm9200_ssc",
|
||||
.driver_data = (unsigned long) &at91rm9200_config,
|
||||
}, {
|
||||
.name = "at91sam9rl_ssc",
|
||||
.driver_data = (unsigned long) &at91sam9rl_config,
|
||||
}, {
|
||||
.name = "at91sam9g45_ssc",
|
||||
.driver_data = (unsigned long) &at91sam9g45_config,
|
||||
|
@ -106,6 +116,9 @@ static const struct of_device_id atmel_ssc_dt_ids[] = {
|
|||
{
|
||||
.compatible = "atmel,at91rm9200-ssc",
|
||||
.data = &at91rm9200_config,
|
||||
}, {
|
||||
.compatible = "atmel,at91sam9rl-ssc",
|
||||
.data = &at91sam9rl_config,
|
||||
}, {
|
||||
.compatible = "atmel,at91sam9g45-ssc",
|
||||
.data = &at91sam9g45_config,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
struct atmel_ssc_platform_data {
|
||||
int use_dma;
|
||||
int has_fslen_ext;
|
||||
};
|
||||
|
||||
struct ssc_device {
|
||||
|
@ -71,6 +72,12 @@ void ssc_free(struct ssc_device *ssc);
|
|||
#define SSC_RFMR_DATNB_OFFSET 8
|
||||
#define SSC_RFMR_FSEDGE_SIZE 1
|
||||
#define SSC_RFMR_FSEDGE_OFFSET 24
|
||||
/*
|
||||
* The FSLEN_EXT exist on at91sam9rl, at91sam9g10,
|
||||
* at91sam9g20, and at91sam9g45 and newer SoCs
|
||||
*/
|
||||
#define SSC_RFMR_FSLEN_EXT_SIZE 4
|
||||
#define SSC_RFMR_FSLEN_EXT_OFFSET 28
|
||||
#define SSC_RFMR_FSLEN_SIZE 4
|
||||
#define SSC_RFMR_FSLEN_OFFSET 16
|
||||
#define SSC_RFMR_FSOS_SIZE 4
|
||||
|
@ -109,6 +116,12 @@ void ssc_free(struct ssc_device *ssc);
|
|||
#define SSC_TFMR_FSDEN_OFFSET 23
|
||||
#define SSC_TFMR_FSEDGE_SIZE 1
|
||||
#define SSC_TFMR_FSEDGE_OFFSET 24
|
||||
/*
|
||||
* The FSLEN_EXT exist on at91sam9rl, at91sam9g10,
|
||||
* at91sam9g20, and at91sam9g45 and newer SoCs
|
||||
*/
|
||||
#define SSC_TFMR_FSLEN_EXT_SIZE 4
|
||||
#define SSC_TFMR_FSLEN_EXT_OFFSET 28
|
||||
#define SSC_TFMR_FSLEN_SIZE 4
|
||||
#define SSC_TFMR_FSLEN_OFFSET 16
|
||||
#define SSC_TFMR_FSOS_SIZE 3
|
||||
|
|
|
@ -299,6 +299,7 @@ enum dma_slave_buswidth {
|
|||
DMA_SLAVE_BUSWIDTH_UNDEFINED = 0,
|
||||
DMA_SLAVE_BUSWIDTH_1_BYTE = 1,
|
||||
DMA_SLAVE_BUSWIDTH_2_BYTES = 2,
|
||||
DMA_SLAVE_BUSWIDTH_3_BYTES = 3,
|
||||
DMA_SLAVE_BUSWIDTH_4_BYTES = 4,
|
||||
DMA_SLAVE_BUSWIDTH_8_BYTES = 8,
|
||||
};
|
||||
|
|
|
@ -110,6 +110,12 @@ struct arizona {
|
|||
int clk32k_ref;
|
||||
|
||||
struct snd_soc_dapm_context *dapm;
|
||||
|
||||
int tdm_width[ARIZONA_MAX_AIF];
|
||||
int tdm_slots[ARIZONA_MAX_AIF];
|
||||
|
||||
uint16_t dac_comp_coeff;
|
||||
uint8_t dac_comp_enabled;
|
||||
};
|
||||
|
||||
int arizona_clk32k_enable(struct arizona *arizona);
|
||||
|
|
|
@ -15,15 +15,6 @@
|
|||
#define S3C64XX_AC97_GPE 1
|
||||
extern void s3c64xx_ac97_setup_gpio(int);
|
||||
|
||||
/*
|
||||
* The machine init code calls s5p*_spdif_setup_gpio with
|
||||
* one of these defines in order to select appropriate bank
|
||||
* of GPIO for S/PDIF pins
|
||||
*/
|
||||
#define S5PC100_SPDIF_GPD 0
|
||||
#define S5PC100_SPDIF_GPG3 1
|
||||
extern void s5pc100_spdif_setup_gpio(int);
|
||||
|
||||
struct samsung_i2s {
|
||||
/* If the Primary DAI has 5.1 Channels */
|
||||
#define QUIRK_PRI_6CHAN (1 << 0)
|
||||
|
|
|
@ -50,6 +50,7 @@ enum imx_dma_prio {
|
|||
|
||||
struct imx_dma_data {
|
||||
int dma_request; /* DMA request line */
|
||||
int dma_request2; /* secondary DMA request line */
|
||||
enum sdma_peripheral_type peripheral_type;
|
||||
int priority;
|
||||
};
|
||||
|
|
|
@ -31,10 +31,15 @@ typedef int (snd_kcontrol_info_t) (struct snd_kcontrol * kcontrol, struct snd_ct
|
|||
typedef int (snd_kcontrol_get_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
|
||||
typedef int (snd_kcontrol_put_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
|
||||
typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol,
|
||||
int op_flag, /* 0=read,1=write,-1=command */
|
||||
int op_flag, /* SNDRV_CTL_TLV_OP_XXX */
|
||||
unsigned int size,
|
||||
unsigned int __user *tlv);
|
||||
|
||||
enum {
|
||||
SNDRV_CTL_TLV_OP_READ = 0,
|
||||
SNDRV_CTL_TLV_OP_WRITE = 1,
|
||||
SNDRV_CTL_TLV_OP_CMD = -1,
|
||||
};
|
||||
|
||||
struct snd_kcontrol_new {
|
||||
snd_ctl_elem_iface_t iface; /* interface identifier */
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
* B : SSI direction
|
||||
*/
|
||||
#define RSND_SSI_CLK_PIN_SHARE (1 << 31)
|
||||
#define RSND_SSI_NO_BUSIF (1 << 30) /* SSI+DMA without BUSIF */
|
||||
|
||||
#define RSND_SSI(_dma_id, _pio_irq, _flags) \
|
||||
{ .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags }
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* linux/sound/rt286.h -- Platform data for RT286
|
||||
*
|
||||
* Copyright 2013 Realtek Microelectronics
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_SND_RT286_H
|
||||
#define __LINUX_SND_RT286_H
|
||||
|
||||
struct rt286_platform_data {
|
||||
bool cbj_en; /*combo jack enable*/
|
||||
bool gpio2_en; /*GPIO2 enable*/
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* linux/sound/rt5670.h -- Platform data for RT5670
|
||||
*
|
||||
* Copyright 2014 Realtek Microelectronics
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_SND_RT5670_H
|
||||
#define __LINUX_SND_RT5670_H
|
||||
|
||||
struct rt5670_platform_data {
|
||||
int jd_mode;
|
||||
bool in2_diff;
|
||||
|
||||
bool dmic_en;
|
||||
unsigned int dmic1_data_pin;
|
||||
/* 0 = GPIO6; 1 = IN2P; 3 = GPIO7*/
|
||||
unsigned int dmic2_data_pin;
|
||||
/* 0 = GPIO8; 1 = IN3N; */
|
||||
unsigned int dmic3_data_pin;
|
||||
/* 0 = GPIO9; 1 = GPIO10; 2 = GPIO5*/
|
||||
};
|
||||
|
||||
#endif
|
|
@ -257,7 +257,6 @@ struct snd_soc_dai {
|
|||
|
||||
struct snd_soc_dapm_widget *playback_widget;
|
||||
struct snd_soc_dapm_widget *capture_widget;
|
||||
struct snd_soc_dapm_context dapm;
|
||||
|
||||
/* DAI DMA data */
|
||||
void *playback_dma_data;
|
||||
|
@ -273,6 +272,10 @@ struct snd_soc_dai {
|
|||
struct snd_soc_codec *codec;
|
||||
struct snd_soc_component *component;
|
||||
|
||||
/* CODEC TDM slot masks and params (for fixup) */
|
||||
unsigned int tx_mask;
|
||||
unsigned int rx_mask;
|
||||
|
||||
struct snd_soc_card *card;
|
||||
|
||||
struct list_head list;
|
||||
|
|
|
@ -431,7 +431,7 @@ int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
|
|||
const char *pin);
|
||||
int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
|
||||
const char *pin);
|
||||
void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec);
|
||||
void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card);
|
||||
|
||||
/* Mostly internal - should not normally be used */
|
||||
void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm);
|
||||
|
@ -441,6 +441,8 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
|
|||
struct snd_soc_dapm_widget_list **list);
|
||||
|
||||
struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol);
|
||||
struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm(
|
||||
struct snd_kcontrol *kcontrol);
|
||||
|
||||
/* dapm widget types */
|
||||
enum snd_soc_dapm_type {
|
||||
|
@ -524,7 +526,6 @@ struct snd_soc_dapm_widget {
|
|||
const char *name; /* widget name */
|
||||
const char *sname; /* stream name */
|
||||
struct snd_soc_codec *codec;
|
||||
struct snd_soc_platform *platform;
|
||||
struct list_head list;
|
||||
struct snd_soc_dapm_context *dapm;
|
||||
|
||||
|
@ -593,7 +594,6 @@ struct snd_soc_dapm_context {
|
|||
struct device *dev; /* from parent - for debug */
|
||||
struct snd_soc_component *component; /* parent component */
|
||||
struct snd_soc_codec *codec; /* parent codec */
|
||||
struct snd_soc_platform *platform; /* parent platform */
|
||||
struct snd_soc_card *card; /* parent card */
|
||||
|
||||
/* used during DAPM updates */
|
||||
|
@ -601,6 +601,8 @@ struct snd_soc_dapm_context {
|
|||
struct list_head list;
|
||||
|
||||
int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
|
||||
int (*set_bias_level)(struct snd_soc_dapm_context *dapm,
|
||||
enum snd_soc_bias_level level);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_dapm;
|
||||
|
|
|
@ -248,6 +248,8 @@
|
|||
.info = snd_soc_info_enum_double, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = (unsigned long)&xenum }
|
||||
#define SOC_VALUE_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) \
|
||||
SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put)
|
||||
|
||||
#define SND_SOC_BYTES(xname, xbase, xregs) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
|
@ -270,7 +272,14 @@
|
|||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = (unsigned long)&(struct soc_bytes_ext) \
|
||||
{.max = xcount} }
|
||||
|
||||
#define SND_SOC_BYTES_TLV(xname, xcount, xhandler_get, xhandler_put) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE | \
|
||||
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \
|
||||
.tlv.c = (snd_soc_bytes_tlv_callback), \
|
||||
.info = snd_soc_info_bytes_ext, \
|
||||
.private_value = (unsigned long)&(struct soc_bytes_ext) \
|
||||
{.max = xcount, .get = xhandler_get, .put = xhandler_put, } }
|
||||
#define SOC_SINGLE_XR_SX(xname, xregbase, xregcount, xnbits, \
|
||||
xmin, xmax, xinvert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
|
@ -436,6 +445,10 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
|
|||
int snd_soc_platform_trigger(struct snd_pcm_substream *substream,
|
||||
int cmd, struct snd_soc_platform *platform);
|
||||
|
||||
int soc_dai_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai);
|
||||
|
||||
/* Jack reporting */
|
||||
int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
|
||||
struct snd_soc_jack *jack);
|
||||
|
@ -503,10 +516,12 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
|
|||
const char *prefix);
|
||||
struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
|
||||
const char *name);
|
||||
int snd_soc_add_component_controls(struct snd_soc_component *component,
|
||||
const struct snd_kcontrol_new *controls, unsigned int num_controls);
|
||||
int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
|
||||
const struct snd_kcontrol_new *controls, int num_controls);
|
||||
const struct snd_kcontrol_new *controls, unsigned int num_controls);
|
||||
int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
|
||||
const struct snd_kcontrol_new *controls, int num_controls);
|
||||
const struct snd_kcontrol_new *controls, unsigned int num_controls);
|
||||
int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
|
||||
const struct snd_kcontrol_new *controls, int num_controls);
|
||||
int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
|
||||
|
@ -552,6 +567,8 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
|
|||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *ucontrol);
|
||||
int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag,
|
||||
unsigned int size, unsigned int __user *tlv);
|
||||
int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo);
|
||||
int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
|
||||
|
@ -677,12 +694,17 @@ struct snd_soc_component_driver {
|
|||
int (*of_xlate_dai_name)(struct snd_soc_component *component,
|
||||
struct of_phandle_args *args,
|
||||
const char **dai_name);
|
||||
void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type,
|
||||
int subseq);
|
||||
int (*stream_event)(struct snd_soc_component *, int event);
|
||||
};
|
||||
|
||||
struct snd_soc_component {
|
||||
const char *name;
|
||||
int id;
|
||||
const char *name_prefix;
|
||||
struct device *dev;
|
||||
struct snd_soc_card *card;
|
||||
|
||||
unsigned int active;
|
||||
|
||||
|
@ -705,18 +727,18 @@ struct snd_soc_component {
|
|||
int val_bytes;
|
||||
|
||||
struct mutex io_mutex;
|
||||
|
||||
/* Don't use these, use snd_soc_component_get_dapm() */
|
||||
struct snd_soc_dapm_context dapm;
|
||||
struct snd_soc_dapm_context *dapm_ptr;
|
||||
};
|
||||
|
||||
/* SoC Audio Codec device */
|
||||
struct snd_soc_codec {
|
||||
const char *name;
|
||||
const char *name_prefix;
|
||||
int id;
|
||||
struct device *dev;
|
||||
const struct snd_soc_codec_driver *driver;
|
||||
|
||||
struct mutex mutex;
|
||||
struct snd_soc_card *card;
|
||||
struct list_head list;
|
||||
struct list_head card_list;
|
||||
|
||||
|
@ -790,9 +812,6 @@ struct snd_soc_codec_driver {
|
|||
void (*seq_notifier)(struct snd_soc_dapm_context *,
|
||||
enum snd_soc_dapm_type, int);
|
||||
|
||||
/* codec stream completion event */
|
||||
int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
|
||||
|
||||
bool ignore_pmdown_time; /* Doesn't benefit from pmdown delay */
|
||||
|
||||
/* probe ordering - for components with runtime dependencies */
|
||||
|
@ -834,9 +853,6 @@ struct snd_soc_platform_driver {
|
|||
/* platform stream compress ops */
|
||||
const struct snd_compr_ops *compr_ops;
|
||||
|
||||
/* platform stream completion event */
|
||||
int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
|
||||
|
||||
/* probe ordering - for components with runtime dependencies */
|
||||
int probe_order;
|
||||
int remove_order;
|
||||
|
@ -847,23 +863,23 @@ struct snd_soc_platform_driver {
|
|||
int (*bespoke_trigger)(struct snd_pcm_substream *, int);
|
||||
};
|
||||
|
||||
struct snd_soc_platform {
|
||||
struct snd_soc_dai_link_component {
|
||||
const char *name;
|
||||
int id;
|
||||
const struct device_node *of_node;
|
||||
const char *dai_name;
|
||||
};
|
||||
|
||||
struct snd_soc_platform {
|
||||
struct device *dev;
|
||||
const struct snd_soc_platform_driver *driver;
|
||||
|
||||
unsigned int suspended:1; /* platform is suspended */
|
||||
unsigned int probed:1;
|
||||
|
||||
struct snd_soc_card *card;
|
||||
struct list_head list;
|
||||
struct list_head card_list;
|
||||
|
||||
struct snd_soc_component component;
|
||||
|
||||
struct snd_soc_dapm_context dapm;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_platform_root;
|
||||
#endif
|
||||
|
@ -896,6 +912,10 @@ struct snd_soc_dai_link {
|
|||
const struct device_node *codec_of_node;
|
||||
/* You MUST specify the DAI name within the codec */
|
||||
const char *codec_dai_name;
|
||||
|
||||
struct snd_soc_dai_link_component *codecs;
|
||||
unsigned int num_codecs;
|
||||
|
||||
/*
|
||||
* You MAY specify the link's platform/PCM/DMA driver, either by
|
||||
* device name, or by DT/OF node, but not both. Some forms of link
|
||||
|
@ -1047,7 +1067,6 @@ struct snd_soc_card {
|
|||
|
||||
/* lists of probed devices belonging to this card */
|
||||
struct list_head codec_dev_list;
|
||||
struct list_head platform_dev_list;
|
||||
|
||||
struct list_head widgets;
|
||||
struct list_head paths;
|
||||
|
@ -1094,6 +1113,9 @@ struct snd_soc_pcm_runtime {
|
|||
struct snd_soc_dai *codec_dai;
|
||||
struct snd_soc_dai *cpu_dai;
|
||||
|
||||
struct snd_soc_dai **codec_dais;
|
||||
unsigned int num_codecs;
|
||||
|
||||
struct delayed_work delayed_work;
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_dpcm_root;
|
||||
|
@ -1119,6 +1141,9 @@ struct soc_bytes {
|
|||
|
||||
struct soc_bytes_ext {
|
||||
int max;
|
||||
/* used for TLV byte control */
|
||||
int (*get)(unsigned int __user *bytes, unsigned int size);
|
||||
int (*put)(const unsigned int __user *bytes, unsigned int size);
|
||||
};
|
||||
|
||||
/* multi register control */
|
||||
|
@ -1164,6 +1189,21 @@ static inline struct snd_soc_platform *snd_soc_component_to_platform(
|
|||
return container_of(component, struct snd_soc_platform, component);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_dapm_to_component() - Casts a DAPM context to the component it is
|
||||
* embedded in
|
||||
* @dapm: The DAPM context to cast to the component
|
||||
*
|
||||
* This function must only be used on DAPM contexts that are known to be part of
|
||||
* a component (e.g. in a component driver). Otherwise the behavior is
|
||||
* undefined.
|
||||
*/
|
||||
static inline struct snd_soc_component *snd_soc_dapm_to_component(
|
||||
struct snd_soc_dapm_context *dapm)
|
||||
{
|
||||
return container_of(dapm, struct snd_soc_component, dapm);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_dapm_to_codec() - Casts a DAPM context to the CODEC it is embedded in
|
||||
* @dapm: The DAPM context to cast to the CODEC
|
||||
|
@ -1188,7 +1228,18 @@ static inline struct snd_soc_codec *snd_soc_dapm_to_codec(
|
|||
static inline struct snd_soc_platform *snd_soc_dapm_to_platform(
|
||||
struct snd_soc_dapm_context *dapm)
|
||||
{
|
||||
return container_of(dapm, struct snd_soc_platform, dapm);
|
||||
return snd_soc_component_to_platform(snd_soc_dapm_to_component(dapm));
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_component_get_dapm() - Returns the DAPM context associated with a
|
||||
* component
|
||||
* @component: The component for which to get the DAPM context
|
||||
*/
|
||||
static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm(
|
||||
struct snd_soc_component *component)
|
||||
{
|
||||
return component->dapm_ptr;
|
||||
}
|
||||
|
||||
/* codec IO */
|
||||
|
@ -1261,7 +1312,6 @@ static inline void *snd_soc_pcm_get_drvdata(struct snd_soc_pcm_runtime *rtd)
|
|||
static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card)
|
||||
{
|
||||
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);
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* TAS2552 driver platform header
|
||||
*
|
||||
* Copyright (C) 2014 Texas Instruments Inc.
|
||||
*
|
||||
* Author: Dan Murphy <dmurphy@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef TAS2552_PLAT_H
|
||||
#define TAS2552_PLAT_H
|
||||
|
||||
struct tas2552_platform_data {
|
||||
int enable_gpio;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -37,6 +37,7 @@
|
|||
#define WM8962_GPIO_FN_MICSCD 22
|
||||
|
||||
struct wm8962_pdata {
|
||||
struct clk *mclk;
|
||||
int gpio_base;
|
||||
u32 gpio_init[WM8962_MAX_GPIO];
|
||||
|
||||
|
|
|
@ -296,17 +296,17 @@ TRACE_EVENT(snd_soc_cache_sync,
|
|||
TP_ARGS(codec, type, status),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string( name, codec->name )
|
||||
__string( name, codec->component.name)
|
||||
__string( status, status )
|
||||
__string( type, type )
|
||||
__field( int, id )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, codec->name);
|
||||
__assign_str(name, codec->component.name);
|
||||
__assign_str(status, status);
|
||||
__assign_str(type, type);
|
||||
__entry->id = codec->id;
|
||||
__entry->id = codec->component.id;
|
||||
),
|
||||
|
||||
TP_printk("codec=%s.%d type=%s status=%s", __get_str(name),
|
||||
|
|
|
@ -152,9 +152,9 @@ static inline void pxa_ac97_cold_pxa27x(void)
|
|||
gsr_bits = 0;
|
||||
|
||||
/* PXA27x Developers Manual section 13.5.2.2.1 */
|
||||
clk_enable(ac97conf_clk);
|
||||
clk_prepare_enable(ac97conf_clk);
|
||||
udelay(5);
|
||||
clk_disable(ac97conf_clk);
|
||||
clk_disable_unprepare(ac97conf_clk);
|
||||
GCR = GCR_COLD_RST | GCR_WARM_RST;
|
||||
}
|
||||
#endif
|
||||
|
@ -299,14 +299,14 @@ static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id)
|
|||
int pxa2xx_ac97_hw_suspend(void)
|
||||
{
|
||||
GCR |= GCR_ACLINK_OFF;
|
||||
clk_disable(ac97_clk);
|
||||
clk_disable_unprepare(ac97_clk);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_suspend);
|
||||
|
||||
int pxa2xx_ac97_hw_resume(void)
|
||||
{
|
||||
clk_enable(ac97_clk);
|
||||
clk_prepare_enable(ac97_clk);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume);
|
||||
|
@ -368,7 +368,7 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev)
|
|||
goto err_clk;
|
||||
}
|
||||
|
||||
ret = clk_enable(ac97_clk);
|
||||
ret = clk_prepare_enable(ac97_clk);
|
||||
if (ret)
|
||||
goto err_clk2;
|
||||
|
||||
|
@ -403,7 +403,7 @@ void pxa2xx_ac97_hw_remove(struct platform_device *dev)
|
|||
clk_put(ac97conf_clk);
|
||||
ac97conf_clk = NULL;
|
||||
}
|
||||
clk_disable(ac97_clk);
|
||||
clk_disable_unprepare(ac97_clk);
|
||||
clk_put(ac97_clk);
|
||||
ac97_clk = NULL;
|
||||
}
|
||||
|
|
|
@ -1406,11 +1406,11 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
|
|||
case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
|
||||
return snd_ctl_subscribe_events(ctl, ip);
|
||||
case SNDRV_CTL_IOCTL_TLV_READ:
|
||||
return snd_ctl_tlv_ioctl(ctl, argp, 0);
|
||||
return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_READ);
|
||||
case SNDRV_CTL_IOCTL_TLV_WRITE:
|
||||
return snd_ctl_tlv_ioctl(ctl, argp, 1);
|
||||
return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_WRITE);
|
||||
case SNDRV_CTL_IOCTL_TLV_COMMAND:
|
||||
return snd_ctl_tlv_ioctl(ctl, argp, -1);
|
||||
return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_CMD);
|
||||
case SNDRV_CTL_IOCTL_POWER:
|
||||
return -ENOPROTOOPT;
|
||||
case SNDRV_CTL_IOCTL_POWER_STATE:
|
||||
|
|
|
@ -65,13 +65,15 @@ int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
|
|||
enum dma_slave_buswidth buswidth;
|
||||
int bits;
|
||||
|
||||
bits = snd_pcm_format_physical_width(params_format(params));
|
||||
bits = params_physical_width(params);
|
||||
if (bits < 8 || bits > 64)
|
||||
return -EINVAL;
|
||||
else if (bits == 8)
|
||||
buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
|
||||
else if (bits == 16)
|
||||
buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
|
||||
else if (bits == 24)
|
||||
buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES;
|
||||
else if (bits <= 32)
|
||||
buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
|
||||
else
|
||||
|
|
|
@ -47,6 +47,7 @@ source "sound/soc/kirkwood/Kconfig"
|
|||
source "sound/soc/intel/Kconfig"
|
||||
source "sound/soc/mxs/Kconfig"
|
||||
source "sound/soc/pxa/Kconfig"
|
||||
source "sound/soc/rockchip/Kconfig"
|
||||
source "sound/soc/samsung/Kconfig"
|
||||
source "sound/soc/s6000/Kconfig"
|
||||
source "sound/soc/sh/Kconfig"
|
||||
|
|
|
@ -24,6 +24,7 @@ obj-$(CONFIG_SND_SOC) += nuc900/
|
|||
obj-$(CONFIG_SND_SOC) += omap/
|
||||
obj-$(CONFIG_SND_SOC) += kirkwood/
|
||||
obj-$(CONFIG_SND_SOC) += pxa/
|
||||
obj-$(CONFIG_SND_SOC) += rockchip/
|
||||
obj-$(CONFIG_SND_SOC) += samsung/
|
||||
obj-$(CONFIG_SND_SOC) += s6000/
|
||||
obj-$(CONFIG_SND_SOC) += sh/
|
||||
|
|
|
@ -347,6 +347,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
u32 tfmr, rfmr, tcmr, rcmr;
|
||||
int start_event;
|
||||
int ret;
|
||||
int fslen, fslen_ext;
|
||||
|
||||
/*
|
||||
* Currently, there is only one set of dma params for
|
||||
|
@ -387,18 +388,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The SSC only supports up to 16-bit samples in I2S format, due
|
||||
* to the size of the Frame Mode Register FSLEN field.
|
||||
*/
|
||||
if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
|
||||
&& bits > 16) {
|
||||
printk(KERN_WARNING
|
||||
"atmel_ssc_dai: sample size %d "
|
||||
"is too large for I2S\n", bits);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute SSC register settings.
|
||||
*/
|
||||
|
@ -413,6 +402,17 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
* from the MCK divider, and the BCLK signal
|
||||
* is output on the SSC TK line.
|
||||
*/
|
||||
|
||||
if (bits > 16 && !ssc->pdata->has_fslen_ext) {
|
||||
dev_err(dai->dev,
|
||||
"sample size %d is too large for SSC device\n",
|
||||
bits);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fslen_ext = (bits - 1) / 16;
|
||||
fslen = (bits - 1) % 16;
|
||||
|
||||
rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
|
||||
| SSC_BF(RCMR_STTDLY, START_DELAY)
|
||||
| SSC_BF(RCMR_START, SSC_START_FALLING_RF)
|
||||
|
@ -420,9 +420,10 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
|
||||
| SSC_BF(RCMR_CKS, SSC_CKS_DIV);
|
||||
|
||||
rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
|
||||
rfmr = SSC_BF(RFMR_FSLEN_EXT, fslen_ext)
|
||||
| SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
|
||||
| SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE)
|
||||
| SSC_BF(RFMR_FSLEN, (bits - 1))
|
||||
| SSC_BF(RFMR_FSLEN, fslen)
|
||||
| SSC_BF(RFMR_DATNB, (channels - 1))
|
||||
| SSC_BIT(RFMR_MSBF)
|
||||
| SSC_BF(RFMR_LOOP, 0)
|
||||
|
@ -435,10 +436,11 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
| SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
|
||||
| SSC_BF(TCMR_CKS, SSC_CKS_DIV);
|
||||
|
||||
tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
|
||||
tfmr = SSC_BF(TFMR_FSLEN_EXT, fslen_ext)
|
||||
| SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
|
||||
| SSC_BF(TFMR_FSDEN, 0)
|
||||
| SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE)
|
||||
| SSC_BF(TFMR_FSLEN, (bits - 1))
|
||||
| SSC_BF(TFMR_FSLEN, fslen)
|
||||
| SSC_BF(TFMR_DATNB, (channels - 1))
|
||||
| SSC_BIT(TFMR_MSBF)
|
||||
| SSC_BF(TFMR_DATDEF, 0)
|
||||
|
|
|
@ -18,10 +18,6 @@
|
|||
#include "../codecs/wm8904.h"
|
||||
#include "atmel_ssc_dai.h"
|
||||
|
||||
#define MCLK_RATE 32768
|
||||
|
||||
static struct clk *mclk;
|
||||
|
||||
static const struct snd_soc_dapm_widget atmel_asoc_wm8904_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_HP("Headphone Jack", NULL),
|
||||
SND_SOC_DAPM_MIC("Mic", NULL),
|
||||
|
@ -61,26 +57,6 @@ static struct snd_soc_ops atmel_asoc_wm8904_ops = {
|
|||
.hw_params = atmel_asoc_wm8904_hw_params,
|
||||
};
|
||||
|
||||
static int atmel_set_bias_level(struct snd_soc_card *card,
|
||||
struct snd_soc_dapm_context *dapm,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
clk_prepare_enable(mclk);
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
clk_disable_unprepare(mclk);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = {
|
||||
.name = "WM8904",
|
||||
.stream_name = "WM8904 PCM",
|
||||
|
@ -94,7 +70,6 @@ static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = {
|
|||
static struct snd_soc_card atmel_asoc_wm8904_card = {
|
||||
.name = "atmel_asoc_wm8904",
|
||||
.owner = THIS_MODULE,
|
||||
.set_bias_level = atmel_set_bias_level,
|
||||
.dai_link = &atmel_asoc_wm8904_dailink,
|
||||
.num_links = 1,
|
||||
.dapm_widgets = atmel_asoc_wm8904_dapm_widgets,
|
||||
|
@ -153,7 +128,6 @@ static int atmel_asoc_wm8904_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct snd_soc_card *card = &atmel_asoc_wm8904_card;
|
||||
struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink;
|
||||
struct clk *clk_src;
|
||||
int id, ret;
|
||||
|
||||
card->dev = &pdev->dev;
|
||||
|
@ -170,30 +144,6 @@ static int atmel_asoc_wm8904_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
mclk = clk_get(NULL, "pck0");
|
||||
if (IS_ERR(mclk)) {
|
||||
dev_err(&pdev->dev, "failed to get pck0\n");
|
||||
ret = PTR_ERR(mclk);
|
||||
goto err_set_audio;
|
||||
}
|
||||
|
||||
clk_src = clk_get(NULL, "clk32k");
|
||||
if (IS_ERR(clk_src)) {
|
||||
dev_err(&pdev->dev, "failed to get clk32k\n");
|
||||
ret = PTR_ERR(clk_src);
|
||||
goto err_set_audio;
|
||||
}
|
||||
|
||||
ret = clk_set_parent(mclk, clk_src);
|
||||
clk_put(clk_src);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "failed to set MCLK parent\n");
|
||||
goto err_set_audio;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "setting pck0 to %dHz\n", MCLK_RATE);
|
||||
clk_set_rate(mclk, MCLK_RATE);
|
||||
|
||||
ret = snd_soc_register_card(card);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "snd_soc_register_card failed\n");
|
||||
|
|
|
@ -945,11 +945,11 @@ static int pm860x_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
unsigned char inf = 0, mask = 0;
|
||||
|
||||
/* bit size */
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
inf &= ~PCM_INF2_18WL;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S18_3LE:
|
||||
case 18:
|
||||
inf |= PCM_INF2_18WL;
|
||||
break;
|
||||
default:
|
||||
|
@ -1044,11 +1044,11 @@ static int pm860x_i2s_hw_params(struct snd_pcm_substream *substream,
|
|||
unsigned char inf;
|
||||
|
||||
/* bit size */
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
inf = 0;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S18_3LE:
|
||||
case 18:
|
||||
inf = PCM_INF2_18WL;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -47,6 +47,7 @@ config SND_SOC_ALL_CODECS
|
|||
select SND_SOC_CS42L52 if I2C && INPUT
|
||||
select SND_SOC_CS42L56 if I2C && INPUT
|
||||
select SND_SOC_CS42L73 if I2C
|
||||
select SND_SOC_CS4265 if I2C
|
||||
select SND_SOC_CS4270 if I2C
|
||||
select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
|
||||
select SND_SOC_CS42XX8_I2C if I2C
|
||||
|
@ -74,10 +75,12 @@ config SND_SOC_ALL_CODECS
|
|||
select SND_SOC_PCM3008
|
||||
select SND_SOC_PCM512x_I2C if I2C
|
||||
select SND_SOC_PCM512x_SPI if SPI_MASTER
|
||||
select SND_SOC_RT286 if I2C
|
||||
select SND_SOC_RT5631 if I2C
|
||||
select SND_SOC_RT5640 if I2C
|
||||
select SND_SOC_RT5645 if I2C
|
||||
select SND_SOC_RT5651 if I2C
|
||||
select SND_SOC_RT5670 if I2C
|
||||
select SND_SOC_RT5677 if I2C
|
||||
select SND_SOC_SGTL5000 if I2C
|
||||
select SND_SOC_SI476X if MFD_SI476X_CORE
|
||||
|
@ -91,6 +94,7 @@ config SND_SOC_ALL_CODECS
|
|||
select SND_SOC_STA350 if I2C
|
||||
select SND_SOC_STA529 if I2C
|
||||
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
|
||||
select SND_SOC_TAS2552 if I2C
|
||||
select SND_SOC_TAS5086 if I2C
|
||||
select SND_SOC_TLV320AIC23_I2C if I2C
|
||||
select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
|
||||
|
@ -338,6 +342,11 @@ config SND_SOC_CS42L73
|
|||
tristate "Cirrus Logic CS42L73 CODEC"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_CS4265
|
||||
tristate "Cirrus Logic CS4265 CODEC"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
|
||||
# Cirrus Logic CS4270 Codec
|
||||
config SND_SOC_CS4270
|
||||
tristate "Cirrus Logic CS4270 CODEC"
|
||||
|
@ -445,9 +454,16 @@ config SND_SOC_RL6231
|
|||
default y if SND_SOC_RT5640=y
|
||||
default y if SND_SOC_RT5645=y
|
||||
default y if SND_SOC_RT5651=y
|
||||
default y if SND_SOC_RT5670=y
|
||||
default y if SND_SOC_RT5677=y
|
||||
default m if SND_SOC_RT5640=m
|
||||
default m if SND_SOC_RT5645=m
|
||||
default m if SND_SOC_RT5651=m
|
||||
default m if SND_SOC_RT5670=m
|
||||
default m if SND_SOC_RT5677=m
|
||||
|
||||
config SND_SOC_RT286
|
||||
tristate
|
||||
|
||||
config SND_SOC_RT5631
|
||||
tristate
|
||||
|
@ -461,6 +477,9 @@ config SND_SOC_RT5645
|
|||
config SND_SOC_RT5651
|
||||
tristate
|
||||
|
||||
config SND_SOC_RT5670
|
||||
tristate
|
||||
|
||||
config SND_SOC_RT5677
|
||||
tristate
|
||||
|
||||
|
@ -521,6 +540,10 @@ config SND_SOC_STA529
|
|||
config SND_SOC_STAC9766
|
||||
tristate
|
||||
|
||||
config SND_SOC_TAS2552
|
||||
tristate "Texas Instruments TAS2552 Mono Audio amplifier"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_TAS5086
|
||||
tristate "Texas Instruments TAS5086 speaker amplifier"
|
||||
depends on I2C
|
||||
|
@ -541,7 +564,9 @@ config SND_SOC_TLV320AIC26
|
|||
depends on SPI
|
||||
|
||||
config SND_SOC_TLV320AIC31XX
|
||||
tristate
|
||||
tristate "Texas Instruments TLV320AIC31xx CODECs"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
|
||||
config SND_SOC_TLV320AIC32X4
|
||||
tristate
|
||||
|
|
|
@ -37,6 +37,7 @@ snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o
|
|||
snd-soc-cs42l52-objs := cs42l52.o
|
||||
snd-soc-cs42l56-objs := cs42l56.o
|
||||
snd-soc-cs42l73-objs := cs42l73.o
|
||||
snd-soc-cs4265-objs := cs4265.o
|
||||
snd-soc-cs4270-objs := cs4270.o
|
||||
snd-soc-cs4271-objs := cs4271.o
|
||||
snd-soc-cs42xx8-objs := cs42xx8.o
|
||||
|
@ -68,10 +69,12 @@ snd-soc-pcm512x-objs := pcm512x.o
|
|||
snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
|
||||
snd-soc-pcm512x-spi-objs := pcm512x-spi.o
|
||||
snd-soc-rl6231-objs := rl6231.o
|
||||
snd-soc-rt286-objs := rt286.o
|
||||
snd-soc-rt5631-objs := rt5631.o
|
||||
snd-soc-rt5640-objs := rt5640.o
|
||||
snd-soc-rt5645-objs := rt5645.o
|
||||
snd-soc-rt5651-objs := rt5651.o
|
||||
snd-soc-rt5670-objs := rt5670.o
|
||||
snd-soc-rt5677-objs := rt5677.o
|
||||
snd-soc-sgtl5000-objs := sgtl5000.o
|
||||
snd-soc-alc5623-objs := alc5623.o
|
||||
|
@ -162,6 +165,7 @@ snd-soc-wm-hubs-objs := wm_hubs.o
|
|||
# Amp
|
||||
snd-soc-max9877-objs := max9877.o
|
||||
snd-soc-tpa6130a2-objs := tpa6130a2.o
|
||||
snd-soc-tas2552-objs := tas2552.o
|
||||
|
||||
obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o
|
||||
obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o
|
||||
|
@ -204,6 +208,7 @@ obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o
|
|||
obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o
|
||||
obj-$(CONFIG_SND_SOC_CS42L56) += snd-soc-cs42l56.o
|
||||
obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o
|
||||
obj-$(CONFIG_SND_SOC_CS4265) += snd-soc-cs4265.o
|
||||
obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
|
||||
obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o
|
||||
obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o
|
||||
|
@ -235,10 +240,12 @@ obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o
|
|||
obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o
|
||||
obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o
|
||||
obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o
|
||||
obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o
|
||||
obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
|
||||
obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o
|
||||
obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o
|
||||
obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o
|
||||
obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o
|
||||
obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o
|
||||
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
|
||||
obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
|
||||
|
@ -255,6 +262,7 @@ 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
|
||||
obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
|
||||
obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o
|
||||
obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o
|
||||
|
|
|
@ -89,8 +89,8 @@ static int ac97_soc_probe(struct snd_soc_codec *codec)
|
|||
int ret;
|
||||
|
||||
/* add codec as bus device for standard ac97 */
|
||||
ret = snd_ac97_bus(codec->card->snd_card, 0, soc_ac97_ops, NULL,
|
||||
&ac97_bus);
|
||||
ret = snd_ac97_bus(codec->component.card->snd_card, 0, soc_ac97_ops,
|
||||
NULL, &ac97_bus);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -359,14 +359,14 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream,
|
|||
if (adau->dai_fmt != SND_SOC_DAIFMT_RIGHT_J)
|
||||
return 0;
|
||||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
val = ADAU17X1_SERIAL_PORT1_DELAY16;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
case 24:
|
||||
val = ADAU17X1_SERIAL_PORT1_DELAY8;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
case 32:
|
||||
val = ADAU17X1_SERIAL_PORT1_DELAY0;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -968,7 +968,7 @@ int adau1977_probe(struct device *dev, struct regmap *regmap,
|
|||
if (adau1977->dvdd_reg)
|
||||
power_off_mask = ~0;
|
||||
else
|
||||
power_off_mask = ~ADAU1977_BLOCK_POWER_SAI_LDO_EN;
|
||||
power_off_mask = (unsigned int)~ADAU1977_BLOCK_POWER_SAI_LDO_EN;
|
||||
|
||||
ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI,
|
||||
power_off_mask, 0x00);
|
||||
|
|
|
@ -547,7 +547,7 @@ static const struct ak4642_drvdata ak4648_drvdata = {
|
|||
.extended_frequencies = 1,
|
||||
};
|
||||
|
||||
static struct of_device_id ak4642_of_match[];
|
||||
static const struct of_device_id ak4642_of_match[];
|
||||
static int ak4642_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
|
@ -593,7 +593,7 @@ static int ak4642_i2c_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id ak4642_of_match[] = {
|
||||
static const struct of_device_id ak4642_of_match[] = {
|
||||
{ .compatible = "asahi-kasei,ak4642", .data = &ak4642_drvdata},
|
||||
{ .compatible = "asahi-kasei,ak4643", .data = &ak4643_drvdata},
|
||||
{ .compatible = "asahi-kasei,ak4648", .data = &ak4648_drvdata},
|
||||
|
|
|
@ -14,12 +14,18 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
static const char * const supply_names[] = {
|
||||
"va", "vd"
|
||||
};
|
||||
|
||||
struct ak5386_priv {
|
||||
int reset_gpio;
|
||||
struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget ak5386_dapm_widgets[] = {
|
||||
|
@ -32,7 +38,42 @@ static const struct snd_soc_dapm_route ak5386_dapm_routes[] = {
|
|||
{ "Capture", NULL, "AINR" },
|
||||
};
|
||||
|
||||
static int ak5386_soc_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
|
||||
}
|
||||
|
||||
static int ak5386_soc_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int ak5386_soc_suspend(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ak5386_soc_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
|
||||
}
|
||||
#else
|
||||
#define ak5386_soc_suspend NULL
|
||||
#define ak5386_soc_resume NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_ak5386 = {
|
||||
.probe = ak5386_soc_probe,
|
||||
.remove = ak5386_soc_remove,
|
||||
.suspend = ak5386_soc_suspend,
|
||||
.resume = ak5386_soc_resume,
|
||||
.dapm_widgets = ak5386_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets),
|
||||
.dapm_routes = ak5386_dapm_routes,
|
||||
|
@ -122,6 +163,7 @@ static int ak5386_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct ak5386_priv *priv;
|
||||
int ret, i;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
|
@ -130,6 +172,14 @@ static int ak5386_probe(struct platform_device *pdev)
|
|||
priv->reset_gpio = -EINVAL;
|
||||
dev_set_drvdata(dev, priv);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(supply_names); i++)
|
||||
priv->supplies[i].supply = supply_names[i];
|
||||
|
||||
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(priv->supplies),
|
||||
priv->supplies);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (of_match_device(of_match_ptr(ak5386_dt_ids), dev))
|
||||
priv->reset_gpio = of_get_named_gpio(dev->of_node,
|
||||
"reset-gpio", 0);
|
||||
|
|
|
@ -1152,6 +1152,31 @@ static int arizona_startup(struct snd_pcm_substream *substream,
|
|||
constraint);
|
||||
}
|
||||
|
||||
static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec,
|
||||
unsigned int rate)
|
||||
{
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona *arizona = priv->arizona;
|
||||
struct reg_default dac_comp[] = {
|
||||
{ 0x80, 0x3 },
|
||||
{ ARIZONA_DAC_COMP_1, 0 },
|
||||
{ ARIZONA_DAC_COMP_2, 0 },
|
||||
{ 0x80, 0x0 },
|
||||
};
|
||||
|
||||
mutex_lock(&codec->mutex);
|
||||
|
||||
dac_comp[1].def = arizona->dac_comp_coeff;
|
||||
if (rate >= 176400)
|
||||
dac_comp[2].def = arizona->dac_comp_enabled;
|
||||
|
||||
mutex_unlock(&codec->mutex);
|
||||
|
||||
regmap_multi_reg_write(arizona->regmap,
|
||||
dac_comp,
|
||||
ARRAY_SIZE(dac_comp));
|
||||
}
|
||||
|
||||
static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
|
@ -1178,6 +1203,15 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
|
|||
|
||||
switch (dai_priv->clk) {
|
||||
case ARIZONA_CLK_SYSCLK:
|
||||
switch (priv->arizona->type) {
|
||||
case WM5102:
|
||||
arizona_wm5102_set_dac_comp(codec,
|
||||
params_rate(params));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
|
||||
ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
|
||||
if (base)
|
||||
|
@ -1200,6 +1234,27 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool arizona_aif_cfg_changed(struct snd_soc_codec *codec,
|
||||
int base, int bclk, int lrclk, int frame)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = snd_soc_read(codec, base + ARIZONA_AIF_BCLK_CTRL);
|
||||
if (bclk != (val & ARIZONA_AIF1_BCLK_FREQ_MASK))
|
||||
return true;
|
||||
|
||||
val = snd_soc_read(codec, base + ARIZONA_AIF_TX_BCLK_RATE);
|
||||
if (lrclk != (val & ARIZONA_AIF1TX_BCPF_MASK))
|
||||
return true;
|
||||
|
||||
val = snd_soc_read(codec, base + ARIZONA_AIF_FRAME_CTRL_1);
|
||||
if (frame != (val & (ARIZONA_AIF1TX_WL_MASK |
|
||||
ARIZONA_AIF1TX_SLOT_LEN_MASK)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int arizona_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
|
@ -1210,26 +1265,40 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
|
|||
int base = dai->driver->base;
|
||||
const int *rates;
|
||||
int i, ret, val;
|
||||
int channels = params_channels(params);
|
||||
int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
|
||||
int tdm_width = arizona->tdm_width[dai->id - 1];
|
||||
int tdm_slots = arizona->tdm_slots[dai->id - 1];
|
||||
int bclk, lrclk, wl, frame, bclk_target;
|
||||
bool reconfig;
|
||||
unsigned int aif_tx_state, aif_rx_state;
|
||||
|
||||
if (params_rate(params) % 8000)
|
||||
rates = &arizona_44k1_bclk_rates[0];
|
||||
else
|
||||
rates = &arizona_48k_bclk_rates[0];
|
||||
|
||||
bclk_target = snd_soc_params_to_bclk(params);
|
||||
if (chan_limit && chan_limit < params_channels(params)) {
|
||||
if (tdm_slots) {
|
||||
arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n",
|
||||
tdm_slots, tdm_width);
|
||||
bclk_target = tdm_slots * tdm_width * params_rate(params);
|
||||
channels = tdm_slots;
|
||||
} else {
|
||||
bclk_target = snd_soc_params_to_bclk(params);
|
||||
}
|
||||
|
||||
if (chan_limit && chan_limit < channels) {
|
||||
arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
|
||||
bclk_target /= params_channels(params);
|
||||
bclk_target /= channels;
|
||||
bclk_target *= chan_limit;
|
||||
}
|
||||
|
||||
/* Force stereo for I2S mode */
|
||||
/* Force multiple of 2 channels for I2S mode */
|
||||
val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT);
|
||||
if (params_channels(params) == 1 && (val & ARIZONA_AIF1_FMT_MASK)) {
|
||||
if ((channels & 1) && (val & ARIZONA_AIF1_FMT_MASK)) {
|
||||
arizona_aif_dbg(dai, "Forcing stereo mode\n");
|
||||
bclk_target *= 2;
|
||||
bclk_target /= channels;
|
||||
bclk_target *= channels + 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
|
||||
|
@ -1253,28 +1322,56 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
|
|||
wl = snd_pcm_format_width(params_format(params));
|
||||
frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
|
||||
|
||||
reconfig = arizona_aif_cfg_changed(codec, base, bclk, lrclk, frame);
|
||||
|
||||
if (reconfig) {
|
||||
/* Save AIF TX/RX state */
|
||||
aif_tx_state = snd_soc_read(codec,
|
||||
base + ARIZONA_AIF_TX_ENABLES);
|
||||
aif_rx_state = snd_soc_read(codec,
|
||||
base + ARIZONA_AIF_RX_ENABLES);
|
||||
/* Disable AIF TX/RX before reconfiguring it */
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_TX_ENABLES, 0xff, 0x0);
|
||||
regmap_update_bits(arizona->regmap,
|
||||
base + ARIZONA_AIF_RX_ENABLES, 0xff, 0x0);
|
||||
}
|
||||
|
||||
ret = arizona_hw_params_rate(substream, params, dai);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
goto restore_aif;
|
||||
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_BCLK_CTRL,
|
||||
ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_TX_BCLK_RATE,
|
||||
ARIZONA_AIF1TX_BCPF_MASK, lrclk);
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_RX_BCLK_RATE,
|
||||
ARIZONA_AIF1RX_BCPF_MASK, lrclk);
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_FRAME_CTRL_1,
|
||||
ARIZONA_AIF1TX_WL_MASK |
|
||||
ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
|
||||
regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FRAME_CTRL_2,
|
||||
ARIZONA_AIF1RX_WL_MASK |
|
||||
ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
|
||||
if (reconfig) {
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_BCLK_CTRL,
|
||||
ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_TX_BCLK_RATE,
|
||||
ARIZONA_AIF1TX_BCPF_MASK, lrclk);
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_RX_BCLK_RATE,
|
||||
ARIZONA_AIF1RX_BCPF_MASK, lrclk);
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_FRAME_CTRL_1,
|
||||
ARIZONA_AIF1TX_WL_MASK |
|
||||
ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
|
||||
regmap_update_bits(arizona->regmap,
|
||||
base + ARIZONA_AIF_FRAME_CTRL_2,
|
||||
ARIZONA_AIF1RX_WL_MASK |
|
||||
ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
|
||||
}
|
||||
|
||||
return 0;
|
||||
restore_aif:
|
||||
if (reconfig) {
|
||||
/* Restore AIF TX/RX state */
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_TX_ENABLES,
|
||||
0xff, aif_tx_state);
|
||||
regmap_update_bits(arizona->regmap,
|
||||
base + ARIZONA_AIF_RX_ENABLES,
|
||||
0xff, aif_rx_state);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char *arizona_dai_clk_str(int clk_id)
|
||||
|
@ -1349,9 +1446,63 @@ static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate)
|
|||
ARIZONA_AIF1_TRI, reg);
|
||||
}
|
||||
|
||||
static void arizona_set_channels_to_mask(struct snd_soc_dai *dai,
|
||||
unsigned int base,
|
||||
int channels, unsigned int mask)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona *arizona = priv->arizona;
|
||||
int slot, i;
|
||||
|
||||
for (i = 0; i < channels; ++i) {
|
||||
slot = ffs(mask) - 1;
|
||||
if (slot < 0)
|
||||
return;
|
||||
|
||||
regmap_write(arizona->regmap, base + i, slot);
|
||||
|
||||
mask &= ~(1 << slot);
|
||||
}
|
||||
|
||||
if (mask)
|
||||
arizona_aif_warn(dai, "Too many channels in TDM mask\n");
|
||||
}
|
||||
|
||||
static int arizona_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
|
||||
unsigned int rx_mask, int slots, int slot_width)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona *arizona = priv->arizona;
|
||||
int base = dai->driver->base;
|
||||
int rx_max_chan = dai->driver->playback.channels_max;
|
||||
int tx_max_chan = dai->driver->capture.channels_max;
|
||||
|
||||
/* Only support TDM for the physical AIFs */
|
||||
if (dai->id > ARIZONA_MAX_AIF)
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (slots == 0) {
|
||||
tx_mask = (1 << tx_max_chan) - 1;
|
||||
rx_mask = (1 << rx_max_chan) - 1;
|
||||
}
|
||||
|
||||
arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_3,
|
||||
tx_max_chan, tx_mask);
|
||||
arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_11,
|
||||
rx_max_chan, rx_mask);
|
||||
|
||||
arizona->tdm_width[dai->id - 1] = slot_width;
|
||||
arizona->tdm_slots[dai->id - 1] = slots;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct snd_soc_dai_ops arizona_dai_ops = {
|
||||
.startup = arizona_startup,
|
||||
.set_fmt = arizona_set_fmt,
|
||||
.set_tdm_slot = arizona_set_tdm_slot,
|
||||
.hw_params = arizona_hw_params,
|
||||
.set_sysclk = arizona_dai_set_sysclk,
|
||||
.set_tristate = arizona_set_tristate,
|
||||
|
@ -1425,6 +1576,12 @@ static int arizona_validate_fll(struct arizona_fll *fll,
|
|||
{
|
||||
unsigned int Fvco_min;
|
||||
|
||||
if (fll->fout && Fout != fll->fout) {
|
||||
arizona_fll_err(fll,
|
||||
"Can't change output on active FLL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) {
|
||||
arizona_fll_err(fll,
|
||||
"Can't scale %dMHz in to <=13.5MHz\n",
|
||||
|
@ -1503,6 +1660,10 @@ static int arizona_calc_fratio(struct arizona_fll *fll,
|
|||
while (div <= ARIZONA_FLL_MAX_REFDIV) {
|
||||
for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO;
|
||||
ratio++) {
|
||||
if ((ARIZONA_FLL_VCO_CORNER / 2) /
|
||||
(fll->vco_mult * ratio) < Fref)
|
||||
break;
|
||||
|
||||
if (target % (ratio * Fref)) {
|
||||
cfg->refdiv = refdiv;
|
||||
cfg->fratio = ratio - 1;
|
||||
|
@ -1510,11 +1671,7 @@ static int arizona_calc_fratio(struct arizona_fll *fll,
|
|||
}
|
||||
}
|
||||
|
||||
for (ratio = init_ratio - 1; ratio >= 0; ratio--) {
|
||||
if (ARIZONA_FLL_VCO_CORNER / (fll->vco_mult * ratio) <
|
||||
Fref)
|
||||
break;
|
||||
|
||||
for (ratio = init_ratio - 1; ratio > 0; ratio--) {
|
||||
if (target % (ratio * Fref)) {
|
||||
cfg->refdiv = refdiv;
|
||||
cfg->fratio = ratio - 1;
|
||||
|
@ -1641,7 +1798,7 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
|
|||
ARIZONA_FLL1_CTRL_UPD | cfg->n);
|
||||
}
|
||||
|
||||
static bool arizona_is_enabled_fll(struct arizona_fll *fll)
|
||||
static int arizona_is_enabled_fll(struct arizona_fll *fll)
|
||||
{
|
||||
struct arizona *arizona = fll->arizona;
|
||||
unsigned int reg;
|
||||
|
@ -1657,13 +1814,26 @@ static bool arizona_is_enabled_fll(struct arizona_fll *fll)
|
|||
return reg & ARIZONA_FLL1_ENA;
|
||||
}
|
||||
|
||||
static void arizona_enable_fll(struct arizona_fll *fll)
|
||||
static int arizona_enable_fll(struct arizona_fll *fll)
|
||||
{
|
||||
struct arizona *arizona = fll->arizona;
|
||||
int ret;
|
||||
bool use_sync = false;
|
||||
int already_enabled = arizona_is_enabled_fll(fll);
|
||||
struct arizona_fll_cfg cfg;
|
||||
|
||||
if (already_enabled < 0)
|
||||
return already_enabled;
|
||||
|
||||
if (already_enabled) {
|
||||
/* Facilitate smooth refclk across the transition */
|
||||
regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x7,
|
||||
ARIZONA_FLL1_GAIN_MASK, 0);
|
||||
regmap_update_bits_async(fll->arizona->regmap, fll->base + 1,
|
||||
ARIZONA_FLL1_FREERUN,
|
||||
ARIZONA_FLL1_FREERUN);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have both REFCLK and SYNCCLK then enable both,
|
||||
* otherwise apply the SYNCCLK settings to REFCLK.
|
||||
|
@ -1691,7 +1861,7 @@ static void arizona_enable_fll(struct arizona_fll *fll)
|
|||
ARIZONA_FLL1_SYNC_ENA, 0);
|
||||
} else {
|
||||
arizona_fll_err(fll, "No clocks provided\n");
|
||||
return;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1706,14 +1876,12 @@ static void arizona_enable_fll(struct arizona_fll *fll)
|
|||
ARIZONA_FLL1_SYNC_BW,
|
||||
ARIZONA_FLL1_SYNC_BW);
|
||||
|
||||
if (!arizona_is_enabled_fll(fll))
|
||||
if (!already_enabled)
|
||||
pm_runtime_get(arizona->dev);
|
||||
|
||||
/* Clear any pending completions */
|
||||
try_wait_for_completion(&fll->ok);
|
||||
|
||||
regmap_update_bits_async(arizona->regmap, fll->base + 1,
|
||||
ARIZONA_FLL1_FREERUN, 0);
|
||||
regmap_update_bits_async(arizona->regmap, fll->base + 1,
|
||||
ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
|
||||
if (use_sync)
|
||||
|
@ -1721,10 +1889,16 @@ static void arizona_enable_fll(struct arizona_fll *fll)
|
|||
ARIZONA_FLL1_SYNC_ENA,
|
||||
ARIZONA_FLL1_SYNC_ENA);
|
||||
|
||||
if (already_enabled)
|
||||
regmap_update_bits_async(arizona->regmap, fll->base + 1,
|
||||
ARIZONA_FLL1_FREERUN, 0);
|
||||
|
||||
ret = wait_for_completion_timeout(&fll->ok,
|
||||
msecs_to_jiffies(250));
|
||||
if (ret == 0)
|
||||
arizona_fll_warn(fll, "Timed out waiting for lock\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void arizona_disable_fll(struct arizona_fll *fll)
|
||||
|
@ -1738,6 +1912,8 @@ static void arizona_disable_fll(struct arizona_fll *fll)
|
|||
ARIZONA_FLL1_ENA, 0, &change);
|
||||
regmap_update_bits(arizona->regmap, fll->base + 0x11,
|
||||
ARIZONA_FLL1_SYNC_ENA, 0);
|
||||
regmap_update_bits_async(arizona->regmap, fll->base + 1,
|
||||
ARIZONA_FLL1_FREERUN, 0);
|
||||
|
||||
if (change)
|
||||
pm_runtime_put_autosuspend(arizona->dev);
|
||||
|
@ -1746,7 +1922,7 @@ static void arizona_disable_fll(struct arizona_fll *fll)
|
|||
int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
|
||||
unsigned int Fref, unsigned int Fout)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (fll->ref_src == source && fll->ref_freq == Fref)
|
||||
return 0;
|
||||
|
@ -1761,17 +1937,17 @@ int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
|
|||
fll->ref_freq = Fref;
|
||||
|
||||
if (fll->fout && Fref > 0) {
|
||||
arizona_enable_fll(fll);
|
||||
ret = arizona_enable_fll(fll);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
|
||||
|
||||
int arizona_set_fll(struct arizona_fll *fll, int source,
|
||||
unsigned int Fref, unsigned int Fout)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (fll->sync_src == source &&
|
||||
fll->sync_freq == Fref && fll->fout == Fout)
|
||||
|
@ -1793,13 +1969,12 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
|
|||
fll->sync_freq = Fref;
|
||||
fll->fout = Fout;
|
||||
|
||||
if (Fout) {
|
||||
arizona_enable_fll(fll);
|
||||
} else {
|
||||
if (Fout)
|
||||
ret = arizona_enable_fll(fll);
|
||||
else
|
||||
arizona_disable_fll(fll);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arizona_set_fll);
|
||||
|
||||
|
|
|
@ -0,0 +1,682 @@
|
|||
/*
|
||||
* cs4265.c -- CS4265 ALSA SoC audio driver
|
||||
*
|
||||
* Copyright 2014 Cirrus Logic, Inc.
|
||||
*
|
||||
* Author: Paul Handrigan <paul.handrigan@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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
#include "cs4265.h"
|
||||
|
||||
struct cs4265_private {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct gpio_desc *reset_gpio;
|
||||
u8 format;
|
||||
u32 sysclk;
|
||||
};
|
||||
|
||||
static const struct reg_default cs4265_reg_defaults[] = {
|
||||
{ CS4265_PWRCTL, 0x0F },
|
||||
{ CS4265_DAC_CTL, 0x08 },
|
||||
{ CS4265_ADC_CTL, 0x00 },
|
||||
{ CS4265_MCLK_FREQ, 0x00 },
|
||||
{ CS4265_SIG_SEL, 0x40 },
|
||||
{ CS4265_CHB_PGA_CTL, 0x00 },
|
||||
{ CS4265_CHA_PGA_CTL, 0x00 },
|
||||
{ CS4265_ADC_CTL2, 0x19 },
|
||||
{ CS4265_DAC_CHA_VOL, 0x00 },
|
||||
{ CS4265_DAC_CHB_VOL, 0x00 },
|
||||
{ CS4265_DAC_CTL2, 0xC0 },
|
||||
{ CS4265_SPDIF_CTL1, 0x00 },
|
||||
{ CS4265_SPDIF_CTL2, 0x00 },
|
||||
{ CS4265_INT_MASK, 0x00 },
|
||||
{ CS4265_STATUS_MODE_MSB, 0x00 },
|
||||
{ CS4265_STATUS_MODE_LSB, 0x00 },
|
||||
};
|
||||
|
||||
static bool cs4265_readable_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case CS4265_PWRCTL:
|
||||
case CS4265_DAC_CTL:
|
||||
case CS4265_ADC_CTL:
|
||||
case CS4265_MCLK_FREQ:
|
||||
case CS4265_SIG_SEL:
|
||||
case CS4265_CHB_PGA_CTL:
|
||||
case CS4265_CHA_PGA_CTL:
|
||||
case CS4265_ADC_CTL2:
|
||||
case CS4265_DAC_CHA_VOL:
|
||||
case CS4265_DAC_CHB_VOL:
|
||||
case CS4265_DAC_CTL2:
|
||||
case CS4265_SPDIF_CTL1:
|
||||
case CS4265_SPDIF_CTL2:
|
||||
case CS4265_INT_MASK:
|
||||
case CS4265_STATUS_MODE_MSB:
|
||||
case CS4265_STATUS_MODE_LSB:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool cs4265_volatile_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case CS4265_INT_STATUS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLARE_TLV_DB_SCALE(pga_tlv, -1200, 50, 0);
|
||||
|
||||
static DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 0);
|
||||
|
||||
static const char * const digital_input_mux_text[] = {
|
||||
"SDIN1", "SDIN2"
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(digital_input_mux_enum, CS4265_SIG_SEL, 7,
|
||||
digital_input_mux_text);
|
||||
|
||||
static const struct snd_kcontrol_new digital_input_mux =
|
||||
SOC_DAPM_ENUM("Digital Input Mux", digital_input_mux_enum);
|
||||
|
||||
static const char * const mic_linein_text[] = {
|
||||
"MIC", "LINEIN"
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(mic_linein_enum, CS4265_ADC_CTL2, 0,
|
||||
mic_linein_text);
|
||||
|
||||
static const char * const cam_mode_text[] = {
|
||||
"One Byte", "Two Byte"
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(cam_mode_enum, CS4265_SPDIF_CTL1, 5,
|
||||
cam_mode_text);
|
||||
|
||||
static const char * const cam_mono_stereo_text[] = {
|
||||
"Stereo", "Mono"
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(spdif_mono_stereo_enum, CS4265_SPDIF_CTL2, 2,
|
||||
cam_mono_stereo_text);
|
||||
|
||||
static const char * const mono_select_text[] = {
|
||||
"Channel A", "Channel B"
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(spdif_mono_select_enum, CS4265_SPDIF_CTL2, 0,
|
||||
mono_select_text);
|
||||
|
||||
static const struct snd_kcontrol_new mic_linein_mux =
|
||||
SOC_DAPM_ENUM("ADC Input Capture Mux", mic_linein_enum);
|
||||
|
||||
static const struct snd_kcontrol_new loopback_ctl =
|
||||
SOC_DAPM_SINGLE("Switch", CS4265_SIG_SEL, 1, 1, 0);
|
||||
|
||||
static const struct snd_kcontrol_new spdif_switch =
|
||||
SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 0, 0);
|
||||
|
||||
static const struct snd_kcontrol_new dac_switch =
|
||||
SOC_DAPM_SINGLE("Switch", CS4265_PWRCTL, 1, 1, 0);
|
||||
|
||||
static const struct snd_kcontrol_new cs4265_snd_controls[] = {
|
||||
|
||||
SOC_DOUBLE_R_SX_TLV("PGA Volume", CS4265_CHA_PGA_CTL,
|
||||
CS4265_CHB_PGA_CTL, 0, 0x28, 0x30, pga_tlv),
|
||||
SOC_DOUBLE_R_TLV("DAC Volume", CS4265_DAC_CHA_VOL,
|
||||
CS4265_DAC_CHB_VOL, 0, 0xFF, 1, dac_tlv),
|
||||
SOC_SINGLE("De-emp 44.1kHz Switch", CS4265_DAC_CTL, 1,
|
||||
1, 0),
|
||||
SOC_SINGLE("DAC INV Switch", CS4265_DAC_CTL2, 5,
|
||||
1, 0),
|
||||
SOC_SINGLE("DAC Zero Cross Switch", CS4265_DAC_CTL2, 6,
|
||||
1, 0),
|
||||
SOC_SINGLE("DAC Soft Ramp Switch", CS4265_DAC_CTL2, 7,
|
||||
1, 0),
|
||||
SOC_SINGLE("ADC HPF Switch", CS4265_ADC_CTL, 1,
|
||||
1, 0),
|
||||
SOC_SINGLE("ADC Zero Cross Switch", CS4265_ADC_CTL2, 3,
|
||||
1, 1),
|
||||
SOC_SINGLE("ADC Soft Ramp Switch", CS4265_ADC_CTL2, 7,
|
||||
1, 0),
|
||||
SOC_SINGLE("E to F Buffer Disable Switch", CS4265_SPDIF_CTL1,
|
||||
6, 1, 0),
|
||||
SOC_ENUM("C Data Access", cam_mode_enum),
|
||||
SOC_SINGLE("Validity Bit Control Switch", CS4265_SPDIF_CTL2,
|
||||
3, 1, 0),
|
||||
SOC_ENUM("SPDIF Mono/Stereo", spdif_mono_stereo_enum),
|
||||
SOC_SINGLE("MMTLR Data Switch", 0,
|
||||
1, 1, 0),
|
||||
SOC_ENUM("Mono Channel Select", spdif_mono_select_enum),
|
||||
SND_SOC_BYTES("C Data Buffer", CS4265_C_DATA_BUFF, 24),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget cs4265_dapm_widgets[] = {
|
||||
|
||||
SND_SOC_DAPM_INPUT("LINEINL"),
|
||||
SND_SOC_DAPM_INPUT("LINEINR"),
|
||||
SND_SOC_DAPM_INPUT("MICL"),
|
||||
SND_SOC_DAPM_INPUT("MICR"),
|
||||
|
||||
SND_SOC_DAPM_AIF_OUT("DOUT", NULL, 0,
|
||||
SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_AIF_OUT("SPDIFOUT", NULL, 0,
|
||||
SND_SOC_NOPM, 0, 0),
|
||||
|
||||
SND_SOC_DAPM_MUX("ADC Mux", SND_SOC_NOPM, 0, 0, &mic_linein_mux),
|
||||
|
||||
SND_SOC_DAPM_ADC("ADC", NULL, CS4265_PWRCTL, 2, 1),
|
||||
SND_SOC_DAPM_PGA("Pre-amp MIC", CS4265_PWRCTL, 3,
|
||||
1, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM,
|
||||
0, 0, &digital_input_mux),
|
||||
|
||||
SND_SOC_DAPM_MIXER("SDIN1 Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
SND_SOC_DAPM_MIXER("SDIN2 Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
SND_SOC_DAPM_MIXER("SPDIF Transmitter", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_SWITCH("Loopback", SND_SOC_NOPM, 0, 0,
|
||||
&loopback_ctl),
|
||||
SND_SOC_DAPM_SWITCH("SPDIF", SND_SOC_NOPM, 0, 0,
|
||||
&spdif_switch),
|
||||
SND_SOC_DAPM_SWITCH("DAC", CS4265_PWRCTL, 1, 1,
|
||||
&dac_switch),
|
||||
|
||||
SND_SOC_DAPM_AIF_IN("DIN1", NULL, 0,
|
||||
SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_AIF_IN("DIN2", NULL, 0,
|
||||
SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_AIF_IN("TXIN", NULL, 0,
|
||||
CS4265_SPDIF_CTL2, 5, 1),
|
||||
|
||||
SND_SOC_DAPM_OUTPUT("LINEOUTL"),
|
||||
SND_SOC_DAPM_OUTPUT("LINEOUTR"),
|
||||
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route cs4265_audio_map[] = {
|
||||
|
||||
{"DIN1", NULL, "DAI1 Playback"},
|
||||
{"DIN2", NULL, "DAI2 Playback"},
|
||||
{"SDIN1 Input Mixer", NULL, "DIN1"},
|
||||
{"SDIN2 Input Mixer", NULL, "DIN2"},
|
||||
{"Input Mux", "SDIN1", "SDIN1 Input Mixer"},
|
||||
{"Input Mux", "SDIN2", "SDIN2 Input Mixer"},
|
||||
{"DAC", "Switch", "Input Mux"},
|
||||
{"SPDIF", "Switch", "Input Mux"},
|
||||
{"LINEOUTL", NULL, "DAC"},
|
||||
{"LINEOUTR", NULL, "DAC"},
|
||||
{"SPDIFOUT", NULL, "SPDIF"},
|
||||
|
||||
{"ADC Mux", "LINEIN", "LINEINL"},
|
||||
{"ADC Mux", "LINEIN", "LINEINR"},
|
||||
{"ADC Mux", "MIC", "MICL"},
|
||||
{"ADC Mux", "MIC", "MICR"},
|
||||
{"ADC", NULL, "ADC Mux"},
|
||||
{"DOUT", NULL, "ADC"},
|
||||
{"DAI1 Capture", NULL, "DOUT"},
|
||||
{"DAI2 Capture", NULL, "DOUT"},
|
||||
|
||||
/* Loopback */
|
||||
{"Loopback", "Switch", "ADC"},
|
||||
{"DAC", NULL, "Loopback"},
|
||||
};
|
||||
|
||||
struct cs4265_clk_para {
|
||||
u32 mclk;
|
||||
u32 rate;
|
||||
u8 fm_mode; /* values 1, 2, or 4 */
|
||||
u8 mclkdiv;
|
||||
};
|
||||
|
||||
static const struct cs4265_clk_para clk_map_table[] = {
|
||||
/*32k*/
|
||||
{8192000, 32000, 0, 0},
|
||||
{12288000, 32000, 0, 1},
|
||||
{16384000, 32000, 0, 2},
|
||||
{24576000, 32000, 0, 3},
|
||||
{32768000, 32000, 0, 4},
|
||||
|
||||
/*44.1k*/
|
||||
{11289600, 44100, 0, 0},
|
||||
{16934400, 44100, 0, 1},
|
||||
{22579200, 44100, 0, 2},
|
||||
{33868000, 44100, 0, 3},
|
||||
{45158400, 44100, 0, 4},
|
||||
|
||||
/*48k*/
|
||||
{12288000, 48000, 0, 0},
|
||||
{18432000, 48000, 0, 1},
|
||||
{24576000, 48000, 0, 2},
|
||||
{36864000, 48000, 0, 3},
|
||||
{49152000, 48000, 0, 4},
|
||||
|
||||
/*64k*/
|
||||
{8192000, 64000, 1, 0},
|
||||
{1228800, 64000, 1, 1},
|
||||
{1693440, 64000, 1, 2},
|
||||
{2457600, 64000, 1, 3},
|
||||
{3276800, 64000, 1, 4},
|
||||
|
||||
/* 88.2k */
|
||||
{11289600, 88200, 1, 0},
|
||||
{16934400, 88200, 1, 1},
|
||||
{22579200, 88200, 1, 2},
|
||||
{33868000, 88200, 1, 3},
|
||||
{45158400, 88200, 1, 4},
|
||||
|
||||
/* 96k */
|
||||
{12288000, 96000, 1, 0},
|
||||
{18432000, 96000, 1, 1},
|
||||
{24576000, 96000, 1, 2},
|
||||
{36864000, 96000, 1, 3},
|
||||
{49152000, 96000, 1, 4},
|
||||
|
||||
/* 128k */
|
||||
{8192000, 128000, 2, 0},
|
||||
{12288000, 128000, 2, 1},
|
||||
{16934400, 128000, 2, 2},
|
||||
{24576000, 128000, 2, 3},
|
||||
{32768000, 128000, 2, 4},
|
||||
|
||||
/* 176.4k */
|
||||
{11289600, 176400, 2, 0},
|
||||
{16934400, 176400, 2, 1},
|
||||
{22579200, 176400, 2, 2},
|
||||
{33868000, 176400, 2, 3},
|
||||
{49152000, 176400, 2, 4},
|
||||
|
||||
/* 192k */
|
||||
{12288000, 192000, 2, 0},
|
||||
{18432000, 192000, 2, 1},
|
||||
{24576000, 192000, 2, 2},
|
||||
{36864000, 192000, 2, 3},
|
||||
{49152000, 192000, 2, 4},
|
||||
};
|
||||
|
||||
static int cs4265_get_clk_index(int mclk, int rate)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) {
|
||||
if (clk_map_table[i].rate == rate &&
|
||||
clk_map_table[i].mclk == mclk)
|
||||
return i;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int cs4265_set_sysclk(struct snd_soc_dai *codec_dai, int clk_id,
|
||||
unsigned int freq, int dir)
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec);
|
||||
int i;
|
||||
|
||||
if (clk_id != 0) {
|
||||
dev_err(codec->dev, "Invalid clk_id %d\n", clk_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) {
|
||||
if (clk_map_table[i].mclk == freq) {
|
||||
cs4265->sysclk = freq;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
cs4265->sysclk = 0;
|
||||
dev_err(codec->dev, "Invalid freq parameter %d\n", freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int cs4265_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec);
|
||||
u8 iface = 0;
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
snd_soc_update_bits(codec, CS4265_ADC_CTL,
|
||||
CS4265_ADC_MASTER,
|
||||
CS4265_ADC_MASTER);
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
snd_soc_update_bits(codec, CS4265_ADC_CTL,
|
||||
CS4265_ADC_MASTER,
|
||||
0);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* interface format */
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
iface |= SND_SOC_DAIFMT_I2S;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
iface |= SND_SOC_DAIFMT_RIGHT_J;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
iface |= SND_SOC_DAIFMT_LEFT_J;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cs4265->format = iface;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs4265_digital_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
|
||||
if (mute) {
|
||||
snd_soc_update_bits(codec, CS4265_DAC_CTL,
|
||||
CS4265_DAC_CTL_MUTE,
|
||||
CS4265_DAC_CTL_MUTE);
|
||||
snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
|
||||
CS4265_SPDIF_CTL2_MUTE,
|
||||
CS4265_SPDIF_CTL2_MUTE);
|
||||
} else {
|
||||
snd_soc_update_bits(codec, CS4265_DAC_CTL,
|
||||
CS4265_DAC_CTL_MUTE,
|
||||
0);
|
||||
snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
|
||||
CS4265_SPDIF_CTL2_MUTE,
|
||||
0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs4265_pcm_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 cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec);
|
||||
int index;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
|
||||
((cs4265->format & SND_SOC_DAIFMT_FORMAT_MASK)
|
||||
== SND_SOC_DAIFMT_RIGHT_J))
|
||||
return -EINVAL;
|
||||
|
||||
index = cs4265_get_clk_index(cs4265->sysclk, params_rate(params));
|
||||
if (index >= 0) {
|
||||
snd_soc_update_bits(codec, CS4265_ADC_CTL,
|
||||
CS4265_ADC_FM, clk_map_table[index].fm_mode);
|
||||
snd_soc_update_bits(codec, CS4265_MCLK_FREQ,
|
||||
CS4265_MCLK_FREQ_MASK,
|
||||
clk_map_table[index].mclkdiv);
|
||||
|
||||
} else {
|
||||
dev_err(codec->dev, "can't get correct mclk\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (cs4265->format & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
snd_soc_update_bits(codec, CS4265_DAC_CTL,
|
||||
CS4265_DAC_CTL_DIF, (1 << 4));
|
||||
snd_soc_update_bits(codec, CS4265_ADC_CTL,
|
||||
CS4265_ADC_DIF, (1 << 4));
|
||||
snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
|
||||
CS4265_SPDIF_CTL2_DIF, (1 << 6));
|
||||
break;
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
if (params_width(params) == 16) {
|
||||
snd_soc_update_bits(codec, CS4265_DAC_CTL,
|
||||
CS4265_DAC_CTL_DIF, (1 << 5));
|
||||
snd_soc_update_bits(codec, CS4265_ADC_CTL,
|
||||
CS4265_SPDIF_CTL2_DIF, (1 << 7));
|
||||
} else {
|
||||
snd_soc_update_bits(codec, CS4265_DAC_CTL,
|
||||
CS4265_DAC_CTL_DIF, (3 << 5));
|
||||
snd_soc_update_bits(codec, CS4265_ADC_CTL,
|
||||
CS4265_SPDIF_CTL2_DIF, (1 << 7));
|
||||
}
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
snd_soc_update_bits(codec, CS4265_DAC_CTL,
|
||||
CS4265_DAC_CTL_DIF, 0);
|
||||
snd_soc_update_bits(codec, CS4265_ADC_CTL,
|
||||
CS4265_ADC_DIF, 0);
|
||||
snd_soc_update_bits(codec, CS4265_ADC_CTL,
|
||||
CS4265_SPDIF_CTL2_DIF, (1 << 6));
|
||||
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs4265_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
break;
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
snd_soc_update_bits(codec, CS4265_PWRCTL,
|
||||
CS4265_PWRCTL_PDN, 0);
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
snd_soc_update_bits(codec, CS4265_PWRCTL,
|
||||
CS4265_PWRCTL_PDN,
|
||||
CS4265_PWRCTL_PDN);
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
snd_soc_update_bits(codec, CS4265_PWRCTL,
|
||||
CS4265_PWRCTL_PDN,
|
||||
CS4265_PWRCTL_PDN);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CS4265_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
|
||||
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \
|
||||
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
|
||||
SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
|
||||
|
||||
#define CS4265_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \
|
||||
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE)
|
||||
|
||||
static const struct snd_soc_dai_ops cs4265_ops = {
|
||||
.hw_params = cs4265_pcm_hw_params,
|
||||
.digital_mute = cs4265_digital_mute,
|
||||
.set_fmt = cs4265_set_fmt,
|
||||
.set_sysclk = cs4265_set_sysclk,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver cs4265_dai[] = {
|
||||
{
|
||||
.name = "cs4265-dai1",
|
||||
.playback = {
|
||||
.stream_name = "DAI1 Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = CS4265_RATES,
|
||||
.formats = CS4265_FORMATS,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "DAI1 Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = CS4265_RATES,
|
||||
.formats = CS4265_FORMATS,
|
||||
},
|
||||
.ops = &cs4265_ops,
|
||||
},
|
||||
{
|
||||
.name = "cs4265-dai2",
|
||||
.playback = {
|
||||
.stream_name = "DAI2 Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = CS4265_RATES,
|
||||
.formats = CS4265_FORMATS,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "DAI2 Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = CS4265_RATES,
|
||||
.formats = CS4265_FORMATS,
|
||||
},
|
||||
.ops = &cs4265_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct snd_soc_codec_driver soc_codec_cs4265 = {
|
||||
.set_bias_level = cs4265_set_bias_level,
|
||||
|
||||
.dapm_widgets = cs4265_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(cs4265_dapm_widgets),
|
||||
.dapm_routes = cs4265_audio_map,
|
||||
.num_dapm_routes = ARRAY_SIZE(cs4265_audio_map),
|
||||
|
||||
.controls = cs4265_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(cs4265_snd_controls),
|
||||
};
|
||||
|
||||
static const struct regmap_config cs4265_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
||||
.max_register = CS4265_MAX_REGISTER,
|
||||
.reg_defaults = cs4265_reg_defaults,
|
||||
.num_reg_defaults = ARRAY_SIZE(cs4265_reg_defaults),
|
||||
.readable_reg = cs4265_readable_register,
|
||||
.volatile_reg = cs4265_volatile_register,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static int cs4265_i2c_probe(struct i2c_client *i2c_client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct cs4265_private *cs4265;
|
||||
int ret = 0;
|
||||
unsigned int devid = 0;
|
||||
unsigned int reg;
|
||||
|
||||
cs4265 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4265_private),
|
||||
GFP_KERNEL);
|
||||
if (cs4265 == NULL)
|
||||
return -ENOMEM;
|
||||
cs4265->dev = &i2c_client->dev;
|
||||
|
||||
cs4265->regmap = devm_regmap_init_i2c(i2c_client, &cs4265_regmap);
|
||||
if (IS_ERR(cs4265->regmap)) {
|
||||
ret = PTR_ERR(cs4265->regmap);
|
||||
dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
cs4265->reset_gpio = devm_gpiod_get(&i2c_client->dev,
|
||||
"reset-gpios");
|
||||
if (IS_ERR(cs4265->reset_gpio)) {
|
||||
ret = PTR_ERR(cs4265->reset_gpio);
|
||||
if (ret != -ENOENT && ret != -ENOSYS)
|
||||
return ret;
|
||||
|
||||
cs4265->reset_gpio = NULL;
|
||||
} else {
|
||||
ret = gpiod_direction_output(cs4265->reset_gpio, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
mdelay(1);
|
||||
gpiod_set_value_cansleep(cs4265->reset_gpio, 1);
|
||||
|
||||
}
|
||||
|
||||
i2c_set_clientdata(i2c_client, cs4265);
|
||||
|
||||
ret = regmap_read(cs4265->regmap, CS4265_CHIP_ID, ®);
|
||||
devid = reg & CS4265_CHIP_ID_MASK;
|
||||
if (devid != CS4265_CHIP_ID_VAL) {
|
||||
ret = -ENODEV;
|
||||
dev_err(&i2c_client->dev,
|
||||
"CS4265 Device ID (%X). Expected %X\n",
|
||||
devid, CS4265_CHIP_ID);
|
||||
return ret;
|
||||
}
|
||||
dev_info(&i2c_client->dev,
|
||||
"CS4265 Version %x\n",
|
||||
reg & CS4265_REV_ID_MASK);
|
||||
|
||||
regmap_write(cs4265->regmap, CS4265_PWRCTL, 0x0F);
|
||||
|
||||
ret = snd_soc_register_codec(&i2c_client->dev,
|
||||
&soc_codec_cs4265, cs4265_dai,
|
||||
ARRAY_SIZE(cs4265_dai));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cs4265_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id cs4265_of_match[] = {
|
||||
{ .compatible = "cirrus,cs4265", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cs4265_of_match);
|
||||
|
||||
static const struct i2c_device_id cs4265_id[] = {
|
||||
{ "cs4265", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cs4265_id);
|
||||
|
||||
static struct i2c_driver cs4265_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "cs4265",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = cs4265_of_match,
|
||||
},
|
||||
.id_table = cs4265_id,
|
||||
.probe = cs4265_i2c_probe,
|
||||
.remove = cs4265_i2c_remove,
|
||||
};
|
||||
|
||||
module_i2c_driver(cs4265_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC CS4265 driver");
|
||||
MODULE_AUTHOR("Paul Handrigan, Cirrus Logic Inc, <paul.handrigan@cirrus.com>");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* cs4265.h -- CS4265 ALSA SoC audio driver
|
||||
*
|
||||
* Copyright 2014 Cirrus Logic, Inc.
|
||||
*
|
||||
* Author: Paul Handrigan <paul.handrigan@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 __CS4265_H__
|
||||
#define __CS4265_H__
|
||||
|
||||
#define CS4265_CHIP_ID 0x1
|
||||
#define CS4265_CHIP_ID_VAL 0xD0
|
||||
#define CS4265_CHIP_ID_MASK 0xF0
|
||||
#define CS4265_REV_ID_MASK 0x0F
|
||||
|
||||
#define CS4265_PWRCTL 0x02
|
||||
#define CS4265_PWRCTL_PDN 1
|
||||
|
||||
#define CS4265_DAC_CTL 0x3
|
||||
#define CS4265_DAC_CTL_MUTE (1 << 2)
|
||||
#define CS4265_DAC_CTL_DIF (3 << 4)
|
||||
|
||||
#define CS4265_ADC_CTL 0x4
|
||||
#define CS4265_ADC_MASTER 1
|
||||
#define CS4265_ADC_DIF (1 << 4)
|
||||
#define CS4265_ADC_FM (3 << 6)
|
||||
|
||||
#define CS4265_MCLK_FREQ 0x5
|
||||
#define CS4265_MCLK_FREQ_MASK (7 << 4)
|
||||
|
||||
#define CS4265_SIG_SEL 0x6
|
||||
#define CS4265_SIG_SEL_LOOP (1 << 1)
|
||||
|
||||
#define CS4265_CHB_PGA_CTL 0x7
|
||||
#define CS4265_CHA_PGA_CTL 0x8
|
||||
|
||||
#define CS4265_ADC_CTL2 0x9
|
||||
|
||||
#define CS4265_DAC_CHA_VOL 0xA
|
||||
#define CS4265_DAC_CHB_VOL 0xB
|
||||
|
||||
#define CS4265_DAC_CTL2 0xC
|
||||
|
||||
#define CS4265_INT_STATUS 0xD
|
||||
#define CS4265_INT_MASK 0xE
|
||||
#define CS4265_STATUS_MODE_MSB 0xF
|
||||
#define CS4265_STATUS_MODE_LSB 0x10
|
||||
|
||||
#define CS4265_SPDIF_CTL1 0x11
|
||||
|
||||
#define CS4265_SPDIF_CTL2 0x12
|
||||
#define CS4265_SPDIF_CTL2_MUTE (1 << 4)
|
||||
#define CS4265_SPDIF_CTL2_DIF (3 << 6)
|
||||
|
||||
#define CS4265_C_DATA_BUFF 0x13
|
||||
#define CS4265_MAX_REGISTER 0x2A
|
||||
|
||||
#endif
|
|
@ -664,10 +664,8 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
|
|||
|
||||
cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private),
|
||||
GFP_KERNEL);
|
||||
if (!cs4270) {
|
||||
dev_err(&i2c_client->dev, "could not allocate codec\n");
|
||||
if (!cs4270)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* get the power supply regulators */
|
||||
for (i = 0; i < ARRAY_SIZE(supply_names); i++)
|
||||
|
|
|
@ -399,15 +399,15 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
|
|||
CS42L52_MASTERB_VOL, 0, 0x34, 0xE4, hl_tlv),
|
||||
|
||||
SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L52_HPA_VOL,
|
||||
CS42L52_HPB_VOL, 0, 0x34, 0xCC, hpd_tlv),
|
||||
CS42L52_HPB_VOL, 0, 0x34, 0xC0, hpd_tlv),
|
||||
|
||||
SOC_ENUM("Headphone Analog Gain", hp_gain_enum),
|
||||
|
||||
SOC_DOUBLE_R_SX_TLV("Speaker Volume", CS42L52_SPKA_VOL,
|
||||
CS42L52_SPKB_VOL, 0, 0x1, 0xff, hl_tlv),
|
||||
CS42L52_SPKB_VOL, 0, 0x40, 0xC0, hl_tlv),
|
||||
|
||||
SOC_DOUBLE_R_SX_TLV("Bypass Volume", CS42L52_PASSTHRUA_VOL,
|
||||
CS42L52_PASSTHRUB_VOL, 6, 0x18, 0x90, pga_tlv),
|
||||
CS42L52_PASSTHRUB_VOL, 0, 0x88, 0x90, pga_tlv),
|
||||
|
||||
SOC_DOUBLE("Bypass Mute", CS42L52_MISC_CTL, 4, 5, 1, 0),
|
||||
|
||||
|
@ -417,10 +417,10 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
|
|||
SOC_ENUM("MIC Bias Level", mic_bias_level_enum),
|
||||
|
||||
SOC_DOUBLE_R_SX_TLV("ADC Volume", CS42L52_ADCA_VOL,
|
||||
CS42L52_ADCB_VOL, 7, 0x80, 0xA0, ipd_tlv),
|
||||
CS42L52_ADCB_VOL, 0, 0xA0, 0x78, ipd_tlv),
|
||||
SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume",
|
||||
CS42L52_ADCA_MIXER_VOL, CS42L52_ADCB_MIXER_VOL,
|
||||
6, 0x7f, 0x19, ipd_tlv),
|
||||
0, 0x19, 0x7F, ipd_tlv),
|
||||
|
||||
SOC_DOUBLE("ADC Switch", CS42L52_ADC_MISC_CTL, 0, 1, 1, 0),
|
||||
|
||||
|
@ -428,11 +428,11 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
|
|||
CS42L52_ADCB_MIXER_VOL, 7, 1, 1),
|
||||
|
||||
SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L52_PGAA_CTL,
|
||||
CS42L52_PGAB_CTL, 0, 0x28, 0x30, pga_tlv),
|
||||
CS42L52_PGAB_CTL, 0, 0x28, 0x24, pga_tlv),
|
||||
|
||||
SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume",
|
||||
CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL,
|
||||
0, 0x7f, 0x19, mix_tlv),
|
||||
0, 0x19, 0x7f, mix_tlv),
|
||||
SOC_DOUBLE_R("PCM Mixer Switch",
|
||||
CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL, 7, 1, 1),
|
||||
|
||||
|
|
|
@ -318,24 +318,32 @@ static const struct soc_enum adca_swap_enum =
|
|||
ARRAY_SIZE(left_swap_text),
|
||||
left_swap_text,
|
||||
swap_values);
|
||||
static const struct snd_kcontrol_new adca_swap_mux =
|
||||
SOC_DAPM_ENUM("Route", adca_swap_enum);
|
||||
|
||||
static const struct soc_enum pcma_swap_enum =
|
||||
SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 4, 3,
|
||||
ARRAY_SIZE(left_swap_text),
|
||||
left_swap_text,
|
||||
swap_values);
|
||||
static const struct snd_kcontrol_new pcma_swap_mux =
|
||||
SOC_DAPM_ENUM("Route", pcma_swap_enum);
|
||||
|
||||
static const struct soc_enum adcb_swap_enum =
|
||||
SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 2, 3,
|
||||
ARRAY_SIZE(right_swap_text),
|
||||
right_swap_text,
|
||||
swap_values);
|
||||
static const struct snd_kcontrol_new adcb_swap_mux =
|
||||
SOC_DAPM_ENUM("Route", adcb_swap_enum);
|
||||
|
||||
static const struct soc_enum pcmb_swap_enum =
|
||||
SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 6, 3,
|
||||
ARRAY_SIZE(right_swap_text),
|
||||
right_swap_text,
|
||||
swap_values);
|
||||
static const struct snd_kcontrol_new pcmb_swap_mux =
|
||||
SOC_DAPM_ENUM("Route", pcmb_swap_enum);
|
||||
|
||||
static const struct snd_kcontrol_new hpa_switch =
|
||||
SOC_DAPM_SINGLE("Switch", CS42L56_PWRCTL_2, 6, 1, 1);
|
||||
|
@ -421,15 +429,15 @@ static const struct soc_enum ng_delay_enum =
|
|||
static const struct snd_kcontrol_new cs42l56_snd_controls[] = {
|
||||
|
||||
SOC_DOUBLE_R_SX_TLV("Master Volume", CS42L56_MASTER_A_VOLUME,
|
||||
CS42L56_MASTER_B_VOLUME, 0, 0x34, 0xfd, adv_tlv),
|
||||
CS42L56_MASTER_B_VOLUME, 0, 0x34, 0xE4, adv_tlv),
|
||||
SOC_DOUBLE("Master Mute Switch", CS42L56_DSP_MUTE_CTL, 0, 1, 1, 1),
|
||||
|
||||
SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", CS42L56_ADCA_MIX_VOLUME,
|
||||
CS42L56_ADCB_MIX_VOLUME, 0, 0x88, 0xa9, hl_tlv),
|
||||
CS42L56_ADCB_MIX_VOLUME, 0, 0x88, 0x90, hl_tlv),
|
||||
SOC_DOUBLE("ADC Mixer Mute Switch", CS42L56_DSP_MUTE_CTL, 6, 7, 1, 1),
|
||||
|
||||
SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume", CS42L56_PCMA_MIX_VOLUME,
|
||||
CS42L56_PCMB_MIX_VOLUME, 0, 0x88, 0xa9, hl_tlv),
|
||||
CS42L56_PCMB_MIX_VOLUME, 0, 0x88, 0x90, hl_tlv),
|
||||
SOC_DOUBLE("PCM Mixer Mute Switch", CS42L56_DSP_MUTE_CTL, 4, 5, 1, 1),
|
||||
|
||||
SOC_SINGLE_TLV("Analog Advisory Volume",
|
||||
|
@ -438,16 +446,16 @@ static const struct snd_kcontrol_new cs42l56_snd_controls[] = {
|
|||
CS42L56_DIGINPUT_ADV_VOLUME, 0, 0x00, 1, adv_tlv),
|
||||
|
||||
SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L56_PGAA_MUX_VOLUME,
|
||||
CS42L56_PGAB_MUX_VOLUME, 0, 0x34, 0xfd, pga_tlv),
|
||||
CS42L56_PGAB_MUX_VOLUME, 0, 0x34, 0x24, pga_tlv),
|
||||
SOC_DOUBLE_R_TLV("ADC Volume", CS42L56_ADCA_ATTENUATOR,
|
||||
CS42L56_ADCB_ATTENUATOR, 0, 0x00, 1, adc_tlv),
|
||||
SOC_DOUBLE("ADC Mute Switch", CS42L56_MISC_ADC_CTL, 2, 3, 1, 1),
|
||||
SOC_DOUBLE("ADC Boost Switch", CS42L56_GAIN_BIAS_CTL, 3, 2, 1, 1),
|
||||
|
||||
SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L56_HPA_VOLUME,
|
||||
CS42L56_HPB_VOLUME, 0, 0x44, 0x55, hl_tlv),
|
||||
CS42L56_HPB_VOLUME, 0, 0x84, 0x48, hl_tlv),
|
||||
SOC_DOUBLE_R_SX_TLV("LineOut Volume", CS42L56_LOA_VOLUME,
|
||||
CS42L56_LOB_VOLUME, 0, 0x44, 0x55, hl_tlv),
|
||||
CS42L56_LOB_VOLUME, 0, 0x84, 0x48, hl_tlv),
|
||||
|
||||
SOC_SINGLE_TLV("Bass Shelving Volume", CS42L56_TONE_CTL,
|
||||
0, 0x00, 1, tone_tlv),
|
||||
|
@ -467,11 +475,6 @@ static const struct snd_kcontrol_new cs42l56_snd_controls[] = {
|
|||
SOC_SINGLE("ADCA Invert", CS42L56_MISC_ADC_CTL, 2, 1, 1),
|
||||
SOC_SINGLE("ADCB Invert", CS42L56_MISC_ADC_CTL, 3, 1, 1),
|
||||
|
||||
SOC_ENUM("PCMA Swap", pcma_swap_enum),
|
||||
SOC_ENUM("PCMB Swap", pcmb_swap_enum),
|
||||
SOC_ENUM("ADCA Swap", adca_swap_enum),
|
||||
SOC_ENUM("ADCB Swap", adcb_swap_enum),
|
||||
|
||||
SOC_DOUBLE("HPF Switch", CS42L56_HPF_CTL, 5, 7, 1, 1),
|
||||
SOC_DOUBLE("HPF Freeze Switch", CS42L56_HPF_CTL, 4, 6, 1, 1),
|
||||
SOC_ENUM("HPFA Corner Freq", hpfa_freq_enum),
|
||||
|
@ -570,6 +573,16 @@ static const struct snd_soc_dapm_widget cs42l56_dapm_widgets[] = {
|
|||
SND_SOC_DAPM_ADC("ADCA", NULL, CS42L56_PWRCTL_1, 1, 1),
|
||||
SND_SOC_DAPM_ADC("ADCB", NULL, CS42L56_PWRCTL_1, 2, 1),
|
||||
|
||||
SND_SOC_DAPM_MUX("ADCA Swap Mux", SND_SOC_NOPM, 0, 0,
|
||||
&adca_swap_mux),
|
||||
SND_SOC_DAPM_MUX("ADCB Swap Mux", SND_SOC_NOPM, 0, 0,
|
||||
&adcb_swap_mux),
|
||||
|
||||
SND_SOC_DAPM_MUX("PCMA Swap Mux", SND_SOC_NOPM, 0, 0,
|
||||
&pcma_swap_mux),
|
||||
SND_SOC_DAPM_MUX("PCMB Swap Mux", SND_SOC_NOPM, 0, 0,
|
||||
&pcmb_swap_mux),
|
||||
|
||||
SND_SOC_DAPM_DAC("DACA", NULL, SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_DAC("DACB", NULL, SND_SOC_NOPM, 0, 0),
|
||||
|
||||
|
@ -607,8 +620,19 @@ static const struct snd_soc_dapm_route cs42l56_audio_map[] = {
|
|||
{"Digital Output Mux", NULL, "ADCA"},
|
||||
{"Digital Output Mux", NULL, "ADCB"},
|
||||
|
||||
{"ADCB", NULL, "ADCB Mux"},
|
||||
{"ADCA", NULL, "ADCA Mux"},
|
||||
{"ADCB", NULL, "ADCB Swap Mux"},
|
||||
{"ADCA", NULL, "ADCA Swap Mux"},
|
||||
|
||||
{"ADCA Swap Mux", NULL, "ADCA"},
|
||||
{"ADCB Swap Mux", NULL, "ADCB"},
|
||||
|
||||
{"DACA", "Left", "ADCA Swap Mux"},
|
||||
{"DACA", "LR 2", "ADCA Swap Mux"},
|
||||
{"DACA", "Right", "ADCA Swap Mux"},
|
||||
|
||||
{"DACB", "Left", "ADCB Swap Mux"},
|
||||
{"DACB", "LR 2", "ADCB Swap Mux"},
|
||||
{"DACB", "Right", "ADCB Swap Mux"},
|
||||
|
||||
{"ADCA Mux", NULL, "AIN3A"},
|
||||
{"ADCA Mux", NULL, "AIN2A"},
|
||||
|
@ -633,30 +657,32 @@ static const struct snd_soc_dapm_route cs42l56_audio_map[] = {
|
|||
{"PGAB Input Mux", NULL, "AIN2B"},
|
||||
{"PGAB Input Mux", NULL, "AIN3B"},
|
||||
|
||||
{"LOB", NULL, "Lineout Right"},
|
||||
{"LOA", NULL, "Lineout Left"},
|
||||
|
||||
{"Lineout Right", "Switch", "LINEOUTB Input Mux"},
|
||||
{"Lineout Left", "Switch", "LINEOUTA Input Mux"},
|
||||
{"LOB", "Switch", "LINEOUTB Input Mux"},
|
||||
{"LOA", "Switch", "LINEOUTA Input Mux"},
|
||||
|
||||
{"LINEOUTA Input Mux", "PGAA", "PGAA"},
|
||||
{"LINEOUTB Input Mux", "PGAB", "PGAB"},
|
||||
{"LINEOUTA Input Mux", "DACA", "DACA"},
|
||||
{"LINEOUTB Input Mux", "DACB", "DACB"},
|
||||
|
||||
{"HPA", NULL, "Headphone Left"},
|
||||
{"HPB", NULL, "Headphone Right"},
|
||||
|
||||
{"Headphone Right", "Switch", "HPB Input Mux"},
|
||||
{"Headphone Left", "Switch", "HPA Input Mux"},
|
||||
{"HPA", "Switch", "HPB Input Mux"},
|
||||
{"HPB", "Switch", "HPA Input Mux"},
|
||||
|
||||
{"HPA Input Mux", "PGAA", "PGAA"},
|
||||
{"HPB Input Mux", "PGAB", "PGAB"},
|
||||
{"HPA Input Mux", "DACA", "DACA"},
|
||||
{"HPB Input Mux", "DACB", "DACB"},
|
||||
|
||||
{"DACB", NULL, "HiFi Playback"},
|
||||
{"DACA", NULL, "HiFi Playback"},
|
||||
{"DACA", NULL, "PCMA Swap Mux"},
|
||||
{"DACB", NULL, "PCMB Swap Mux"},
|
||||
|
||||
{"PCMB Swap Mux", "Left", "HiFi Playback"},
|
||||
{"PCMB Swap Mux", "LR 2", "HiFi Playback"},
|
||||
{"PCMB Swap Mux", "Right", "HiFi Playback"},
|
||||
|
||||
{"PCMA Swap Mux", "Left", "HiFi Playback"},
|
||||
{"PCMA Swap Mux", "LR 2", "HiFi Playback"},
|
||||
{"PCMA Swap Mux", "Right", "HiFi Playback"},
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -401,7 +401,7 @@ static const struct snd_kcontrol_new cs42l73_snd_controls[] = {
|
|||
CS42L73_LOBAVOL, 0, 0x41, 0x4B, hpaloa_tlv),
|
||||
|
||||
SOC_DOUBLE_R_SX_TLV("Input PGA Analog Volume", CS42L73_MICAPREPGAAVOL,
|
||||
CS42L73_MICBPREPGABVOL, 5, 0x34,
|
||||
CS42L73_MICBPREPGABVOL, 0, 0x34,
|
||||
0x24, micpga_tlv),
|
||||
|
||||
SOC_DOUBLE_R("MIC Preamp Switch", CS42L73_MICAPREPGAAVOL,
|
||||
|
@ -1408,10 +1408,8 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
|
|||
|
||||
cs42l73 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l73_private),
|
||||
GFP_KERNEL);
|
||||
if (!cs42l73) {
|
||||
dev_err(&i2c_client->dev, "could not allocate codec\n");
|
||||
if (!cs42l73)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cs42l73->regmap = devm_regmap_init_i2c(i2c_client, &cs42l73_regmap);
|
||||
if (IS_ERR(cs42l73->regmap)) {
|
||||
|
|
|
@ -219,6 +219,9 @@ static int cs42xx8_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
|||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
val = CS42XX8_INTF_DAC_DIF_RIGHTJ | CS42XX8_INTF_ADC_DIF_RIGHTJ;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
val = CS42XX8_INTF_DAC_DIF_TDM | CS42XX8_INTF_ADC_DIF_TDM;
|
||||
break;
|
||||
default:
|
||||
dev_err(codec->dev, "unsupported dai format\n");
|
||||
return -EINVAL;
|
||||
|
@ -422,7 +425,7 @@ const struct cs42xx8_driver_data cs42888_data = {
|
|||
};
|
||||
EXPORT_SYMBOL_GPL(cs42888_data);
|
||||
|
||||
const struct of_device_id cs42xx8_of_match[] = {
|
||||
static const struct of_device_id cs42xx8_of_match[] = {
|
||||
{ .compatible = "cirrus,cs42448", .data = &cs42448_data, },
|
||||
{ .compatible = "cirrus,cs42888", .data = &cs42888_data, },
|
||||
{ /* sentinel */ }
|
||||
|
|
|
@ -128,8 +128,8 @@ int cs42xx8_probe(struct device *dev, struct regmap *regmap);
|
|||
#define CS42XX8_INTF_DAC_DIF_RIGHTJ (2 << CS42XX8_INTF_DAC_DIF_SHIFT)
|
||||
#define CS42XX8_INTF_DAC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_DAC_DIF_SHIFT)
|
||||
#define CS42XX8_INTF_DAC_DIF_ONELINE_20 (4 << CS42XX8_INTF_DAC_DIF_SHIFT)
|
||||
#define CS42XX8_INTF_DAC_DIF_ONELINE_24 (6 << CS42XX8_INTF_DAC_DIF_SHIFT)
|
||||
#define CS42XX8_INTF_DAC_DIF_TDM (7 << CS42XX8_INTF_DAC_DIF_SHIFT)
|
||||
#define CS42XX8_INTF_DAC_DIF_ONELINE_24 (5 << CS42XX8_INTF_DAC_DIF_SHIFT)
|
||||
#define CS42XX8_INTF_DAC_DIF_TDM (6 << CS42XX8_INTF_DAC_DIF_SHIFT)
|
||||
#define CS42XX8_INTF_ADC_DIF_SHIFT 0
|
||||
#define CS42XX8_INTF_ADC_DIF_WIDTH 3
|
||||
#define CS42XX8_INTF_ADC_DIF_MASK (((1 << CS42XX8_INTF_ADC_DIF_WIDTH) - 1) << CS42XX8_INTF_ADC_DIF_SHIFT)
|
||||
|
@ -138,8 +138,8 @@ int cs42xx8_probe(struct device *dev, struct regmap *regmap);
|
|||
#define CS42XX8_INTF_ADC_DIF_RIGHTJ (2 << CS42XX8_INTF_ADC_DIF_SHIFT)
|
||||
#define CS42XX8_INTF_ADC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_ADC_DIF_SHIFT)
|
||||
#define CS42XX8_INTF_ADC_DIF_ONELINE_20 (4 << CS42XX8_INTF_ADC_DIF_SHIFT)
|
||||
#define CS42XX8_INTF_ADC_DIF_ONELINE_24 (6 << CS42XX8_INTF_ADC_DIF_SHIFT)
|
||||
#define CS42XX8_INTF_ADC_DIF_TDM (7 << CS42XX8_INTF_ADC_DIF_SHIFT)
|
||||
#define CS42XX8_INTF_ADC_DIF_ONELINE_24 (5 << CS42XX8_INTF_ADC_DIF_SHIFT)
|
||||
#define CS42XX8_INTF_ADC_DIF_TDM (6 << CS42XX8_INTF_ADC_DIF_SHIFT)
|
||||
|
||||
/* ADC Control & DAC De-Emphasis (Address 05h) */
|
||||
#define CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT 7
|
||||
|
|
|
@ -253,7 +253,7 @@ static void v253_close(struct tty_struct *tty)
|
|||
/* Prevent the codec driver from further accessing the modem */
|
||||
codec->hw_write = NULL;
|
||||
cx20442->control_data = NULL;
|
||||
codec->card->pop_time = 0;
|
||||
codec->component.card->pop_time = 0;
|
||||
}
|
||||
|
||||
/* Line discipline .hangup() */
|
||||
|
@ -281,7 +281,7 @@ static void v253_receive(struct tty_struct *tty,
|
|||
/* Set up codec driver access to modem controls */
|
||||
cx20442->control_data = tty;
|
||||
codec->hw_write = (hw_write_t)tty->ops->write;
|
||||
codec->card->pop_time = 1;
|
||||
codec->component.card->pop_time = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -372,7 +372,7 @@ static int cx20442_codec_probe(struct snd_soc_codec *codec)
|
|||
|
||||
snd_soc_codec_set_drvdata(codec, cx20442);
|
||||
codec->hw_write = NULL;
|
||||
codec->card->pop_time = 0;
|
||||
codec->component.card->pop_time = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -383,8 +383,8 @@ static int cx20442_codec_remove(struct snd_soc_codec *codec)
|
|||
struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (cx20442->control_data) {
|
||||
struct tty_struct *tty = cx20442->control_data;
|
||||
tty_hangup(tty);
|
||||
struct tty_struct *tty = cx20442->control_data;
|
||||
tty_hangup(tty);
|
||||
}
|
||||
|
||||
if (!IS_ERR(cx20442->por)) {
|
||||
|
|
|
@ -1299,12 +1299,12 @@ static int max98088_dai2_hw_params(struct snd_pcm_substream *substream,
|
|||
|
||||
rate = params_rate(params);
|
||||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT,
|
||||
M98088_DAI_WS, 0);
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
case 24:
|
||||
snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT,
|
||||
M98088_DAI_WS, M98088_DAI_WS);
|
||||
break;
|
||||
|
|
|
@ -26,10 +26,6 @@
|
|||
#include <sound/max98090.h>
|
||||
#include "max98090.h"
|
||||
|
||||
#define DEBUG
|
||||
#define EXTMIC_METHOD
|
||||
#define EXTMIC_METHOD_TEST
|
||||
|
||||
/* Allows for sparsely populated register maps */
|
||||
static struct reg_default max98090_reg[] = {
|
||||
{ 0x00, 0x00 }, /* 00 Software Reset */
|
||||
|
@ -820,7 +816,6 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w,
|
|||
else
|
||||
val = (val & M98090_MIC_PA2EN_MASK) >> M98090_MIC_PA2EN_SHIFT;
|
||||
|
||||
|
||||
if (val >= 1) {
|
||||
if (w->reg == M98090_REG_MIC1_INPUT_LEVEL) {
|
||||
max98090->pa1en = val - 1; /* Update for volatile */
|
||||
|
@ -1140,7 +1135,6 @@ static const struct snd_kcontrol_new max98090_mixhprsel_mux =
|
|||
SOC_DAPM_ENUM("MIXHPRSEL Mux", mixhprsel_mux_enum);
|
||||
|
||||
static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
|
||||
|
||||
SND_SOC_DAPM_INPUT("MIC1"),
|
||||
SND_SOC_DAPM_INPUT("MIC2"),
|
||||
SND_SOC_DAPM_INPUT("DMICL"),
|
||||
|
@ -1304,7 +1298,6 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
|
|||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = {
|
||||
|
||||
SND_SOC_DAPM_INPUT("DMIC3"),
|
||||
SND_SOC_DAPM_INPUT("DMIC4"),
|
||||
|
||||
|
@ -1315,7 +1308,6 @@ static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = {
|
|||
};
|
||||
|
||||
static const struct snd_soc_dapm_route max98090_dapm_routes[] = {
|
||||
|
||||
{"MIC1 Input", NULL, "MIC1"},
|
||||
{"MIC2 Input", NULL, "MIC2"},
|
||||
|
||||
|
@ -1493,17 +1485,14 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = {
|
|||
{"SPKR", NULL, "SPK Right Out"},
|
||||
{"RCVL", NULL, "RCV Left Out"},
|
||||
{"RCVR", NULL, "RCV Right Out"},
|
||||
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route max98091_dapm_routes[] = {
|
||||
|
||||
/* DMIC inputs */
|
||||
{"DMIC3", NULL, "DMIC3_ENA"},
|
||||
{"DMIC4", NULL, "DMIC4_ENA"},
|
||||
{"DMIC3", NULL, "AHPF"},
|
||||
{"DMIC4", NULL, "AHPF"},
|
||||
|
||||
};
|
||||
|
||||
static int max98090_add_widgets(struct snd_soc_codec *codec)
|
||||
|
@ -1531,7 +1520,6 @@ static int max98090_add_widgets(struct snd_soc_codec *codec)
|
|||
|
||||
snd_soc_dapm_add_routes(dapm, max98091_dapm_routes,
|
||||
ARRAY_SIZE(max98091_dapm_routes));
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -2212,22 +2200,11 @@ static struct snd_soc_dai_driver max98090_dai[] = {
|
|||
}
|
||||
};
|
||||
|
||||
static void max98090_handle_pdata(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
|
||||
struct max98090_pdata *pdata = max98090->pdata;
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(codec->dev, "No platform data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int max98090_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
|
||||
struct max98090_cdata *cdata;
|
||||
enum max98090_type devtype;
|
||||
int ret = 0;
|
||||
|
||||
dev_dbg(codec->dev, "max98090_probe\n");
|
||||
|
@ -2263,16 +2240,21 @@ static int max98090_probe(struct snd_soc_codec *codec)
|
|||
}
|
||||
|
||||
if ((ret >= M98090_REVA) && (ret <= M98090_REVA + 0x0f)) {
|
||||
max98090->devtype = MAX98090;
|
||||
devtype = MAX98090;
|
||||
dev_info(codec->dev, "MAX98090 REVID=0x%02x\n", ret);
|
||||
} else if ((ret >= M98091_REVA) && (ret <= M98091_REVA + 0x0f)) {
|
||||
max98090->devtype = MAX98091;
|
||||
devtype = MAX98091;
|
||||
dev_info(codec->dev, "MAX98091 REVID=0x%02x\n", ret);
|
||||
} else {
|
||||
max98090->devtype = MAX98090;
|
||||
devtype = MAX98090;
|
||||
dev_err(codec->dev, "Unrecognized revision 0x%02x\n", ret);
|
||||
}
|
||||
|
||||
if (max98090->devtype != devtype) {
|
||||
dev_warn(codec->dev, "Mismatch in DT specified CODEC type.\n");
|
||||
max98090->devtype = devtype;
|
||||
}
|
||||
|
||||
max98090->jack_state = M98090_JACK_STATE_NO_HEADSET;
|
||||
|
||||
INIT_DELAYED_WORK(&max98090->jack_work, max98090_jack_work);
|
||||
|
@ -2317,8 +2299,6 @@ static int max98090_probe(struct snd_soc_codec *codec)
|
|||
snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE,
|
||||
M98090_MBVSEL_MASK, M98090_MBVSEL_2V8);
|
||||
|
||||
max98090_handle_pdata(codec);
|
||||
|
||||
max98090_add_widgets(codec);
|
||||
|
||||
err_access:
|
||||
|
@ -2428,7 +2408,7 @@ static int max98090_runtime_suspend(struct device *dev)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int max98090_resume(struct device *dev)
|
||||
{
|
||||
struct max98090_priv *max98090 = dev_get_drvdata(dev);
|
||||
|
@ -2460,12 +2440,14 @@ static const struct dev_pm_ops max98090_pm = {
|
|||
|
||||
static const struct i2c_device_id max98090_i2c_id[] = {
|
||||
{ "max98090", MAX98090 },
|
||||
{ "max98091", MAX98091 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, max98090_i2c_id);
|
||||
|
||||
static const struct of_device_id max98090_of_match[] = {
|
||||
{ .compatible = "maxim,max98090", },
|
||||
{ .compatible = "maxim,max98091", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, max98090_of_match);
|
||||
|
|
|
@ -1280,12 +1280,12 @@ static int max98095_dai2_hw_params(struct snd_pcm_substream *substream,
|
|||
|
||||
rate = params_rate(params);
|
||||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
snd_soc_update_bits(codec, M98095_034_DAI2_FORMAT,
|
||||
M98095_DAI_WS, 0);
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
case 24:
|
||||
snd_soc_update_bits(codec, M98095_034_DAI2_FORMAT,
|
||||
M98095_DAI_WS, M98095_DAI_WS);
|
||||
break;
|
||||
|
@ -1341,12 +1341,12 @@ static int max98095_dai3_hw_params(struct snd_pcm_substream *substream,
|
|||
|
||||
rate = params_rate(params);
|
||||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
snd_soc_update_bits(codec, M98095_03E_DAI3_FORMAT,
|
||||
M98095_DAI_WS, 0);
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
case 24:
|
||||
snd_soc_update_bits(codec, M98095_03E_DAI3_FORMAT,
|
||||
M98095_DAI_WS, M98095_DAI_WS);
|
||||
break;
|
||||
|
|
|
@ -766,11 +766,11 @@ static int __init mc13783_codec_probe(struct platform_device *pdev)
|
|||
|
||||
ret = of_property_read_u32(np, "adc-port", &priv->adc_ssi_port);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
ret = of_property_read_u32(np, "dac-port", &priv->dac_ssi_port);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_set_drvdata(&pdev->dev, priv);
|
||||
|
@ -783,6 +783,8 @@ static int __init mc13783_codec_probe(struct platform_device *pdev)
|
|||
ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783,
|
||||
mc13783_dai_async, ARRAY_SIZE(mc13783_dai_async));
|
||||
|
||||
out:
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#define PCM1792A_DAC_VOL_LEFT 0x10
|
||||
#define PCM1792A_DAC_VOL_RIGHT 0x11
|
||||
#define PCM1792A_FMT_CONTROL 0x12
|
||||
#define PCM1792A_MODE_CONTROL 0x13
|
||||
#define PCM1792A_SOFT_MUTE PCM1792A_FMT_CONTROL
|
||||
|
||||
#define PCM1792A_FMT_MASK 0x70
|
||||
|
@ -164,6 +165,8 @@ static const struct snd_kcontrol_new pcm1792a_controls[] = {
|
|||
SOC_DOUBLE_R_RANGE_TLV("DAC Playback Volume", PCM1792A_DAC_VOL_LEFT,
|
||||
PCM1792A_DAC_VOL_RIGHT, 0, 0xf, 0xff, 0,
|
||||
pcm1792a_dac_tlv),
|
||||
SOC_SINGLE("DAC Invert Output Switch", PCM1792A_MODE_CONTROL, 7, 1, 0),
|
||||
SOC_SINGLE("DAC Rolloff Filter Switch", PCM1792A_MODE_CONTROL, 1, 1, 0),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget pcm1792a_dapm_widgets[] = {
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
#define __PCM1792A_H__
|
||||
|
||||
#define PCM1792A_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_8000_48000 | \
|
||||
SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
|
||||
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
|
||||
SNDRV_PCM_RATE_192000)
|
||||
|
||||
#define PCM1792A_FORMATS (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \
|
||||
SNDRV_PCM_FMTBIT_S16_LE)
|
||||
|
|
|
@ -11,25 +11,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#include "rl6231.h"
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* rt286.h -- RT286 ALSA SoC audio driver
|
||||
*
|
||||
* Copyright 2011 Realtek Microelectronics
|
||||
* Author: Johnny Hsu <johnnyhsu@realtek.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 __RT286_H__
|
||||
#define __RT286_H__
|
||||
|
||||
#define VERB_CMD(V, N, D) ((N << 20) | (V << 8) | D)
|
||||
|
||||
#define RT286_AUDIO_FUNCTION_GROUP 0x01
|
||||
#define RT286_DAC_OUT1 0x02
|
||||
#define RT286_DAC_OUT2 0x03
|
||||
#define RT286_ADC_IN1 0x09
|
||||
#define RT286_ADC_IN2 0x08
|
||||
#define RT286_MIXER_IN 0x0b
|
||||
#define RT286_MIXER_OUT1 0x0c
|
||||
#define RT286_MIXER_OUT2 0x0d
|
||||
#define RT286_DMIC1 0x12
|
||||
#define RT286_DMIC2 0x13
|
||||
#define RT286_SPK_OUT 0x14
|
||||
#define RT286_MIC1 0x18
|
||||
#define RT286_LINE1 0x1a
|
||||
#define RT286_BEEP 0x1d
|
||||
#define RT286_SPDIF 0x1e
|
||||
#define RT286_VENDOR_REGISTERS 0x20
|
||||
#define RT286_HP_OUT 0x21
|
||||
#define RT286_MIXER_IN1 0x22
|
||||
#define RT286_MIXER_IN2 0x23
|
||||
|
||||
#define RT286_SET_PIN_SFT 6
|
||||
#define RT286_SET_PIN_ENABLE 0x40
|
||||
#define RT286_SET_PIN_DISABLE 0
|
||||
#define RT286_SET_EAPD_HIGH 0x2
|
||||
#define RT286_SET_EAPD_LOW 0
|
||||
|
||||
#define RT286_MUTE_SFT 7
|
||||
|
||||
/* Verb commands */
|
||||
#define RT286_GET_PARAM(NID, PARAM) VERB_CMD(AC_VERB_PARAMETERS, NID, PARAM)
|
||||
#define RT286_SET_POWER(NID) VERB_CMD(AC_VERB_SET_POWER_STATE, NID, 0)
|
||||
#define RT286_SET_AUDIO_POWER RT286_SET_POWER(RT286_AUDIO_FUNCTION_GROUP)
|
||||
#define RT286_SET_HPO_POWER RT286_SET_POWER(RT286_HP_OUT)
|
||||
#define RT286_SET_SPK_POWER RT286_SET_POWER(RT286_SPK_OUT)
|
||||
#define RT286_SET_DMIC1_POWER RT286_SET_POWER(RT286_DMIC1)
|
||||
#define RT286_SPK_MUX\
|
||||
VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_SPK_OUT, 0)
|
||||
#define RT286_HPO_MUX\
|
||||
VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_HP_OUT, 0)
|
||||
#define RT286_ADC0_MUX\
|
||||
VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_MIXER_IN1, 0)
|
||||
#define RT286_ADC1_MUX\
|
||||
VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_MIXER_IN2, 0)
|
||||
#define RT286_SET_MIC1\
|
||||
VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_MIC1, 0)
|
||||
#define RT286_SET_PIN_HPO\
|
||||
VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_HP_OUT, 0)
|
||||
#define RT286_SET_PIN_SPK\
|
||||
VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_SPK_OUT, 0)
|
||||
#define RT286_SET_PIN_DMIC1\
|
||||
VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_DMIC1, 0)
|
||||
#define RT286_SPK_EAPD\
|
||||
VERB_CMD(AC_VERB_SET_EAPD_BTLENABLE, RT286_SPK_OUT, 0)
|
||||
#define RT286_SET_AMP_GAIN_HPO\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_HP_OUT, 0)
|
||||
#define RT286_SET_AMP_GAIN_ADC_IN1\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN1, 0)
|
||||
#define RT286_SET_AMP_GAIN_ADC_IN2\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN2, 0)
|
||||
#define RT286_GET_HP_SENSE\
|
||||
VERB_CMD(AC_VERB_GET_PIN_SENSE, RT286_HP_OUT, 0)
|
||||
#define RT286_GET_MIC1_SENSE\
|
||||
VERB_CMD(AC_VERB_GET_PIN_SENSE, RT286_MIC1, 0)
|
||||
#define RT286_SET_DMIC2_DEFAULT\
|
||||
VERB_CMD(AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, RT286_DMIC2, 0)
|
||||
#define RT286_DACL_GAIN\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_DAC_OUT1, 0xa000)
|
||||
#define RT286_DACR_GAIN\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_DAC_OUT1, 0x9000)
|
||||
#define RT286_ADCL_GAIN\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN1, 0x6000)
|
||||
#define RT286_ADCR_GAIN\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN1, 0x5000)
|
||||
#define RT286_MIC_GAIN\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIC1, 0x7000)
|
||||
#define RT286_SPOL_GAIN\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_SPK_OUT, 0xa000)
|
||||
#define RT286_SPOR_GAIN\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_SPK_OUT, 0x9000)
|
||||
#define RT286_HPOL_GAIN\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_HP_OUT, 0xa000)
|
||||
#define RT286_HPOR_GAIN\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_HP_OUT, 0x9000)
|
||||
#define RT286_F_DAC_SWITCH\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_OUT1, 0x7000)
|
||||
#define RT286_F_RECMIX_SWITCH\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_OUT1, 0x7100)
|
||||
#define RT286_REC_MIC_SWITCH\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7000)
|
||||
#define RT286_REC_I2S_SWITCH\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7100)
|
||||
#define RT286_REC_LINE_SWITCH\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7200)
|
||||
#define RT286_REC_BEEP_SWITCH\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7300)
|
||||
#define RT286_DAC_FORMAT\
|
||||
VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT286_DAC_OUT1, 0)
|
||||
#define RT286_ADC_FORMAT\
|
||||
VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT286_ADC_IN1, 0)
|
||||
#define RT286_COEF_INDEX\
|
||||
VERB_CMD(AC_VERB_SET_COEF_INDEX, RT286_VENDOR_REGISTERS, 0)
|
||||
#define RT286_PROC_COEF\
|
||||
VERB_CMD(AC_VERB_SET_PROC_COEF, RT286_VENDOR_REGISTERS, 0)
|
||||
|
||||
/* Index registers */
|
||||
#define RT286_A_BIAS_CTRL1 0x01
|
||||
#define RT286_A_BIAS_CTRL2 0x02
|
||||
#define RT286_POWER_CTRL1 0x03
|
||||
#define RT286_A_BIAS_CTRL3 0x04
|
||||
#define RT286_POWER_CTRL2 0x08
|
||||
#define RT286_I2S_CTRL1 0x09
|
||||
#define RT286_I2S_CTRL2 0x0a
|
||||
#define RT286_CLK_DIV 0x0b
|
||||
#define RT286_DC_GAIN 0x0d
|
||||
#define RT286_POWER_CTRL3 0x0f
|
||||
#define RT286_MIC1_DET_CTRL 0x19
|
||||
#define RT286_MISC_CTRL1 0x20
|
||||
#define RT286_IRQ_CTRL 0x33
|
||||
#define RT286_PLL_CTRL1 0x49
|
||||
#define RT286_CBJ_CTRL1 0x4f
|
||||
#define RT286_CBJ_CTRL2 0x50
|
||||
#define RT286_PLL_CTRL 0x63
|
||||
#define RT286_DEPOP_CTRL1 0x66
|
||||
#define RT286_DEPOP_CTRL2 0x67
|
||||
#define RT286_DEPOP_CTRL3 0x68
|
||||
#define RT286_DEPOP_CTRL4 0x69
|
||||
|
||||
/* SPDIF (0x06) */
|
||||
#define RT286_SPDIF_SEL_SFT 0
|
||||
#define RT286_SPDIF_SEL_PCM0 0
|
||||
#define RT286_SPDIF_SEL_PCM1 1
|
||||
#define RT286_SPDIF_SEL_SPOUT 2
|
||||
#define RT286_SPDIF_SEL_PP 3
|
||||
|
||||
/* RECMIX (0x0b) */
|
||||
#define RT286_M_REC_BEEP_SFT 0
|
||||
#define RT286_M_REC_LINE1_SFT 1
|
||||
#define RT286_M_REC_MIC1_SFT 2
|
||||
#define RT286_M_REC_I2S_SFT 3
|
||||
|
||||
/* Front (0x0c) */
|
||||
#define RT286_M_FRONT_DAC_SFT 0
|
||||
#define RT286_M_FRONT_REC_SFT 1
|
||||
|
||||
/* SPK-OUT (0x14) */
|
||||
#define RT286_M_SPK_MUX_SFT 14
|
||||
#define RT286_SPK_SEL_MASK 0x1
|
||||
#define RT286_SPK_SEL_SFT 0
|
||||
#define RT286_SPK_SEL_F 0
|
||||
#define RT286_SPK_SEL_S 1
|
||||
|
||||
/* HP-OUT (0x21) */
|
||||
#define RT286_M_HP_MUX_SFT 14
|
||||
#define RT286_HP_SEL_MASK 0x1
|
||||
#define RT286_HP_SEL_SFT 0
|
||||
#define RT286_HP_SEL_F 0
|
||||
#define RT286_HP_SEL_S 1
|
||||
|
||||
/* ADC (0x22) (0x23) */
|
||||
#define RT286_ADC_SEL_MASK 0x7
|
||||
#define RT286_ADC_SEL_SFT 0
|
||||
#define RT286_ADC_SEL_SURR 0
|
||||
#define RT286_ADC_SEL_FRONT 1
|
||||
#define RT286_ADC_SEL_DMIC 2
|
||||
#define RT286_ADC_SEL_BEEP 4
|
||||
#define RT286_ADC_SEL_LINE1 5
|
||||
#define RT286_ADC_SEL_I2S 6
|
||||
#define RT286_ADC_SEL_MIC1 7
|
||||
|
||||
#define RT286_SCLK_S_MCLK 0
|
||||
#define RT286_SCLK_S_PLL 1
|
||||
|
||||
enum {
|
||||
RT286_AIF1,
|
||||
RT286_AIF2,
|
||||
RT286_AIFS,
|
||||
};
|
||||
|
||||
int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
|
||||
|
||||
#endif /* __RT286_H__ */
|
||||
|
|
@ -1370,16 +1370,16 @@ static int rt5631_hifi_pcm_params(struct snd_pcm_substream *substream,
|
|||
return coeff;
|
||||
}
|
||||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S20_3LE:
|
||||
case 20:
|
||||
iface |= RT5631_SDP_I2S_DL_20;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
case 24:
|
||||
iface |= RT5631_SDP_I2S_DL_24;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S8:
|
||||
case 8:
|
||||
iface |= RT5631_SDP_I2S_DL_8;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -2215,14 +2215,8 @@ static int rt5640_i2c_probe(struct i2c_client *i2c,
|
|||
|
||||
rt5640->hp_mute = 1;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5640,
|
||||
rt5640_dai, ARRAY_SIZE(rt5640_dai));
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
return ret;
|
||||
return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5640,
|
||||
rt5640_dai, ARRAY_SIZE(rt5640_dai));
|
||||
}
|
||||
|
||||
static int rt5640_i2c_remove(struct i2c_client *i2c)
|
||||
|
|
|
@ -2345,14 +2345,8 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
|
|||
|
||||
}
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645,
|
||||
rt5645_dai, ARRAY_SIZE(rt5645_dai));
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
return ret;
|
||||
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)
|
||||
|
|
|
@ -1366,16 +1366,16 @@ static int rt5651_hw_params(struct snd_pcm_substream *substream,
|
|||
dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
|
||||
bclk_ms, pre_div, dai->id);
|
||||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S20_3LE:
|
||||
case 20:
|
||||
val_len |= RT5651_I2S_DL_20;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
case 24:
|
||||
val_len |= RT5651_I2S_DL_24;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S8:
|
||||
case 8:
|
||||
val_len |= RT5651_I2S_DL_8;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* rt5670-dsp.h -- RT5670 ALSA SoC DSP driver
|
||||
*
|
||||
* Copyright 2014 Realtek Microelectronics
|
||||
* Author: Bard Liao <bardliao@realtek.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 __RT5670_DSP_H__
|
||||
#define __RT5670_DSP_H__
|
||||
|
||||
#define RT5670_DSP_CTRL1 0xe0
|
||||
#define RT5670_DSP_CTRL2 0xe1
|
||||
#define RT5670_DSP_CTRL3 0xe2
|
||||
#define RT5670_DSP_CTRL4 0xe3
|
||||
#define RT5670_DSP_CTRL5 0xe4
|
||||
|
||||
/* DSP Control 1 (0xe0) */
|
||||
#define RT5670_DSP_CMD_MASK (0xff << 8)
|
||||
#define RT5670_DSP_CMD_PE (0x0d << 8) /* Patch Entry */
|
||||
#define RT5670_DSP_CMD_MW (0x3b << 8) /* Memory Write */
|
||||
#define RT5670_DSP_CMD_MR (0x37 << 8) /* Memory Read */
|
||||
#define RT5670_DSP_CMD_RR (0x60 << 8) /* Register Read */
|
||||
#define RT5670_DSP_CMD_RW (0x68 << 8) /* Register Write */
|
||||
#define RT5670_DSP_REG_DATHI (0x26 << 8) /* High Data Addr */
|
||||
#define RT5670_DSP_REG_DATLO (0x25 << 8) /* Low Data Addr */
|
||||
#define RT5670_DSP_CLK_MASK (0x3 << 6)
|
||||
#define RT5670_DSP_CLK_SFT 6
|
||||
#define RT5670_DSP_CLK_768K (0x0 << 6)
|
||||
#define RT5670_DSP_CLK_384K (0x1 << 6)
|
||||
#define RT5670_DSP_CLK_192K (0x2 << 6)
|
||||
#define RT5670_DSP_CLK_96K (0x3 << 6)
|
||||
#define RT5670_DSP_BUSY_MASK (0x1 << 5)
|
||||
#define RT5670_DSP_RW_MASK (0x1 << 4)
|
||||
#define RT5670_DSP_DL_MASK (0x3 << 2)
|
||||
#define RT5670_DSP_DL_0 (0x0 << 2)
|
||||
#define RT5670_DSP_DL_1 (0x1 << 2)
|
||||
#define RT5670_DSP_DL_2 (0x2 << 2)
|
||||
#define RT5670_DSP_DL_3 (0x3 << 2)
|
||||
#define RT5670_DSP_I2C_AL_16 (0x1 << 1)
|
||||
#define RT5670_DSP_CMD_EN (0x1)
|
||||
|
||||
struct rt5670_dsp_param {
|
||||
u16 cmd_fmt;
|
||||
u16 addr;
|
||||
u16 data;
|
||||
u8 cmd;
|
||||
};
|
||||
|
||||
#endif /* __RT5670_DSP_H__ */
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -27,6 +27,7 @@
|
|||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#include "rl6231.h"
|
||||
#include "rt5677.h"
|
||||
|
||||
#define RT5677_DEVICE_ID 0x6327
|
||||
|
@ -604,19 +605,19 @@ static const struct snd_kcontrol_new rt5677_snd_controls[] = {
|
|||
adc_vol_tlv),
|
||||
|
||||
/* ADC Boost Volume Control */
|
||||
SOC_DOUBLE_TLV("STO1 ADC Boost Gain", RT5677_STO1_2_ADC_BST,
|
||||
SOC_DOUBLE_TLV("STO1 ADC Boost Volume", RT5677_STO1_2_ADC_BST,
|
||||
RT5677_STO1_ADC_L_BST_SFT, RT5677_STO1_ADC_R_BST_SFT, 3, 0,
|
||||
adc_bst_tlv),
|
||||
SOC_DOUBLE_TLV("STO2 ADC Boost Gain", RT5677_STO1_2_ADC_BST,
|
||||
SOC_DOUBLE_TLV("STO2 ADC Boost Volume", RT5677_STO1_2_ADC_BST,
|
||||
RT5677_STO2_ADC_L_BST_SFT, RT5677_STO2_ADC_R_BST_SFT, 3, 0,
|
||||
adc_bst_tlv),
|
||||
SOC_DOUBLE_TLV("STO3 ADC Boost Gain", RT5677_STO3_4_ADC_BST,
|
||||
SOC_DOUBLE_TLV("STO3 ADC Boost Volume", RT5677_STO3_4_ADC_BST,
|
||||
RT5677_STO3_ADC_L_BST_SFT, RT5677_STO3_ADC_R_BST_SFT, 3, 0,
|
||||
adc_bst_tlv),
|
||||
SOC_DOUBLE_TLV("STO4 ADC Boost Gain", RT5677_STO3_4_ADC_BST,
|
||||
SOC_DOUBLE_TLV("STO4 ADC Boost Volume", RT5677_STO3_4_ADC_BST,
|
||||
RT5677_STO4_ADC_L_BST_SFT, RT5677_STO4_ADC_R_BST_SFT, 3, 0,
|
||||
adc_bst_tlv),
|
||||
SOC_DOUBLE_TLV("Mono ADC Boost Gain", RT5677_ADC_BST_CTRL2,
|
||||
SOC_DOUBLE_TLV("Mono ADC Boost Volume", RT5677_ADC_BST_CTRL2,
|
||||
RT5677_MONO_ADC_L_BST_SFT, RT5677_MONO_ADC_R_BST_SFT, 3, 0,
|
||||
adc_bst_tlv),
|
||||
};
|
||||
|
@ -636,21 +637,7 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
|
|||
{
|
||||
struct snd_soc_codec *codec = w->codec;
|
||||
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
|
||||
int div[] = {2, 3, 4, 6, 8, 12}, idx = -EINVAL, i;
|
||||
int rate, red, bound, temp;
|
||||
|
||||
rate = rt5677->sysclk;
|
||||
red = 3000000 * 12;
|
||||
for (i = 0; i < ARRAY_SIZE(div); i++) {
|
||||
bound = div[i] * 3000000;
|
||||
if (rate > bound)
|
||||
continue;
|
||||
temp = bound - rate;
|
||||
if (temp < red) {
|
||||
red = temp;
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
int idx = rl6231_calc_dmic_clk(rt5677->sysclk);
|
||||
|
||||
if (idx < 0)
|
||||
dev_err(codec->dev, "Failed to set DMIC clock\n");
|
||||
|
@ -951,7 +938,7 @@ static const struct snd_kcontrol_new rt5677_ob_7_mix[] = {
|
|||
|
||||
|
||||
/* Mux */
|
||||
/* DAC1 L/R source */ /* MX-29 [10:8] */
|
||||
/* DAC1 L/R Source */ /* MX-29 [10:8] */
|
||||
static const char * const rt5677_dac1_src[] = {
|
||||
"IF1 DAC 01", "IF2 DAC 01", "IF3 DAC LR", "IF4 DAC LR", "SLB DAC 01",
|
||||
"OB 01"
|
||||
|
@ -962,9 +949,9 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_DAC1_L_SEL_SFT, rt5677_dac1_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_dac1_mux =
|
||||
SOC_DAPM_ENUM("DAC1 source", rt5677_dac1_enum);
|
||||
SOC_DAPM_ENUM("DAC1 Source", rt5677_dac1_enum);
|
||||
|
||||
/* ADDA1 L/R source */ /* MX-29 [1:0] */
|
||||
/* ADDA1 L/R Source */ /* MX-29 [1:0] */
|
||||
static const char * const rt5677_adda1_src[] = {
|
||||
"STO1 ADC MIX", "STO2 ADC MIX", "OB 67",
|
||||
};
|
||||
|
@ -974,10 +961,10 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_ADDA1_SEL_SFT, rt5677_adda1_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_adda1_mux =
|
||||
SOC_DAPM_ENUM("ADDA1 source", rt5677_adda1_enum);
|
||||
SOC_DAPM_ENUM("ADDA1 Source", rt5677_adda1_enum);
|
||||
|
||||
|
||||
/*DAC2 L/R source*/ /* MX-1B [6:4] [2:0] */
|
||||
/*DAC2 L/R Source*/ /* MX-1B [6:4] [2:0] */
|
||||
static const char * const rt5677_dac2l_src[] = {
|
||||
"IF1 DAC 2", "IF2 DAC 2", "IF3 DAC L", "IF4 DAC L", "SLB DAC 2",
|
||||
"OB 2",
|
||||
|
@ -988,7 +975,7 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_SEL_DAC2_L_SRC_SFT, rt5677_dac2l_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_dac2_l_mux =
|
||||
SOC_DAPM_ENUM("DAC2 L source", rt5677_dac2l_enum);
|
||||
SOC_DAPM_ENUM("DAC2 L Source", rt5677_dac2l_enum);
|
||||
|
||||
static const char * const rt5677_dac2r_src[] = {
|
||||
"IF1 DAC 3", "IF2 DAC 3", "IF3 DAC R", "IF4 DAC R", "SLB DAC 3",
|
||||
|
@ -1000,9 +987,9 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_SEL_DAC2_R_SRC_SFT, rt5677_dac2r_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_dac2_r_mux =
|
||||
SOC_DAPM_ENUM("DAC2 R source", rt5677_dac2r_enum);
|
||||
SOC_DAPM_ENUM("DAC2 R Source", rt5677_dac2r_enum);
|
||||
|
||||
/*DAC3 L/R source*/ /* MX-16 [6:4] [2:0] */
|
||||
/*DAC3 L/R Source*/ /* MX-16 [6:4] [2:0] */
|
||||
static const char * const rt5677_dac3l_src[] = {
|
||||
"IF1 DAC 4", "IF2 DAC 4", "IF3 DAC L", "IF4 DAC L",
|
||||
"SLB DAC 4", "OB 4"
|
||||
|
@ -1013,7 +1000,7 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_SEL_DAC3_L_SRC_SFT, rt5677_dac3l_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_dac3_l_mux =
|
||||
SOC_DAPM_ENUM("DAC3 L source", rt5677_dac3l_enum);
|
||||
SOC_DAPM_ENUM("DAC3 L Source", rt5677_dac3l_enum);
|
||||
|
||||
static const char * const rt5677_dac3r_src[] = {
|
||||
"IF1 DAC 5", "IF2 DAC 5", "IF3 DAC R", "IF4 DAC R",
|
||||
|
@ -1025,9 +1012,9 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_SEL_DAC3_R_SRC_SFT, rt5677_dac3r_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_dac3_r_mux =
|
||||
SOC_DAPM_ENUM("DAC3 R source", rt5677_dac3r_enum);
|
||||
SOC_DAPM_ENUM("DAC3 R Source", rt5677_dac3r_enum);
|
||||
|
||||
/*DAC4 L/R source*/ /* MX-16 [14:12] [10:8] */
|
||||
/*DAC4 L/R Source*/ /* MX-16 [14:12] [10:8] */
|
||||
static const char * const rt5677_dac4l_src[] = {
|
||||
"IF1 DAC 6", "IF2 DAC 6", "IF3 DAC L", "IF4 DAC L",
|
||||
"SLB DAC 6", "OB 6"
|
||||
|
@ -1038,7 +1025,7 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_SEL_DAC4_L_SRC_SFT, rt5677_dac4l_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_dac4_l_mux =
|
||||
SOC_DAPM_ENUM("DAC4 L source", rt5677_dac4l_enum);
|
||||
SOC_DAPM_ENUM("DAC4 L Source", rt5677_dac4l_enum);
|
||||
|
||||
static const char * const rt5677_dac4r_src[] = {
|
||||
"IF1 DAC 7", "IF2 DAC 7", "IF3 DAC R", "IF4 DAC R",
|
||||
|
@ -1050,7 +1037,7 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_SEL_DAC4_R_SRC_SFT, rt5677_dac4r_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_dac4_r_mux =
|
||||
SOC_DAPM_ENUM("DAC4 R source", rt5677_dac4r_enum);
|
||||
SOC_DAPM_ENUM("DAC4 R Source", rt5677_dac4r_enum);
|
||||
|
||||
/* In/OutBound Source Pass SRC */ /* MX-A5 [3] [4] [0] [1] [2] */
|
||||
static const char * const rt5677_iob_bypass_src[] = {
|
||||
|
@ -1062,35 +1049,35 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_SEL_SRC_OB01_SFT, rt5677_iob_bypass_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_ob01_bypass_src_mux =
|
||||
SOC_DAPM_ENUM("OB01 Bypass source", rt5677_ob01_bypass_src_enum);
|
||||
SOC_DAPM_ENUM("OB01 Bypass Source", rt5677_ob01_bypass_src_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_ob23_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL,
|
||||
RT5677_SEL_SRC_OB23_SFT, rt5677_iob_bypass_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_ob23_bypass_src_mux =
|
||||
SOC_DAPM_ENUM("OB23 Bypass source", rt5677_ob23_bypass_src_enum);
|
||||
SOC_DAPM_ENUM("OB23 Bypass Source", rt5677_ob23_bypass_src_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_ib01_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL,
|
||||
RT5677_SEL_SRC_IB01_SFT, rt5677_iob_bypass_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_ib01_bypass_src_mux =
|
||||
SOC_DAPM_ENUM("IB01 Bypass source", rt5677_ib01_bypass_src_enum);
|
||||
SOC_DAPM_ENUM("IB01 Bypass Source", rt5677_ib01_bypass_src_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_ib23_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL,
|
||||
RT5677_SEL_SRC_IB23_SFT, rt5677_iob_bypass_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_ib23_bypass_src_mux =
|
||||
SOC_DAPM_ENUM("IB23 Bypass source", rt5677_ib23_bypass_src_enum);
|
||||
SOC_DAPM_ENUM("IB23 Bypass Source", rt5677_ib23_bypass_src_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_ib45_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL,
|
||||
RT5677_SEL_SRC_IB45_SFT, rt5677_iob_bypass_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_ib45_bypass_src_mux =
|
||||
SOC_DAPM_ENUM("IB45 Bypass source", rt5677_ib45_bypass_src_enum);
|
||||
SOC_DAPM_ENUM("IB45 Bypass Source", rt5677_ib45_bypass_src_enum);
|
||||
|
||||
/* Stereo ADC Source 2 */ /* MX-27 MX26 MX25 [11:10] */
|
||||
static const char * const rt5677_stereo_adc2_src[] = {
|
||||
|
@ -1102,21 +1089,21 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_SEL_STO1_ADC2_SFT, rt5677_stereo_adc2_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_sto1_adc2_mux =
|
||||
SOC_DAPM_ENUM("Stereo1 ADC2 source", rt5677_stereo1_adc2_enum);
|
||||
SOC_DAPM_ENUM("Stereo1 ADC2 Source", rt5677_stereo1_adc2_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_stereo2_adc2_enum, RT5677_STO2_ADC_MIXER,
|
||||
RT5677_SEL_STO2_ADC2_SFT, rt5677_stereo_adc2_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_sto2_adc2_mux =
|
||||
SOC_DAPM_ENUM("Stereo2 ADC2 source", rt5677_stereo2_adc2_enum);
|
||||
SOC_DAPM_ENUM("Stereo2 ADC2 Source", rt5677_stereo2_adc2_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_stereo3_adc2_enum, RT5677_STO3_ADC_MIXER,
|
||||
RT5677_SEL_STO3_ADC2_SFT, rt5677_stereo_adc2_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_sto3_adc2_mux =
|
||||
SOC_DAPM_ENUM("Stereo3 ADC2 source", rt5677_stereo3_adc2_enum);
|
||||
SOC_DAPM_ENUM("Stereo3 ADC2 Source", rt5677_stereo3_adc2_enum);
|
||||
|
||||
/* DMIC Source */ /* MX-28 [9:8][1:0] MX-27 MX-26 MX-25 MX-24 [9:8] */
|
||||
static const char * const rt5677_dmic_src[] = {
|
||||
|
@ -1128,44 +1115,44 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_SEL_MONO_DMIC_L_SFT, rt5677_dmic_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_mono_dmic_l_mux =
|
||||
SOC_DAPM_ENUM("Mono DMIC L source", rt5677_mono_dmic_l_enum);
|
||||
SOC_DAPM_ENUM("Mono DMIC L Source", rt5677_mono_dmic_l_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_mono_dmic_r_enum, RT5677_MONO_ADC_MIXER,
|
||||
RT5677_SEL_MONO_DMIC_R_SFT, rt5677_dmic_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_mono_dmic_r_mux =
|
||||
SOC_DAPM_ENUM("Mono DMIC R source", rt5677_mono_dmic_r_enum);
|
||||
SOC_DAPM_ENUM("Mono DMIC R Source", rt5677_mono_dmic_r_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_stereo1_dmic_enum, RT5677_STO1_ADC_MIXER,
|
||||
RT5677_SEL_STO1_DMIC_SFT, rt5677_dmic_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_sto1_dmic_mux =
|
||||
SOC_DAPM_ENUM("Stereo1 DMIC source", rt5677_stereo1_dmic_enum);
|
||||
SOC_DAPM_ENUM("Stereo1 DMIC Source", rt5677_stereo1_dmic_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_stereo2_dmic_enum, RT5677_STO2_ADC_MIXER,
|
||||
RT5677_SEL_STO2_DMIC_SFT, rt5677_dmic_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_sto2_dmic_mux =
|
||||
SOC_DAPM_ENUM("Stereo2 DMIC source", rt5677_stereo2_dmic_enum);
|
||||
SOC_DAPM_ENUM("Stereo2 DMIC Source", rt5677_stereo2_dmic_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_stereo3_dmic_enum, RT5677_STO3_ADC_MIXER,
|
||||
RT5677_SEL_STO3_DMIC_SFT, rt5677_dmic_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_sto3_dmic_mux =
|
||||
SOC_DAPM_ENUM("Stereo3 DMIC source", rt5677_stereo3_dmic_enum);
|
||||
SOC_DAPM_ENUM("Stereo3 DMIC Source", rt5677_stereo3_dmic_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_stereo4_dmic_enum, RT5677_STO4_ADC_MIXER,
|
||||
RT5677_SEL_STO4_DMIC_SFT, rt5677_dmic_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_sto4_dmic_mux =
|
||||
SOC_DAPM_ENUM("Stereo4 DMIC source", rt5677_stereo4_dmic_enum);
|
||||
SOC_DAPM_ENUM("Stereo4 DMIC Source", rt5677_stereo4_dmic_enum);
|
||||
|
||||
/* Stereo2 ADC source */ /* MX-26 [0] */
|
||||
/* Stereo2 ADC Source */ /* MX-26 [0] */
|
||||
static const char * const rt5677_stereo2_adc_lr_src[] = {
|
||||
"L", "LR"
|
||||
};
|
||||
|
@ -1175,7 +1162,7 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_SEL_STO2_LR_MIX_SFT, rt5677_stereo2_adc_lr_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_sto2_adc_lr_mux =
|
||||
SOC_DAPM_ENUM("Stereo2 ADC LR source", rt5677_stereo2_adc_lr_enum);
|
||||
SOC_DAPM_ENUM("Stereo2 ADC LR Source", rt5677_stereo2_adc_lr_enum);
|
||||
|
||||
/* Stereo1 ADC Source 1 */ /* MX-27 MX26 MX25 [13:12] */
|
||||
static const char * const rt5677_stereo_adc1_src[] = {
|
||||
|
@ -1187,23 +1174,23 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_SEL_STO1_ADC1_SFT, rt5677_stereo_adc1_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_sto1_adc1_mux =
|
||||
SOC_DAPM_ENUM("Stereo1 ADC1 source", rt5677_stereo1_adc1_enum);
|
||||
SOC_DAPM_ENUM("Stereo1 ADC1 Source", rt5677_stereo1_adc1_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_stereo2_adc1_enum, RT5677_STO2_ADC_MIXER,
|
||||
RT5677_SEL_STO2_ADC1_SFT, rt5677_stereo_adc1_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_sto2_adc1_mux =
|
||||
SOC_DAPM_ENUM("Stereo2 ADC1 source", rt5677_stereo2_adc1_enum);
|
||||
SOC_DAPM_ENUM("Stereo2 ADC1 Source", rt5677_stereo2_adc1_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_stereo3_adc1_enum, RT5677_STO3_ADC_MIXER,
|
||||
RT5677_SEL_STO3_ADC1_SFT, rt5677_stereo_adc1_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_sto3_adc1_mux =
|
||||
SOC_DAPM_ENUM("Stereo3 ADC1 source", rt5677_stereo3_adc1_enum);
|
||||
SOC_DAPM_ENUM("Stereo3 ADC1 Source", rt5677_stereo3_adc1_enum);
|
||||
|
||||
/* Mono ADC Left source 2 */ /* MX-28 [11:10] */
|
||||
/* Mono ADC Left Source 2 */ /* MX-28 [11:10] */
|
||||
static const char * const rt5677_mono_adc2_l_src[] = {
|
||||
"DD MIX1L", "DMIC", "MONO DAC MIXL"
|
||||
};
|
||||
|
@ -1213,9 +1200,9 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_SEL_MONO_ADC_L2_SFT, rt5677_mono_adc2_l_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_mono_adc2_l_mux =
|
||||
SOC_DAPM_ENUM("Mono ADC2 L source", rt5677_mono_adc2_l_enum);
|
||||
SOC_DAPM_ENUM("Mono ADC2 L Source", rt5677_mono_adc2_l_enum);
|
||||
|
||||
/* Mono ADC Left source 1 */ /* MX-28 [13:12] */
|
||||
/* Mono ADC Left Source 1 */ /* MX-28 [13:12] */
|
||||
static const char * const rt5677_mono_adc1_l_src[] = {
|
||||
"DD MIX1L", "ADC1", "MONO DAC MIXL"
|
||||
};
|
||||
|
@ -1225,9 +1212,9 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_SEL_MONO_ADC_L1_SFT, rt5677_mono_adc1_l_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_mono_adc1_l_mux =
|
||||
SOC_DAPM_ENUM("Mono ADC1 L source", rt5677_mono_adc1_l_enum);
|
||||
SOC_DAPM_ENUM("Mono ADC1 L Source", rt5677_mono_adc1_l_enum);
|
||||
|
||||
/* Mono ADC Right source 2 */ /* MX-28 [3:2] */
|
||||
/* Mono ADC Right Source 2 */ /* MX-28 [3:2] */
|
||||
static const char * const rt5677_mono_adc2_r_src[] = {
|
||||
"DD MIX1R", "DMIC", "MONO DAC MIXR"
|
||||
};
|
||||
|
@ -1237,9 +1224,9 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_SEL_MONO_ADC_R2_SFT, rt5677_mono_adc2_r_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_mono_adc2_r_mux =
|
||||
SOC_DAPM_ENUM("Mono ADC2 R source", rt5677_mono_adc2_r_enum);
|
||||
SOC_DAPM_ENUM("Mono ADC2 R Source", rt5677_mono_adc2_r_enum);
|
||||
|
||||
/* Mono ADC Right source 1 */ /* MX-28 [5:4] */
|
||||
/* Mono ADC Right Source 1 */ /* MX-28 [5:4] */
|
||||
static const char * const rt5677_mono_adc1_r_src[] = {
|
||||
"DD MIX1R", "ADC2", "MONO DAC MIXR"
|
||||
};
|
||||
|
@ -1249,7 +1236,7 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_SEL_MONO_ADC_R1_SFT, rt5677_mono_adc1_r_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_mono_adc1_r_mux =
|
||||
SOC_DAPM_ENUM("Mono ADC1 R source", rt5677_mono_adc1_r_enum);
|
||||
SOC_DAPM_ENUM("Mono ADC1 R Source", rt5677_mono_adc1_r_enum);
|
||||
|
||||
/* Stereo4 ADC Source 2 */ /* MX-24 [11:10] */
|
||||
static const char * const rt5677_stereo4_adc2_src[] = {
|
||||
|
@ -1261,7 +1248,7 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_SEL_STO4_ADC2_SFT, rt5677_stereo4_adc2_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_sto4_adc2_mux =
|
||||
SOC_DAPM_ENUM("Stereo4 ADC2 source", rt5677_stereo4_adc2_enum);
|
||||
SOC_DAPM_ENUM("Stereo4 ADC2 Source", rt5677_stereo4_adc2_enum);
|
||||
|
||||
|
||||
/* Stereo4 ADC Source 1 */ /* MX-24 [13:12] */
|
||||
|
@ -1274,7 +1261,7 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_SEL_STO4_ADC1_SFT, rt5677_stereo4_adc1_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_sto4_adc1_mux =
|
||||
SOC_DAPM_ENUM("Stereo4 ADC1 source", rt5677_stereo4_adc1_enum);
|
||||
SOC_DAPM_ENUM("Stereo4 ADC1 Source", rt5677_stereo4_adc1_enum);
|
||||
|
||||
/* InBound0/1 Source */ /* MX-A3 [14:12] */
|
||||
static const char * const rt5677_inbound01_src[] = {
|
||||
|
@ -1416,7 +1403,7 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
static const struct snd_kcontrol_new rt5677_dac3_mux =
|
||||
SOC_DAPM_ENUM("Analog DAC3 Source", rt5677_dac3_enum);
|
||||
|
||||
/* PDM channel source */ /* MX-31 [13:12][9:8][5:4][1:0] */
|
||||
/* PDM channel Source */ /* MX-31 [13:12][9:8][5:4][1:0] */
|
||||
static const char * const rt5677_pdm_src[] = {
|
||||
"STO1 DAC MIX", "MONO DAC MIX", "DD MIX1", "DD MIX2"
|
||||
};
|
||||
|
@ -1426,28 +1413,28 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_SEL_PDM1_L_SFT, rt5677_pdm_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_pdm1_l_mux =
|
||||
SOC_DAPM_ENUM("PDM1 source", rt5677_pdm1_l_enum);
|
||||
SOC_DAPM_ENUM("PDM1 Source", rt5677_pdm1_l_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_pdm2_l_enum, RT5677_PDM_OUT_CTRL,
|
||||
RT5677_SEL_PDM2_L_SFT, rt5677_pdm_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_pdm2_l_mux =
|
||||
SOC_DAPM_ENUM("PDM2 source", rt5677_pdm2_l_enum);
|
||||
SOC_DAPM_ENUM("PDM2 Source", rt5677_pdm2_l_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_pdm1_r_enum, RT5677_PDM_OUT_CTRL,
|
||||
RT5677_SEL_PDM1_R_SFT, rt5677_pdm_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_pdm1_r_mux =
|
||||
SOC_DAPM_ENUM("PDM1 source", rt5677_pdm1_r_enum);
|
||||
SOC_DAPM_ENUM("PDM1 Source", rt5677_pdm1_r_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_pdm2_r_enum, RT5677_PDM_OUT_CTRL,
|
||||
RT5677_SEL_PDM2_R_SFT, rt5677_pdm_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_pdm2_r_mux =
|
||||
SOC_DAPM_ENUM("PDM2 source", rt5677_pdm2_r_enum);
|
||||
SOC_DAPM_ENUM("PDM2 Source", rt5677_pdm2_r_enum);
|
||||
|
||||
/* TDM IF1/2 SLB ADC1 Data Selection */ /* MX-3C MX-41 [5:4] MX-08 [1:0]*/
|
||||
static const char * const rt5677_if12_adc1_src[] = {
|
||||
|
@ -1459,21 +1446,21 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_IF1_ADC1_SFT, rt5677_if12_adc1_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_if1_adc1_mux =
|
||||
SOC_DAPM_ENUM("IF1 ADC1 source", rt5677_if1_adc1_enum);
|
||||
SOC_DAPM_ENUM("IF1 ADC1 Source", rt5677_if1_adc1_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_if2_adc1_enum, RT5677_TDM2_CTRL2,
|
||||
RT5677_IF2_ADC1_SFT, rt5677_if12_adc1_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_if2_adc1_mux =
|
||||
SOC_DAPM_ENUM("IF2 ADC1 source", rt5677_if2_adc1_enum);
|
||||
SOC_DAPM_ENUM("IF2 ADC1 Source", rt5677_if2_adc1_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_slb_adc1_enum, RT5677_SLIMBUS_RX,
|
||||
RT5677_SLB_ADC1_SFT, rt5677_if12_adc1_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_slb_adc1_mux =
|
||||
SOC_DAPM_ENUM("SLB ADC1 source", rt5677_slb_adc1_enum);
|
||||
SOC_DAPM_ENUM("SLB ADC1 Source", rt5677_slb_adc1_enum);
|
||||
|
||||
/* TDM IF1/2 SLB ADC2 Data Selection */ /* MX-3C MX-41 [7:6] MX-08 [3:2] */
|
||||
static const char * const rt5677_if12_adc2_src[] = {
|
||||
|
@ -1485,21 +1472,21 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_IF1_ADC2_SFT, rt5677_if12_adc2_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_if1_adc2_mux =
|
||||
SOC_DAPM_ENUM("IF1 ADC2 source", rt5677_if1_adc2_enum);
|
||||
SOC_DAPM_ENUM("IF1 ADC2 Source", rt5677_if1_adc2_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_if2_adc2_enum, RT5677_TDM2_CTRL2,
|
||||
RT5677_IF2_ADC2_SFT, rt5677_if12_adc2_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_if2_adc2_mux =
|
||||
SOC_DAPM_ENUM("IF2 ADC2 source", rt5677_if2_adc2_enum);
|
||||
SOC_DAPM_ENUM("IF2 ADC2 Source", rt5677_if2_adc2_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_slb_adc2_enum, RT5677_SLIMBUS_RX,
|
||||
RT5677_SLB_ADC2_SFT, rt5677_if12_adc2_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_slb_adc2_mux =
|
||||
SOC_DAPM_ENUM("SLB ADC2 source", rt5677_slb_adc2_enum);
|
||||
SOC_DAPM_ENUM("SLB ADC2 Source", rt5677_slb_adc2_enum);
|
||||
|
||||
/* TDM IF1/2 SLB ADC3 Data Selection */ /* MX-3C MX-41 [9:8] MX-08 [5:4] */
|
||||
static const char * const rt5677_if12_adc3_src[] = {
|
||||
|
@ -1511,21 +1498,21 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_IF1_ADC3_SFT, rt5677_if12_adc3_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_if1_adc3_mux =
|
||||
SOC_DAPM_ENUM("IF1 ADC3 source", rt5677_if1_adc3_enum);
|
||||
SOC_DAPM_ENUM("IF1 ADC3 Source", rt5677_if1_adc3_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_if2_adc3_enum, RT5677_TDM2_CTRL2,
|
||||
RT5677_IF2_ADC3_SFT, rt5677_if12_adc3_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_if2_adc3_mux =
|
||||
SOC_DAPM_ENUM("IF2 ADC3 source", rt5677_if2_adc3_enum);
|
||||
SOC_DAPM_ENUM("IF2 ADC3 Source", rt5677_if2_adc3_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_slb_adc3_enum, RT5677_SLIMBUS_RX,
|
||||
RT5677_SLB_ADC3_SFT, rt5677_if12_adc3_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_slb_adc3_mux =
|
||||
SOC_DAPM_ENUM("SLB ADC3 source", rt5677_slb_adc3_enum);
|
||||
SOC_DAPM_ENUM("SLB ADC3 Source", rt5677_slb_adc3_enum);
|
||||
|
||||
/* TDM IF1/2 SLB ADC4 Data Selection */ /* MX-3C MX-41 [11:10] MX-08 [7:6] */
|
||||
static const char * const rt5677_if12_adc4_src[] = {
|
||||
|
@ -1537,21 +1524,21 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_IF1_ADC4_SFT, rt5677_if12_adc4_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_if1_adc4_mux =
|
||||
SOC_DAPM_ENUM("IF1 ADC4 source", rt5677_if1_adc4_enum);
|
||||
SOC_DAPM_ENUM("IF1 ADC4 Source", rt5677_if1_adc4_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_if2_adc4_enum, RT5677_TDM2_CTRL2,
|
||||
RT5677_IF2_ADC4_SFT, rt5677_if12_adc4_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_if2_adc4_mux =
|
||||
SOC_DAPM_ENUM("IF2 ADC4 source", rt5677_if2_adc4_enum);
|
||||
SOC_DAPM_ENUM("IF2 ADC4 Source", rt5677_if2_adc4_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_slb_adc4_enum, RT5677_SLIMBUS_RX,
|
||||
RT5677_SLB_ADC4_SFT, rt5677_if12_adc4_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_slb_adc4_mux =
|
||||
SOC_DAPM_ENUM("SLB ADC4 source", rt5677_slb_adc4_enum);
|
||||
SOC_DAPM_ENUM("SLB ADC4 Source", rt5677_slb_adc4_enum);
|
||||
|
||||
/* Interface3/4 ADC Data Input */ /* MX-2F [3:0] MX-30 [7:4]*/
|
||||
static const char * const rt5677_if34_adc_src[] = {
|
||||
|
@ -1564,14 +1551,14 @@ static SOC_ENUM_SINGLE_DECL(
|
|||
RT5677_IF3_ADC_IN_SFT, rt5677_if34_adc_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_if3_adc_mux =
|
||||
SOC_DAPM_ENUM("IF3 ADC source", rt5677_if3_adc_enum);
|
||||
SOC_DAPM_ENUM("IF3 ADC Source", rt5677_if3_adc_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(
|
||||
rt5677_if4_adc_enum, RT5677_IF4_DATA,
|
||||
RT5677_IF4_ADC_IN_SFT, rt5677_if34_adc_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5677_if4_adc_mux =
|
||||
SOC_DAPM_ENUM("IF4 ADC source", rt5677_if4_adc_enum);
|
||||
SOC_DAPM_ENUM("IF4 ADC Source", rt5677_if4_adc_enum);
|
||||
|
||||
static int rt5677_bst1_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
|
@ -1670,6 +1657,13 @@ static int rt5677_set_micbias1_event(struct snd_soc_dapm_widget *w,
|
|||
RT5677_PWR_CLK_MB, RT5677_PWR_CLK_MB1 |
|
||||
RT5677_PWR_PP_MB1 | RT5677_PWR_CLK_MB);
|
||||
break;
|
||||
|
||||
case SND_SOC_DAPM_PRE_PMD:
|
||||
regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2,
|
||||
RT5677_PWR_CLK_MB1 | RT5677_PWR_PP_MB1 |
|
||||
RT5677_PWR_CLK_MB, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -1685,8 +1679,9 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = {
|
|||
|
||||
/* Input Side */
|
||||
/* micbias */
|
||||
SND_SOC_DAPM_SUPPLY("micbias1", RT5677_PWR_ANLG2, RT5677_PWR_MB1_BIT,
|
||||
0, rt5677_set_micbias1_event, SND_SOC_DAPM_POST_PMU),
|
||||
SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5677_PWR_ANLG2, RT5677_PWR_MB1_BIT,
|
||||
0, rt5677_set_micbias1_event, SND_SOC_DAPM_PRE_PMD |
|
||||
SND_SOC_DAPM_POST_PMU),
|
||||
|
||||
/* Input Lines */
|
||||
SND_SOC_DAPM_INPUT("DMIC L1"),
|
||||
|
@ -2798,21 +2793,6 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = {
|
|||
{ "PDM2R", NULL, "PDM2 R Mux" },
|
||||
};
|
||||
|
||||
static int get_clk_info(int sclk, int rate)
|
||||
{
|
||||
int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
|
||||
|
||||
if (sclk <= 0 || rate <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
rate = rate << 8;
|
||||
for (i = 0; i < ARRAY_SIZE(pd); i++)
|
||||
if (sclk == rate * pd[i])
|
||||
return i;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int rt5677_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
|
||||
{
|
||||
|
@ -2822,7 +2802,7 @@ static int rt5677_hw_params(struct snd_pcm_substream *substream,
|
|||
int pre_div, bclk_ms, frame_size;
|
||||
|
||||
rt5677->lrck[dai->id] = params_rate(params);
|
||||
pre_div = get_clk_info(rt5677->sysclk, rt5677->lrck[dai->id]);
|
||||
pre_div = rl6231_get_clk_info(rt5677->sysclk, rt5677->lrck[dai->id]);
|
||||
if (pre_div < 0) {
|
||||
dev_err(codec->dev, "Unsupported clock setting\n");
|
||||
return -EINVAL;
|
||||
|
@ -3016,62 +2996,12 @@ static int rt5677_set_dai_sysclk(struct snd_soc_dai *dai,
|
|||
* Returns 0 for success or negative error code.
|
||||
*/
|
||||
static int rt5677_pll_calc(const unsigned int freq_in,
|
||||
const unsigned int freq_out, struct rt5677_pll_code *pll_code)
|
||||
const unsigned int freq_out, struct rl6231_pll_code *pll_code)
|
||||
{
|
||||
int max_n = RT5677_PLL_N_MAX, max_m = RT5677_PLL_M_MAX;
|
||||
int k, red, n_t, pll_out, in_t;
|
||||
int n = 0, m = 0, m_t = 0;
|
||||
int out_t, red_t = abs(freq_out - freq_in);
|
||||
bool m_bp = false, k_bp = false;
|
||||
|
||||
if (RT5677_PLL_INP_MAX < freq_in || RT5677_PLL_INP_MIN > freq_in)
|
||||
if (RT5677_PLL_INP_MIN > freq_in)
|
||||
return -EINVAL;
|
||||
|
||||
k = 100000000 / freq_out - 2;
|
||||
if (k > RT5677_PLL_K_MAX)
|
||||
k = RT5677_PLL_K_MAX;
|
||||
for (n_t = 0; n_t <= max_n; n_t++) {
|
||||
in_t = freq_in / (k + 2);
|
||||
pll_out = freq_out / (n_t + 2);
|
||||
if (in_t < 0)
|
||||
continue;
|
||||
if (in_t == pll_out) {
|
||||
m_bp = true;
|
||||
n = n_t;
|
||||
goto code_find;
|
||||
}
|
||||
red = abs(in_t - pll_out);
|
||||
if (red < red_t) {
|
||||
m_bp = true;
|
||||
n = n_t;
|
||||
m = m_t;
|
||||
if (red == 0)
|
||||
goto code_find;
|
||||
red_t = red;
|
||||
}
|
||||
for (m_t = 0; m_t <= max_m; m_t++) {
|
||||
out_t = in_t / (m_t + 2);
|
||||
red = abs(out_t - pll_out);
|
||||
if (red < red_t) {
|
||||
m_bp = false;
|
||||
n = n_t;
|
||||
m = m_t;
|
||||
if (red == 0)
|
||||
goto code_find;
|
||||
red_t = red;
|
||||
}
|
||||
}
|
||||
}
|
||||
pr_debug("Only get approximation about PLL\n");
|
||||
|
||||
code_find:
|
||||
|
||||
pll_code->m_bp = m_bp;
|
||||
pll_code->k_bp = k_bp;
|
||||
pll_code->m_code = m;
|
||||
pll_code->n_code = n;
|
||||
pll_code->k_code = k;
|
||||
return 0;
|
||||
return rl6231_pll_calc(freq_in, freq_out, pll_code);
|
||||
}
|
||||
|
||||
static int rt5677_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
|
||||
|
@ -3079,7 +3009,7 @@ static int rt5677_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
|
|||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
|
||||
struct rt5677_pll_code pll_code;
|
||||
struct rl6231_pll_code pll_code;
|
||||
int ret;
|
||||
|
||||
if (source == rt5677->pll_src && freq_in == rt5677->pll_in &&
|
||||
|
@ -3137,15 +3067,12 @@ static int rt5677_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
|
|||
return ret;
|
||||
}
|
||||
|
||||
dev_dbg(codec->dev, "m_bypass=%d k_bypass=%d m=%d n=%d k=%d\n",
|
||||
pll_code.m_bp, pll_code.k_bp,
|
||||
(pll_code.m_bp ? 0 : pll_code.m_code), pll_code.n_code,
|
||||
(pll_code.k_bp ? 0 : pll_code.k_code));
|
||||
dev_dbg(codec->dev, "m_bypass=%d m=%d n=%d k=%d\n",
|
||||
pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
|
||||
pll_code.n_code, pll_code.k_code);
|
||||
|
||||
regmap_write(rt5677->regmap, RT5677_PLL1_CTRL1,
|
||||
pll_code.n_code << RT5677_PLL_N_SFT |
|
||||
pll_code.k_bp << RT5677_PLL_K_BP_SFT |
|
||||
(pll_code.k_bp ? 0 : pll_code.k_code));
|
||||
pll_code.n_code << RT5677_PLL_N_SFT | pll_code.k_code);
|
||||
regmap_write(rt5677->regmap, RT5677_PLL1_CTRL2,
|
||||
(pll_code.m_bp ? 0 : pll_code.m_code) << RT5677_PLL_M_SFT |
|
||||
pll_code.m_bp << RT5677_PLL_M_BP_SFT);
|
||||
|
@ -3197,7 +3124,7 @@ static int rt5677_set_bias_level(struct snd_soc_codec *codec,
|
|||
regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x1, 0x0);
|
||||
regmap_write(rt5677->regmap, RT5677_PWR_DIG1, 0x0000);
|
||||
regmap_write(rt5677->regmap, RT5677_PWR_DIG2, 0x0000);
|
||||
regmap_write(rt5677->regmap, RT5677_PWR_ANLG1, 0x0000);
|
||||
regmap_write(rt5677->regmap, RT5677_PWR_ANLG1, 0x0022);
|
||||
regmap_write(rt5677->regmap, RT5677_PWR_ANLG2, 0x0000);
|
||||
regmap_update_bits(rt5677->regmap,
|
||||
RT5677_PR_BASE + RT5677_BIAS_CUR4, 0x0f00, 0x0000);
|
||||
|
@ -3454,14 +3381,8 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
|
|||
regmap_update_bits(rt5677->regmap, RT5677_IN1,
|
||||
RT5677_IN_DF2, RT5677_IN_DF2);
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677,
|
||||
rt5677_dai, ARRAY_SIZE(rt5677_dai));
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
return ret;
|
||||
return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677,
|
||||
rt5677_dai, ARRAY_SIZE(rt5677_dai));
|
||||
}
|
||||
|
||||
static int rt5677_i2c_remove(struct i2c_client *i2c)
|
||||
|
@ -3480,18 +3401,7 @@ static struct i2c_driver rt5677_i2c_driver = {
|
|||
.remove = rt5677_i2c_remove,
|
||||
.id_table = rt5677_i2c_id,
|
||||
};
|
||||
|
||||
static int __init rt5677_modinit(void)
|
||||
{
|
||||
return i2c_add_driver(&rt5677_i2c_driver);
|
||||
}
|
||||
module_init(rt5677_modinit);
|
||||
|
||||
static void __exit rt5677_modexit(void)
|
||||
{
|
||||
i2c_del_driver(&rt5677_i2c_driver);
|
||||
}
|
||||
module_exit(rt5677_modexit);
|
||||
module_i2c_driver(rt5677_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC RT5677 driver");
|
||||
MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>");
|
||||
|
|
|
@ -1393,13 +1393,6 @@
|
|||
#define RT5677_DSP_IB_9_L (0x1 << 1)
|
||||
#define RT5677_DSP_IB_9_L_SFT 1
|
||||
|
||||
/* Debug String Length */
|
||||
#define RT5677_REG_DISP_LEN 23
|
||||
|
||||
#define RT5677_NO_JACK BIT(0)
|
||||
#define RT5677_HEADSET_DET BIT(1)
|
||||
#define RT5677_HEADPHO_DET BIT(2)
|
||||
|
||||
/* System Clock Source */
|
||||
enum {
|
||||
RT5677_SCLK_S_MCLK,
|
||||
|
@ -1425,14 +1418,6 @@ enum {
|
|||
RT5677_AIFS,
|
||||
};
|
||||
|
||||
struct rt5677_pll_code {
|
||||
bool m_bp; /* Indicates bypass m code or not. */
|
||||
bool k_bp; /* Indicates bypass k code or not. */
|
||||
int m_code;
|
||||
int n_code;
|
||||
int k_code;
|
||||
};
|
||||
|
||||
struct rt5677_priv {
|
||||
struct snd_soc_codec *codec;
|
||||
struct rt5677_platform_data pdata;
|
||||
|
|
|
@ -724,25 +724,25 @@ static int sgtl5000_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
return ret;
|
||||
|
||||
/* set i2s data format */
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
if (sgtl5000->fmt == SND_SOC_DAIFMT_RIGHT_J)
|
||||
return -EINVAL;
|
||||
i2s_ctl |= SGTL5000_I2S_DLEN_16 << SGTL5000_I2S_DLEN_SHIFT;
|
||||
i2s_ctl |= SGTL5000_I2S_SCLKFREQ_32FS <<
|
||||
SGTL5000_I2S_SCLKFREQ_SHIFT;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S20_3LE:
|
||||
case 20:
|
||||
i2s_ctl |= SGTL5000_I2S_DLEN_20 << SGTL5000_I2S_DLEN_SHIFT;
|
||||
i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS <<
|
||||
SGTL5000_I2S_SCLKFREQ_SHIFT;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
case 24:
|
||||
i2s_ctl |= SGTL5000_I2S_DLEN_24 << SGTL5000_I2S_DLEN_SHIFT;
|
||||
i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS <<
|
||||
SGTL5000_I2S_SCLKFREQ_SHIFT;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
case 32:
|
||||
if (sgtl5000->fmt == SND_SOC_DAIFMT_RIGHT_J)
|
||||
return -EINVAL;
|
||||
i2s_ctl |= SGTL5000_I2S_DLEN_32 << SGTL5000_I2S_DLEN_SHIFT;
|
||||
|
@ -843,10 +843,8 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
|
|||
|
||||
ldo = kzalloc(sizeof(struct ldo_regulator), GFP_KERNEL);
|
||||
|
||||
if (!ldo) {
|
||||
dev_err(codec->dev, "failed to allocate ldo_regulator\n");
|
||||
if (!ldo)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ldo->desc.name = kstrdup(dev_name(codec->dev), GFP_KERNEL);
|
||||
if (!ldo->desc.name) {
|
||||
|
|
|
@ -167,17 +167,17 @@ static int si476x_codec_hw_params(struct snd_pcm_substream *substream,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S8:
|
||||
switch (params_width(params)) {
|
||||
case 8:
|
||||
width = SI476X_PCM_FORMAT_S8;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
case 16:
|
||||
width = SI476X_PCM_FORMAT_S16_LE;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S20_3LE:
|
||||
case 20:
|
||||
width = SI476X_PCM_FORMAT_S20_3LE;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
case 24:
|
||||
width = SI476X_PCM_FORMAT_S24_LE;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -471,8 +471,8 @@ static int sirf_audio_codec_driver_probe(struct platform_device *pdev)
|
|||
|
||||
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(&pdev->dev, mem_res);
|
||||
if (base == NULL)
|
||||
return -ENOMEM;
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
sirf_audio_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
|
||||
&sirf_audio_codec_regmap_config);
|
||||
|
|
|
@ -661,12 +661,12 @@ static int sn95031_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
{
|
||||
unsigned int format, rate;
|
||||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
format = BIT(4)|BIT(5);
|
||||
break;
|
||||
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
case 24:
|
||||
format = 0;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
#define DRV_NAME "spdif-dit"
|
||||
|
||||
#define STUB_RATES SNDRV_PCM_RATE_8000_96000
|
||||
#define STUB_RATES SNDRV_PCM_RATE_8000_192000
|
||||
#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
|
||||
SNDRV_PCM_FMTBIT_S20_3LE | \
|
||||
SNDRV_PCM_FMTBIT_S24_LE)
|
||||
|
|
|
@ -361,11 +361,11 @@ static int ssm2518_hw_params(struct snd_pcm_substream *substream,
|
|||
return -EINVAL;
|
||||
|
||||
if (ssm2518->right_j) {
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_16BIT;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
case 24:
|
||||
ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_24BIT;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -275,17 +275,17 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,
|
|||
regmap_write(ssm2602->regmap, SSM2602_SRATE, srate);
|
||||
|
||||
/* bit size */
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
iface = 0x0;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S20_3LE:
|
||||
case 20:
|
||||
iface = 0x4;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
case 24:
|
||||
iface = 0x8;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
case 32:
|
||||
iface = 0xc;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -678,15 +678,11 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream,
|
|||
|
||||
confb = snd_soc_read(codec, STA32X_CONFB);
|
||||
confb &= ~(STA32X_CONFB_SAI_MASK | STA32X_CONFB_SAIFB);
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
case SNDRV_PCM_FORMAT_S24_BE:
|
||||
case SNDRV_PCM_FORMAT_S24_3LE:
|
||||
case SNDRV_PCM_FORMAT_S24_3BE:
|
||||
switch (params_width(params)) {
|
||||
case 24:
|
||||
pr_debug("24bit\n");
|
||||
/* fall through */
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
case SNDRV_PCM_FORMAT_S32_BE:
|
||||
case 32:
|
||||
pr_debug("24bit or 32bit\n");
|
||||
switch (sta32x->format) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
|
@ -701,8 +697,7 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream,
|
|||
}
|
||||
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S20_3LE:
|
||||
case SNDRV_PCM_FORMAT_S20_3BE:
|
||||
case 20:
|
||||
pr_debug("20bit\n");
|
||||
switch (sta32x->format) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
|
@ -717,8 +712,7 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream,
|
|||
}
|
||||
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S18_3LE:
|
||||
case SNDRV_PCM_FORMAT_S18_3BE:
|
||||
case 18:
|
||||
pr_debug("18bit\n");
|
||||
switch (sta32x->format) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
|
@ -733,8 +727,7 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream,
|
|||
}
|
||||
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
case SNDRV_PCM_FORMAT_S16_BE:
|
||||
case 16:
|
||||
pr_debug("16bit\n");
|
||||
switch (sta32x->format) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
|
|
|
@ -197,16 +197,16 @@ static int sta529_hw_params(struct snd_pcm_substream *substream,
|
|||
int pdata, play_freq_val, record_freq_val;
|
||||
int bclk_to_fs_ratio;
|
||||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
pdata = 1;
|
||||
bclk_to_fs_ratio = 0;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
case 24:
|
||||
pdata = 2;
|
||||
bclk_to_fs_ratio = 1;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
case 32:
|
||||
pdata = 3;
|
||||
bclk_to_fs_ratio = 2;
|
||||
break;
|
||||
|
@ -380,10 +380,8 @@ static int sta529_i2c_probe(struct i2c_client *i2c,
|
|||
return -EINVAL;
|
||||
|
||||
sta529 = devm_kzalloc(&i2c->dev, sizeof(struct sta529), GFP_KERNEL);
|
||||
if (sta529 == NULL) {
|
||||
dev_err(&i2c->dev, "Can not allocate memory\n");
|
||||
if (!sta529)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
sta529->regmap = devm_regmap_init_i2c(i2c, &sta529_regmap);
|
||||
if (IS_ERR(sta529->regmap)) {
|
||||
|
|
|
@ -0,0 +1,544 @@
|
|||
/*
|
||||
* tas2552.c - ALSA SoC Texas Instruments TAS2552 Mono Audio Amplifier
|
||||
*
|
||||
* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
|
||||
*
|
||||
* Author: Dan Murphy <dmurphy@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <sound/tas2552-plat.h>
|
||||
|
||||
#include "tas2552.h"
|
||||
|
||||
static struct reg_default tas2552_reg_defs[] = {
|
||||
{TAS2552_CFG_1, 0x22},
|
||||
{TAS2552_CFG_3, 0x80},
|
||||
{TAS2552_DOUT, 0x00},
|
||||
{TAS2552_OUTPUT_DATA, 0xc0},
|
||||
{TAS2552_PDM_CFG, 0x01},
|
||||
{TAS2552_PGA_GAIN, 0x00},
|
||||
{TAS2552_BOOST_PT_CTRL, 0x0f},
|
||||
{TAS2552_RESERVED_0D, 0x00},
|
||||
{TAS2552_LIMIT_RATE_HYS, 0x08},
|
||||
{TAS2552_CFG_2, 0xef},
|
||||
{TAS2552_SER_CTRL_1, 0x00},
|
||||
{TAS2552_SER_CTRL_2, 0x00},
|
||||
{TAS2552_PLL_CTRL_1, 0x10},
|
||||
{TAS2552_PLL_CTRL_2, 0x00},
|
||||
{TAS2552_PLL_CTRL_3, 0x00},
|
||||
{TAS2552_BTIP, 0x8f},
|
||||
{TAS2552_BTS_CTRL, 0x80},
|
||||
{TAS2552_LIMIT_RELEASE, 0x04},
|
||||
{TAS2552_LIMIT_INT_COUNT, 0x00},
|
||||
{TAS2552_EDGE_RATE_CTRL, 0x40},
|
||||
{TAS2552_VBAT_DATA, 0x00},
|
||||
};
|
||||
|
||||
#define TAS2552_NUM_SUPPLIES 3
|
||||
static const char *tas2552_supply_names[TAS2552_NUM_SUPPLIES] = {
|
||||
"vbat", /* vbat voltage */
|
||||
"iovdd", /* I/O Voltage */
|
||||
"avdd", /* Analog DAC Voltage */
|
||||
};
|
||||
|
||||
struct tas2552_data {
|
||||
struct snd_soc_codec *codec;
|
||||
struct regmap *regmap;
|
||||
struct i2c_client *tas2552_client;
|
||||
struct regulator_bulk_data supplies[TAS2552_NUM_SUPPLIES];
|
||||
struct gpio_desc *enable_gpio;
|
||||
unsigned char regs[TAS2552_VBAT_DATA];
|
||||
unsigned int mclk;
|
||||
};
|
||||
|
||||
static void tas2552_sw_shutdown(struct tas2552_data *tas_data, int sw_shutdown)
|
||||
{
|
||||
u8 cfg1_reg;
|
||||
|
||||
if (sw_shutdown)
|
||||
cfg1_reg = 0;
|
||||
else
|
||||
cfg1_reg = TAS2552_SWS_MASK;
|
||||
|
||||
snd_soc_update_bits(tas_data->codec, TAS2552_CFG_1,
|
||||
TAS2552_SWS_MASK, cfg1_reg);
|
||||
}
|
||||
|
||||
static int tas2552_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 tas2552_data *tas2552 = dev_get_drvdata(codec->dev);
|
||||
int sample_rate, pll_clk;
|
||||
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;
|
||||
|
||||
snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, 0);
|
||||
|
||||
if (tas2552->mclk == TAS2552_245MHZ_CLK ||
|
||||
tas2552->mclk == TAS2552_225MHZ_CLK) {
|
||||
/* By pass the PLL configuration */
|
||||
snd_soc_update_bits(codec, TAS2552_PLL_CTRL_2,
|
||||
TAS2552_PLL_BYPASS_MASK,
|
||||
TAS2552_PLL_BYPASS);
|
||||
} else {
|
||||
/* Fill in the PLL control registers for J & D
|
||||
* PLL_CLK = (.5 * freq * J.D) / 2^p
|
||||
* Need to fill in J and D here based on incoming freq
|
||||
*/
|
||||
p = snd_soc_read(codec, TAS2552_PLL_CTRL_1);
|
||||
p = (p >> 7);
|
||||
sample_rate = params_rate(params);
|
||||
|
||||
if (sample_rate == 48000)
|
||||
pll_clk = TAS2552_245MHZ_CLK;
|
||||
else if (sample_rate == 44100)
|
||||
pll_clk = TAS2552_225MHZ_CLK;
|
||||
else {
|
||||
dev_vdbg(codec->dev, "Substream sample rate is not found %i\n",
|
||||
params_rate(params));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
j = (pll_clk * 2 * (1 << p)) / tas2552->mclk;
|
||||
d = (pll_clk * 2 * (1 << p)) % tas2552->mclk;
|
||||
|
||||
snd_soc_update_bits(codec, TAS2552_PLL_CTRL_1,
|
||||
TAS2552_PLL_J_MASK, j);
|
||||
snd_soc_write(codec, TAS2552_PLL_CTRL_2,
|
||||
(d >> 7) & TAS2552_PLL_D_UPPER_MASK);
|
||||
snd_soc_write(codec, TAS2552_PLL_CTRL_3,
|
||||
d & TAS2552_PLL_D_LOWER_MASK);
|
||||
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE,
|
||||
TAS2552_PLL_ENABLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tas2552_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
u8 serial_format;
|
||||
u8 serial_control_mask;
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
serial_format = 0x00;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBS_CFM:
|
||||
serial_format = TAS2552_WORD_CLK_MASK;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBM_CFS:
|
||||
serial_format = TAS2552_BIT_CLK_MASK;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
serial_format = (TAS2552_BIT_CLK_MASK | TAS2552_WORD_CLK_MASK);
|
||||
break;
|
||||
default:
|
||||
dev_vdbg(codec->dev, "DAI Format master is not found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
serial_control_mask = TAS2552_BIT_CLK_MASK | TAS2552_WORD_CLK_MASK;
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
serial_format &= TAS2552_DAIFMT_I2S_MASK;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
serial_format |= TAS2552_DAIFMT_DSP;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
serial_format |= TAS2552_DAIFMT_RIGHT_J;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
serial_format |= TAS2552_DAIFMT_LEFT_J;
|
||||
break;
|
||||
default:
|
||||
dev_vdbg(codec->dev, "DAI Format is not found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (fmt & SND_SOC_DAIFMT_FORMAT_MASK)
|
||||
serial_control_mask |= TAS2552_DATA_FORMAT_MASK;
|
||||
|
||||
snd_soc_update_bits(codec, TAS2552_SER_CTRL_1, serial_control_mask,
|
||||
serial_format);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tas2552_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
|
||||
unsigned int freq, int dir)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev);
|
||||
|
||||
tas2552->mclk = freq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tas2552_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
u8 cfg1_reg;
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
|
||||
if (mute)
|
||||
cfg1_reg = TAS2552_MUTE_MASK;
|
||||
else
|
||||
cfg1_reg = ~TAS2552_MUTE_MASK;
|
||||
|
||||
snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_MUTE_MASK, cfg1_reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
static int tas2552_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct tas2552_data *tas2552 = dev_get_drvdata(dev);
|
||||
|
||||
tas2552_sw_shutdown(tas2552, 0);
|
||||
|
||||
regcache_cache_only(tas2552->regmap, true);
|
||||
regcache_mark_dirty(tas2552->regmap);
|
||||
|
||||
if (tas2552->enable_gpio)
|
||||
gpiod_set_value(tas2552->enable_gpio, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tas2552_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct tas2552_data *tas2552 = dev_get_drvdata(dev);
|
||||
|
||||
if (tas2552->enable_gpio)
|
||||
gpiod_set_value(tas2552->enable_gpio, 1);
|
||||
|
||||
tas2552_sw_shutdown(tas2552, 1);
|
||||
|
||||
regcache_cache_only(tas2552->regmap, false);
|
||||
regcache_sync(tas2552->regmap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops tas2552_pm = {
|
||||
SET_RUNTIME_PM_OPS(tas2552_runtime_suspend, tas2552_runtime_resume,
|
||||
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,
|
||||
};
|
||||
|
||||
/* Formats supported by TAS2552 driver. */
|
||||
#define TAS2552_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
|
||||
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
|
||||
|
||||
/* TAS2552 dai structure. */
|
||||
static struct snd_soc_dai_driver tas2552_dai[] = {
|
||||
{
|
||||
.name = "tas2552-amplifier",
|
||||
.playback = {
|
||||
.stream_name = "Speaker",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_8000_192000,
|
||||
.formats = TAS2552_FORMATS,
|
||||
},
|
||||
.ops = &tas2552_speaker_dai_ops,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* DAC digital volumes. From -7 to 24 dB in 1 dB steps
|
||||
*/
|
||||
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),
|
||||
};
|
||||
|
||||
static const struct reg_default tas2552_init_regs[] = {
|
||||
{ TAS2552_RESERVED_0D, 0xc0 },
|
||||
};
|
||||
|
||||
static int tas2552_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
tas2552->codec = codec;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(tas2552->supplies),
|
||||
tas2552->supplies);
|
||||
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to enable supplies: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (tas2552->enable_gpio)
|
||||
gpiod_set_value(tas2552->enable_gpio, 1);
|
||||
|
||||
ret = pm_runtime_get_sync(codec->dev);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Enabling device failed: %d\n",
|
||||
ret);
|
||||
goto probe_fail;
|
||||
}
|
||||
|
||||
snd_soc_write(codec, TAS2552_CFG_1, TAS2552_MUTE_MASK |
|
||||
TAS2552_PLL_SRC_BCLK);
|
||||
snd_soc_write(codec, TAS2552_CFG_3, TAS2552_I2S_OUT_SEL |
|
||||
TAS2552_DIN_SRC_SEL_AVG_L_R | TAS2552_88_96KHZ);
|
||||
snd_soc_write(codec, TAS2552_DOUT, TAS2552_PDM_DATA_I);
|
||||
snd_soc_write(codec, TAS2552_OUTPUT_DATA, TAS2552_PDM_DATA_V_I | 0x8);
|
||||
snd_soc_write(codec, TAS2552_PDM_CFG, TAS2552_PDM_BCLK_SEL);
|
||||
snd_soc_write(codec, TAS2552_BOOST_PT_CTRL, TAS2552_APT_DELAY_200 |
|
||||
TAS2552_APT_THRESH_2_1_7);
|
||||
|
||||
ret = regmap_register_patch(tas2552->regmap, tas2552_init_regs,
|
||||
ARRAY_SIZE(tas2552_init_regs));
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to write init registers: %d\n",
|
||||
ret);
|
||||
goto patch_fail;
|
||||
}
|
||||
|
||||
snd_soc_write(codec, TAS2552_CFG_2, TAS2552_CLASSD_EN |
|
||||
TAS2552_BOOST_EN | TAS2552_APT_EN |
|
||||
TAS2552_LIM_EN);
|
||||
return 0;
|
||||
|
||||
patch_fail:
|
||||
pm_runtime_put(codec->dev);
|
||||
probe_fail:
|
||||
if (tas2552->enable_gpio)
|
||||
gpiod_set_value(tas2552->enable_gpio, 0);
|
||||
|
||||
regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies),
|
||||
tas2552->supplies);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int tas2552_codec_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
pm_runtime_put(codec->dev);
|
||||
|
||||
if (tas2552->enable_gpio)
|
||||
gpiod_set_value(tas2552->enable_gpio, 0);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int tas2552_suspend(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
ret = regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies),
|
||||
tas2552->supplies);
|
||||
|
||||
if (ret != 0)
|
||||
dev_err(codec->dev, "Failed to disable supplies: %d\n",
|
||||
ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tas2552_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(tas2552->supplies),
|
||||
tas2552->supplies);
|
||||
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to enable supplies: %d\n",
|
||||
ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define tas2552_suspend NULL
|
||||
#define tas2552_resume NULL
|
||||
#endif
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_tas2552 = {
|
||||
.probe = tas2552_codec_probe,
|
||||
.remove = tas2552_codec_remove,
|
||||
.suspend = tas2552_suspend,
|
||||
.resume = tas2552_resume,
|
||||
.controls = tas2552_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(tas2552_snd_controls),
|
||||
};
|
||||
|
||||
static const struct regmap_config tas2552_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
||||
.max_register = TAS2552_MAX_REG,
|
||||
.reg_defaults = tas2552_reg_defs,
|
||||
.num_reg_defaults = ARRAY_SIZE(tas2552_reg_defs),
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static int tas2552_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct device *dev;
|
||||
struct tas2552_data *data;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
dev = &client->dev;
|
||||
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (data == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
data->enable_gpio = devm_gpiod_get(dev, "enable");
|
||||
if (IS_ERR(data->enable_gpio)) {
|
||||
ret = PTR_ERR(data->enable_gpio);
|
||||
if (ret != -ENOENT && ret != -ENOSYS)
|
||||
return ret;
|
||||
|
||||
data->enable_gpio = NULL;
|
||||
} else {
|
||||
gpiod_direction_output(data->enable_gpio, 0);
|
||||
}
|
||||
|
||||
data->tas2552_client = client;
|
||||
data->regmap = devm_regmap_init_i2c(client, &tas2552_regmap_config);
|
||||
if (IS_ERR(data->regmap)) {
|
||||
ret = PTR_ERR(data->regmap);
|
||||
dev_err(&client->dev, "Failed to allocate register map: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(data->supplies); i++)
|
||||
data->supplies[i].supply = tas2552_supply_names[i];
|
||||
|
||||
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->supplies),
|
||||
data->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "Failed to request supplies: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pm_runtime_set_active(&client->dev);
|
||||
pm_runtime_set_autosuspend_delay(&client->dev, 1000);
|
||||
pm_runtime_use_autosuspend(&client->dev);
|
||||
pm_runtime_enable(&client->dev);
|
||||
pm_runtime_mark_last_busy(&client->dev);
|
||||
pm_runtime_put_sync_autosuspend(&client->dev);
|
||||
|
||||
dev_set_drvdata(&client->dev, data);
|
||||
|
||||
ret = snd_soc_register_codec(&client->dev,
|
||||
&soc_codec_dev_tas2552,
|
||||
tas2552_dai, ARRAY_SIZE(tas2552_dai));
|
||||
if (ret < 0)
|
||||
dev_err(&client->dev, "Failed to register codec: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas2552_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id tas2552_id[] = {
|
||||
{ "tas2552", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tas2552_id);
|
||||
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
static const struct of_device_id tas2552_of_match[] = {
|
||||
{ .compatible = "ti,tas2552", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tas2552_of_match);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver tas2552_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "tas2552",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(tas2552_of_match),
|
||||
.pm = &tas2552_pm,
|
||||
},
|
||||
.probe = tas2552_probe,
|
||||
.remove = tas2552_i2c_remove,
|
||||
.id_table = tas2552_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(tas2552_i2c_driver);
|
||||
|
||||
MODULE_AUTHOR("Dan Muprhy <dmurphy@ti.com>");
|
||||
MODULE_DESCRIPTION("TAS2552 Audio amplifier driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* tas2552.h - ALSA SoC Texas Instruments TAS2552 Mono Audio Amplifier
|
||||
*
|
||||
* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
|
||||
*
|
||||
* Author: Dan Murphy <dmurphy@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __TAS2552_H__
|
||||
#define __TAS2552_H__
|
||||
|
||||
/* Register Address Map */
|
||||
#define TAS2552_DEVICE_STATUS 0x00
|
||||
#define TAS2552_CFG_1 0x01
|
||||
#define TAS2552_CFG_2 0x02
|
||||
#define TAS2552_CFG_3 0x03
|
||||
#define TAS2552_DOUT 0x04
|
||||
#define TAS2552_SER_CTRL_1 0x05
|
||||
#define TAS2552_SER_CTRL_2 0x06
|
||||
#define TAS2552_OUTPUT_DATA 0x07
|
||||
#define TAS2552_PLL_CTRL_1 0x08
|
||||
#define TAS2552_PLL_CTRL_2 0x09
|
||||
#define TAS2552_PLL_CTRL_3 0x0a
|
||||
#define TAS2552_BTIP 0x0b
|
||||
#define TAS2552_BTS_CTRL 0x0c
|
||||
#define TAS2552_RESERVED_0D 0x0d
|
||||
#define TAS2552_LIMIT_RATE_HYS 0x0e
|
||||
#define TAS2552_LIMIT_RELEASE 0x0f
|
||||
#define TAS2552_LIMIT_INT_COUNT 0x10
|
||||
#define TAS2552_PDM_CFG 0x11
|
||||
#define TAS2552_PGA_GAIN 0x12
|
||||
#define TAS2552_EDGE_RATE_CTRL 0x13
|
||||
#define TAS2552_BOOST_PT_CTRL 0x14
|
||||
#define TAS2552_VER_NUM 0x16
|
||||
#define TAS2552_VBAT_DATA 0x19
|
||||
#define TAS2552_MAX_REG 0x20
|
||||
|
||||
/* CFG1 Register Masks */
|
||||
#define TAS2552_MUTE_MASK (1 << 2)
|
||||
#define TAS2552_SWS_MASK (1 << 1)
|
||||
#define TAS2552_WCLK_MASK 0x07
|
||||
#define TAS2552_CLASSD_EN_MASK (1 << 7)
|
||||
|
||||
/* CFG2 Register Masks */
|
||||
#define TAS2552_CLASSD_EN (1 << 7)
|
||||
#define TAS2552_BOOST_EN (1 << 6)
|
||||
#define TAS2552_APT_EN (1 << 5)
|
||||
#define TAS2552_PLL_ENABLE (1 << 3)
|
||||
#define TAS2552_LIM_EN (1 << 2)
|
||||
#define TAS2552_IVSENSE_EN (1 << 1)
|
||||
|
||||
/* CFG3 Register Masks */
|
||||
#define TAS2552_WORD_CLK_MASK (1 << 7)
|
||||
#define TAS2552_BIT_CLK_MASK (1 << 6)
|
||||
#define TAS2552_DATA_FORMAT_MASK (0x11 << 2)
|
||||
|
||||
#define TAS2552_DAIFMT_I2S_MASK 0xf3
|
||||
#define TAS2552_DAIFMT_DSP (1 << 3)
|
||||
#define TAS2552_DAIFMT_RIGHT_J (1 << 4)
|
||||
#define TAS2552_DAIFMT_LEFT_J (0x11 << 3)
|
||||
|
||||
#define TAS2552_PLL_SRC_MCLK 0x00
|
||||
#define TAS2552_PLL_SRC_BCLK (1 << 3)
|
||||
#define TAS2552_PLL_SRC_IVCLKIN (1 << 4)
|
||||
#define TAS2552_PLL_SRC_1_8_FIXED (0x11 << 3)
|
||||
|
||||
#define TAS2552_DIN_SRC_SEL_MUTED 0x00
|
||||
#define TAS2552_DIN_SRC_SEL_LEFT (1 << 4)
|
||||
#define TAS2552_DIN_SRC_SEL_RIGHT (1 << 5)
|
||||
#define TAS2552_DIN_SRC_SEL_AVG_L_R (0x11 << 4)
|
||||
|
||||
#define TAS2552_PDM_IN_SEL (1 << 5)
|
||||
#define TAS2552_I2S_OUT_SEL (1 << 6)
|
||||
#define TAS2552_ANALOG_IN_SEL (1 << 7)
|
||||
|
||||
/* CFG3 WCLK Dividers */
|
||||
#define TAS2552_8KHZ 0x00
|
||||
#define TAS2552_11_12KHZ (1 << 1)
|
||||
#define TAS2552_16KHZ (1 << 2)
|
||||
#define TAS2552_22_24KHZ (1 << 3)
|
||||
#define TAS2552_32KHZ (1 << 4)
|
||||
#define TAS2552_44_48KHZ (1 << 5)
|
||||
#define TAS2552_88_96KHZ (1 << 6)
|
||||
#define TAS2552_176_192KHZ (1 << 7)
|
||||
|
||||
/* OUTPUT_DATA register */
|
||||
#define TAS2552_PDM_DATA_I 0x00
|
||||
#define TAS2552_PDM_DATA_V (1 << 6)
|
||||
#define TAS2552_PDM_DATA_I_V (1 << 7)
|
||||
#define TAS2552_PDM_DATA_V_I (0x11 << 6)
|
||||
|
||||
/* PDM CFG Register */
|
||||
#define TAS2552_PDM_DATA_ES_RISE 0x4
|
||||
|
||||
#define TAS2552_PDM_PLL_CLK_SEL 0x00
|
||||
#define TAS2552_PDM_IV_CLK_SEL (1 << 1)
|
||||
#define TAS2552_PDM_BCLK_SEL (1 << 2)
|
||||
#define TAS2552_PDM_MCLK_SEL (1 << 3)
|
||||
|
||||
/* Boost pass-through register */
|
||||
#define TAS2552_APT_DELAY_50 0x00
|
||||
#define TAS2552_APT_DELAY_75 (1 << 1)
|
||||
#define TAS2552_APT_DELAY_125 (1 << 2)
|
||||
#define TAS2552_APT_DELAY_200 (1 << 3)
|
||||
|
||||
#define TAS2552_APT_THRESH_2_5 0x00
|
||||
#define TAS2552_APT_THRESH_1_7 (1 << 3)
|
||||
#define TAS2552_APT_THRESH_1_4_1_1 (1 << 4)
|
||||
#define TAS2552_APT_THRESH_2_1_7 (0x11 << 2)
|
||||
|
||||
/* PLL Control Register */
|
||||
#define TAS2552_245MHZ_CLK 24576000
|
||||
#define TAS2552_225MHZ_CLK 22579200
|
||||
#define TAS2552_PLL_J_MASK 0x7f
|
||||
#define TAS2552_PLL_D_UPPER_MASK 0x3f
|
||||
#define TAS2552_PLL_D_LOWER_MASK 0xff
|
||||
#define TAS2552_PLL_BYPASS_MASK 0x80
|
||||
#define TAS2552_PLL_BYPASS 0x80
|
||||
|
||||
#endif
|
|
@ -36,6 +36,7 @@
|
|||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
@ -240,6 +241,10 @@ static int tas5086_reg_read(void *context, unsigned int reg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const char * const supply_names[] = {
|
||||
"dvdd", "avdd"
|
||||
};
|
||||
|
||||
struct tas5086_private {
|
||||
struct regmap *regmap;
|
||||
unsigned int mclk, sclk;
|
||||
|
@ -251,6 +256,7 @@ struct tas5086_private {
|
|||
int rate;
|
||||
/* GPIO driving Reset pin, if any */
|
||||
int gpio_nreset;
|
||||
struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
|
||||
};
|
||||
|
||||
static int tas5086_deemph[] = { 0, 32000, 44100, 48000 };
|
||||
|
@ -419,14 +425,14 @@ static int tas5086_hw_params(struct snd_pcm_substream *substream,
|
|||
}
|
||||
|
||||
/* ... then add the offset for the sample bit depth. */
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
val += 0;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S20_3LE:
|
||||
case 20:
|
||||
val += 1;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_3LE:
|
||||
case 24:
|
||||
val += 2;
|
||||
break;
|
||||
default:
|
||||
|
@ -773,6 +779,8 @@ static int tas5086_soc_suspend(struct snd_soc_codec *codec)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -781,6 +789,10 @@ static int tas5086_soc_resume(struct snd_soc_codec *codec)
|
|||
struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
tas5086_reset(priv);
|
||||
regcache_mark_dirty(priv->regmap);
|
||||
|
||||
|
@ -812,6 +824,12 @@ static int tas5086_probe(struct snd_soc_codec *codec)
|
|||
struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
int i, ret;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to enable regulators: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->pwm_start_mid_z = 0;
|
||||
priv->charge_period = 1300000; /* hardware default is 1300 ms */
|
||||
|
||||
|
@ -832,16 +850,22 @@ static int tas5086_probe(struct snd_soc_codec *codec)
|
|||
}
|
||||
}
|
||||
|
||||
tas5086_reset(priv);
|
||||
ret = tas5086_init(codec->dev, priv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto exit_disable_regulators;
|
||||
|
||||
/* set master volume to 0 dB */
|
||||
ret = regmap_write(priv->regmap, TAS5086_MASTER_VOL, 0x30);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto exit_disable_regulators;
|
||||
|
||||
return 0;
|
||||
|
||||
exit_disable_regulators:
|
||||
regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas5086_remove(struct snd_soc_codec *codec)
|
||||
|
@ -852,6 +876,8 @@ static int tas5086_remove(struct snd_soc_codec *codec)
|
|||
/* Set codec to the reset state */
|
||||
gpio_set_value(priv->gpio_nreset, 0);
|
||||
|
||||
regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
@ -900,6 +926,16 @@ static int tas5086_i2c_probe(struct i2c_client *i2c,
|
|||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(supply_names); i++)
|
||||
priv->supplies[i].supply = supply_names[i];
|
||||
|
||||
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(priv->supplies),
|
||||
priv->supplies);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to get regulators: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->regmap = devm_regmap_init(dev, NULL, i2c, &tas5086_regmap);
|
||||
if (IS_ERR(priv->regmap)) {
|
||||
ret = PTR_ERR(priv->regmap);
|
||||
|
@ -919,21 +955,34 @@ static int tas5086_i2c_probe(struct i2c_client *i2c,
|
|||
gpio_nreset = -EINVAL;
|
||||
|
||||
priv->gpio_nreset = gpio_nreset;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enable regulators: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
tas5086_reset(priv);
|
||||
|
||||
/* The TAS5086 always returns 0x03 in its TAS5086_DEV_ID register */
|
||||
ret = regmap_read(priv->regmap, TAS5086_DEV_ID, &i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (i != 0x3) {
|
||||
if (ret == 0 && i != 0x3) {
|
||||
dev_err(dev,
|
||||
"Failed to identify TAS5086 codec (got %02x)\n", i);
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
}
|
||||
|
||||
return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_tas5086,
|
||||
&tas5086_dai, 1);
|
||||
/*
|
||||
* The chip has been identified, so we can turn off the power
|
||||
* again until the dai link is set up.
|
||||
*/
|
||||
regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
|
||||
|
||||
if (ret == 0)
|
||||
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_tas5086,
|
||||
&tas5086_dai, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas5086_i2c_remove(struct i2c_client *i2c)
|
||||
|
|
|
@ -364,16 +364,16 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
|
|||
|
||||
iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
|
||||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S20_3LE:
|
||||
case 20:
|
||||
iface_reg |= (0x01 << 2);
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
case 24:
|
||||
iface_reg |= (0x02 << 2);
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
case 32:
|
||||
iface_reg |= (0x03 << 2);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -71,8 +71,8 @@ static int aic26_hw_params(struct snd_pcm_substream *substream,
|
|||
|
||||
dev_dbg(&aic26->spi->dev, "aic26_hw_params(substream=%p, params=%p)\n",
|
||||
substream, params);
|
||||
dev_dbg(&aic26->spi->dev, "rate=%i format=%i\n", params_rate(params),
|
||||
params_format(params));
|
||||
dev_dbg(&aic26->spi->dev, "rate=%i width=%d\n", params_rate(params),
|
||||
params_width(params));
|
||||
|
||||
switch (params_rate(params)) {
|
||||
case 8000: fsref = 48000; divisor = AIC26_DIV_6; break;
|
||||
|
@ -89,11 +89,11 @@ static int aic26_hw_params(struct snd_pcm_substream *substream,
|
|||
}
|
||||
|
||||
/* select data word length */
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S8: wlen = AIC26_WLEN_16; break;
|
||||
case SNDRV_PCM_FORMAT_S16_BE: wlen = AIC26_WLEN_16; break;
|
||||
case SNDRV_PCM_FORMAT_S24_BE: wlen = AIC26_WLEN_24; break;
|
||||
case SNDRV_PCM_FORMAT_S32_BE: wlen = AIC26_WLEN_32; break;
|
||||
switch (params_width(params)) {
|
||||
case 8: wlen = AIC26_WLEN_16; break;
|
||||
case 16: wlen = AIC26_WLEN_16; break;
|
||||
case 24: wlen = AIC26_WLEN_24; break;
|
||||
case 32: wlen = AIC26_WLEN_32; break;
|
||||
default:
|
||||
dev_dbg(&aic26->spi->dev, "bad format\n"); return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -249,17 +249,16 @@ static const char * const mic_select_text[] = {
|
|||
"Off", "FFR 10 Ohm", "FFR 20 Ohm", "FFR 40 Ohm"
|
||||
};
|
||||
|
||||
static const
|
||||
SOC_ENUM_SINGLE_DECL(mic1lp_p_enum, AIC31XX_MICPGAPI, 6, mic_select_text);
|
||||
static const
|
||||
SOC_ENUM_SINGLE_DECL(mic1rp_p_enum, AIC31XX_MICPGAPI, 4, mic_select_text);
|
||||
static const
|
||||
SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2, mic_select_text);
|
||||
static SOC_ENUM_SINGLE_DECL(mic1lp_p_enum, AIC31XX_MICPGAPI, 6,
|
||||
mic_select_text);
|
||||
static SOC_ENUM_SINGLE_DECL(mic1rp_p_enum, AIC31XX_MICPGAPI, 4,
|
||||
mic_select_text);
|
||||
static SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2,
|
||||
mic_select_text);
|
||||
|
||||
static const
|
||||
SOC_ENUM_SINGLE_DECL(cm_m_enum, AIC31XX_MICPGAMI, 6, mic_select_text);
|
||||
static const
|
||||
SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4, mic_select_text);
|
||||
static SOC_ENUM_SINGLE_DECL(cm_m_enum, AIC31XX_MICPGAMI, 6, mic_select_text);
|
||||
static SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4,
|
||||
mic_select_text);
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6350, 50, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(adc_fgain_tlv, 0, 10, 0);
|
||||
|
@ -329,6 +328,7 @@ static int aic31xx_wait_bits(struct aic31xx_priv *aic31xx, unsigned int reg,
|
|||
unsigned int bits;
|
||||
int counter = count;
|
||||
int ret = regmap_read(aic31xx->regmap, reg, &bits);
|
||||
|
||||
while ((bits & mask) != wbits && counter && !ret) {
|
||||
usleep_range(sleep, sleep * 2);
|
||||
ret = regmap_read(aic31xx->regmap, reg, &bits);
|
||||
|
@ -435,6 +435,7 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w,
|
|||
{
|
||||
struct snd_soc_codec *codec = w->codec;
|
||||
struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
/* change mic bias voltage to user defined */
|
||||
|
@ -759,8 +760,8 @@ static int aic31xx_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_soc_codec *codec = dai->codec;
|
||||
u8 data = 0;
|
||||
|
||||
dev_dbg(codec->dev, "## %s: format %d width %d rate %d\n",
|
||||
__func__, params_format(params), params_width(params),
|
||||
dev_dbg(codec->dev, "## %s: width %d rate %d\n",
|
||||
__func__, params_width(params),
|
||||
params_rate(params));
|
||||
|
||||
switch (params_width(params)) {
|
||||
|
@ -779,8 +780,8 @@ static int aic31xx_hw_params(struct snd_pcm_substream *substream,
|
|||
AIC31XX_IFACE1_DATALEN_SHIFT);
|
||||
break;
|
||||
default:
|
||||
dev_err(codec->dev, "%s: Unsupported format %d\n",
|
||||
__func__, params_format(params));
|
||||
dev_err(codec->dev, "%s: Unsupported width %d\n",
|
||||
__func__, params_width(params));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1178,7 +1179,7 @@ static void aic31xx_pdata_from_of(struct aic31xx_priv *aic31xx)
|
|||
}
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
static void aic31xx_device_init(struct aic31xx_priv *aic31xx)
|
||||
static int aic31xx_device_init(struct aic31xx_priv *aic31xx)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
|
@ -1197,7 +1198,7 @@ static void aic31xx_device_init(struct aic31xx_priv *aic31xx)
|
|||
"aic31xx-reset-pin");
|
||||
if (ret < 0) {
|
||||
dev_err(aic31xx->dev, "not able to acquire gpio\n");
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1210,6 +1211,7 @@ static void aic31xx_device_init(struct aic31xx_priv *aic31xx)
|
|||
if (ret != 0)
|
||||
dev_err(aic31xx->dev, "Failed to request supplies: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aic31xx_i2c_probe(struct i2c_client *i2c,
|
||||
|
@ -1239,7 +1241,9 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c,
|
|||
|
||||
aic31xx->pdata.codec_type = id->driver_data;
|
||||
|
||||
aic31xx_device_init(aic31xx);
|
||||
ret = aic31xx_device_init(aic31xx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return snd_soc_register_codec(&i2c->dev, &soc_codec_driver_aic31xx,
|
||||
aic31xx_dai_driver,
|
||||
|
|
|
@ -450,16 +450,16 @@ static int aic32x4_hw_params(struct snd_pcm_substream *substream,
|
|||
|
||||
data = snd_soc_read(codec, AIC32X4_IFACE1);
|
||||
data = data & ~(3 << 4);
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S20_3LE:
|
||||
case 20:
|
||||
data |= (AIC32X4_WORD_LEN_20BITS << AIC32X4_DOSRMSB_SHIFT);
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
case 24:
|
||||
data |= (AIC32X4_WORD_LEN_24BITS << AIC32X4_DOSRMSB_SHIFT);
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
case 32:
|
||||
data |= (AIC32X4_WORD_LEN_32BITS << AIC32X4_DOSRMSB_SHIFT);
|
||||
break;
|
||||
}
|
||||
|
@ -626,32 +626,33 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
|
|||
snd_soc_write(codec, AIC32X4_MICBIAS, AIC32X4_MICBIAS_LDOIN |
|
||||
AIC32X4_MICBIAS_2075V);
|
||||
}
|
||||
if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) {
|
||||
if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE)
|
||||
snd_soc_write(codec, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE);
|
||||
}
|
||||
|
||||
tmp_reg = (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) ?
|
||||
AIC32X4_LDOCTLEN : 0;
|
||||
snd_soc_write(codec, AIC32X4_LDOCTL, tmp_reg);
|
||||
|
||||
tmp_reg = snd_soc_read(codec, AIC32X4_CMMODE);
|
||||
if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) {
|
||||
if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36)
|
||||
tmp_reg |= AIC32X4_LDOIN_18_36;
|
||||
}
|
||||
if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED) {
|
||||
if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED)
|
||||
tmp_reg |= AIC32X4_LDOIN2HP;
|
||||
}
|
||||
snd_soc_write(codec, AIC32X4_CMMODE, tmp_reg);
|
||||
|
||||
/* Mic PGA routing */
|
||||
if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K)
|
||||
snd_soc_write(codec, AIC32X4_LMICPGANIN, AIC32X4_LMICPGANIN_IN2R_10K);
|
||||
snd_soc_write(codec, AIC32X4_LMICPGANIN,
|
||||
AIC32X4_LMICPGANIN_IN2R_10K);
|
||||
else
|
||||
snd_soc_write(codec, AIC32X4_LMICPGANIN, AIC32X4_LMICPGANIN_CM1L_10K);
|
||||
snd_soc_write(codec, AIC32X4_LMICPGANIN,
|
||||
AIC32X4_LMICPGANIN_CM1L_10K);
|
||||
if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K)
|
||||
snd_soc_write(codec, AIC32X4_RMICPGANIN, AIC32X4_RMICPGANIN_IN1L_10K);
|
||||
snd_soc_write(codec, AIC32X4_RMICPGANIN,
|
||||
AIC32X4_RMICPGANIN_IN1L_10K);
|
||||
else
|
||||
snd_soc_write(codec, AIC32X4_RMICPGANIN, AIC32X4_RMICPGANIN_CM1R_10K);
|
||||
snd_soc_write(codec, AIC32X4_RMICPGANIN,
|
||||
AIC32X4_RMICPGANIN_CM1R_10K);
|
||||
|
||||
aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
|
|
|
@ -873,16 +873,16 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
|
|||
|
||||
/* select data word length */
|
||||
data = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4));
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S20_3LE:
|
||||
case 20:
|
||||
data |= (0x01 << 4);
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_3LE:
|
||||
case 24:
|
||||
data |= (0x02 << 4);
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
case 32:
|
||||
data |= (0x03 << 4);
|
||||
break;
|
||||
}
|
||||
|
@ -1194,7 +1194,8 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
|
|||
|
||||
#define AIC3X_RATES SNDRV_PCM_RATE_8000_96000
|
||||
#define AIC3X_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)
|
||||
|
||||
static const struct snd_soc_dai_ops aic3x_dai_ops = {
|
||||
.hw_params = aic3x_hw_params,
|
||||
|
@ -1477,10 +1478,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
|
|||
u32 value;
|
||||
|
||||
aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL);
|
||||
if (aic3x == NULL) {
|
||||
dev_err(&i2c->dev, "failed to create private data\n");
|
||||
if (!aic3x)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
aic3x->regmap = devm_regmap_init_i2c(i2c, &aic3x_regmap);
|
||||
if (IS_ERR(aic3x->regmap)) {
|
||||
|
@ -1498,10 +1497,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
|
|||
} else if (np) {
|
||||
ai3x_setup = devm_kzalloc(&i2c->dev, sizeof(*ai3x_setup),
|
||||
GFP_KERNEL);
|
||||
if (ai3x_setup == NULL) {
|
||||
dev_err(&i2c->dev, "failed to create private data\n");
|
||||
if (!ai3x_setup)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = of_get_named_gpio(np, "gpio-reset", 0);
|
||||
if (ret >= 0)
|
||||
|
|
|
@ -832,18 +832,18 @@ static int dac33_hw_params(struct snd_pcm_substream *substream,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
dac33->fifo_size = DAC33_FIFO_SIZE_16BIT;
|
||||
dac33->burst_rate = CALC_BURST_RATE(dac33->burst_bclkdiv, 32);
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
case 32:
|
||||
dac33->fifo_size = DAC33_FIFO_SIZE_24BIT;
|
||||
dac33->burst_rate = CALC_BURST_RATE(dac33->burst_bclkdiv, 64);
|
||||
break;
|
||||
default:
|
||||
dev_err(codec->dev, "unsupported format %d\n",
|
||||
params_format(params));
|
||||
dev_err(codec->dev, "unsupported width %d\n",
|
||||
params_width(params));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1404,7 +1404,7 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
|
|||
if (dac33->irq >= 0) {
|
||||
ret = request_irq(dac33->irq, dac33_interrupt_handler,
|
||||
IRQF_TRIGGER_RISING,
|
||||
codec->name, codec);
|
||||
codec->component.name, codec);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Could not request IRQ%d (%d)\n",
|
||||
dac33->irq, ret);
|
||||
|
|
|
@ -381,10 +381,8 @@ static int tpa6130a2_probe(struct i2c_client *client,
|
|||
dev = &client->dev;
|
||||
|
||||
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (data == NULL) {
|
||||
dev_err(dev, "Can not allocate memory\n");
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (pdata) {
|
||||
data->power_gpio = pdata->power_gpio;
|
||||
|
|
|
@ -344,17 +344,16 @@ static void twl4030_init_chip(struct snd_soc_codec *codec)
|
|||
static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable)
|
||||
{
|
||||
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
|
||||
int status = -1;
|
||||
|
||||
if (enable) {
|
||||
twl4030->apll_enabled++;
|
||||
if (twl4030->apll_enabled == 1)
|
||||
status = twl4030_audio_enable_resource(
|
||||
twl4030_audio_enable_resource(
|
||||
TWL4030_AUDIO_RES_APLL);
|
||||
} else {
|
||||
twl4030->apll_enabled--;
|
||||
if (!twl4030->apll_enabled)
|
||||
status = twl4030_audio_disable_resource(
|
||||
twl4030_audio_disable_resource(
|
||||
TWL4030_AUDIO_RES_APLL);
|
||||
}
|
||||
}
|
||||
|
@ -1764,16 +1763,16 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
|
|||
old_format = twl4030_read(codec, TWL4030_REG_AUDIO_IF);
|
||||
format = old_format;
|
||||
format &= ~TWL4030_DATA_WIDTH;
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
format |= TWL4030_DATA_WIDTH_16S_16W;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
case 32:
|
||||
format |= TWL4030_DATA_WIDTH_32S_24W;
|
||||
break;
|
||||
default:
|
||||
dev_err(codec->dev, "%s: unknown format %d\n", __func__,
|
||||
params_format(params));
|
||||
dev_err(codec->dev, "%s: unsupported bits/sample %d\n",
|
||||
__func__, params_width(params));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -2162,10 +2161,8 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec)
|
|||
|
||||
twl4030 = devm_kzalloc(codec->dev, sizeof(struct twl4030_priv),
|
||||
GFP_KERNEL);
|
||||
if (twl4030 == NULL) {
|
||||
dev_err(codec->dev, "Can not allocate memory\n");
|
||||
if (!twl4030)
|
||||
return -ENOMEM;
|
||||
}
|
||||
snd_soc_codec_set_drvdata(codec, twl4030);
|
||||
/* Set the defaults, and power up the codec */
|
||||
twl4030->sysclk = twl4030_audio_get_mclk() / 1000;
|
||||
|
|
|
@ -243,14 +243,14 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream,
|
|||
case SND_SOC_DAIFMT_I2S:
|
||||
break;
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
hw_params |= (1<<1);
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S18_3LE:
|
||||
case 18:
|
||||
hw_params |= (1<<2);
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S20_3LE:
|
||||
case 20:
|
||||
hw_params |= ((1<<2) | (1<<1));
|
||||
break;
|
||||
default:
|
||||
|
@ -479,7 +479,7 @@ static struct snd_soc_dai_driver uda134x_dai = {
|
|||
static int uda134x_soc_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct uda134x_priv *uda134x;
|
||||
struct uda134x_platform_data *pd = codec->card->dev->platform_data;
|
||||
struct uda134x_platform_data *pd = codec->component.card->dev->platform_data;
|
||||
const struct snd_soc_dapm_widget *widgets;
|
||||
unsigned num_widgets;
|
||||
|
||||
|
|
|
@ -341,8 +341,9 @@ static int wl1273_hw_params(struct snd_pcm_substream *substream,
|
|||
struct wl1273_core *core = wl1273->core;
|
||||
unsigned int rate, width, r;
|
||||
|
||||
if (params_format(params) != SNDRV_PCM_FORMAT_S16_LE) {
|
||||
pr_err("Only SNDRV_PCM_FORMAT_S16_LE supported.\n");
|
||||
if (params_width(params) != 16) {
|
||||
dev_err(dai->dev, "%d bits/sample not supported\n",
|
||||
params_width(params));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -461,10 +462,8 @@ static int wl1273_probe(struct snd_soc_codec *codec)
|
|||
}
|
||||
|
||||
wl1273 = kzalloc(sizeof(struct wl1273_priv), GFP_KERNEL);
|
||||
if (wl1273 == NULL) {
|
||||
dev_err(codec->dev, "Cannot allocate memory.\n");
|
||||
if (!wl1273)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
wl1273->mode = WL1273_MODE_BT;
|
||||
wl1273->core = *core;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue