audio: remove Cirrus code to vendor/cirrus/audio/dlkm

Cirrus has their own code release branch. and these branches are
not compatible each other. audio team can't branch off motorola
kernel modules

Note: cs4012 and msm-cirrus-playback had not beeen moved away.

Change-Id: Ib14bf3c5a5cfaa9c363a59c4ba0f871e11e9c92a
Signed-off-by: huangys <huangys@motorola.com>
Reviewed-on: https://gerrit.mot.com/1350673
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Guobin Zhang <zhanggb@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
huangys 2019-05-14 17:06:50 +08:00 • committed by Yuesheng Huang
commit 1e7204e942
77 changed files with 0 additions and 47271 deletions

View file

@ -1,140 +0,0 @@
Cirrus Logic Madera class audio codecs extcon driver
The extcon configuration settings are a child node of the parent MFD driver
binding.
See Documentation/devicetree/bindings/mfd/madera.txt
This node contains one or more child nodes to describe the configuration for
each accessory detect.
Mandatory properties:
- compatible : must be "cirrus,madera-extcon"
- #address-cells : must be 1
- #size-cells : must be 0
Optional properties:
- cirrus,gpsw : Settings for the general purpose switches, set as per the
SWn_MODE bits in the GP Switch 1 register. If given must be 2 cells.
First cell is the value for the SW1_MODE
Second cell is the value for the SW2_MODE (cs47l90, cs47l91)
- cirrus,micd-pol-gpio : GPIO specifier for the GPIO controlling the headset
polarity if one exists. One cell for each child node.
- cirrus,micd-pol-alt-gpio : GPIO specifier for second GPIO controlling the headset
polarity if one exist. If 2 alt gpio is configured, its value will be set opposite
to the first GPIO.
Child node mandatory properties:
- reg : output number this configuration applies to, must be 1
Child node optional properties:
- cirrus,init-mic-delay-ms : Additional delay to wait headset plug in totally
delay specified in milliseconds
- cirrus,micd-detect-debounce-ms : Additional software microphone detection
debounce specified in milliseconds
- cirrus,micd-manual-debounce : Additional software button detection
debounce specified as a number
- cirrus,micd-bias-start-time : Time allowed for MICBIAS to startup prior to
performing microphone detection, specified as per the MICD_BIAS_STARTTIME
bits in the register MIC_DETECT_1
- cirrus,micd-rate : Delay between successive microphone detection
measurements, specified as per the MICD_RATE bits in the register
MIC_DETECT_1
- cirrus,micd-dbtime : Microphone detection hardware debounce level, specified
as per the MICD_DBTIME bits in the register MIC_DETECT_1
- cirrus,micd-timeout-ms : Timeout for microphone detection, specified in
milliseconds
- cirrus,micd-force-micbias : Force MICBIAS continuously on during microphone
detection and button detection
- cirrus,micd-software-compare : Use a software comparison to determine mic
presence
- cirrus,jd-invert : Invert the polarity of the jack detection switch
- cirrus,jd-use-jd2 : Use JD2 input with JD1 for dual jack detection.
- cirrus,fixed-hpdet-imp : Do not perform any headphone detection, just use
the fixed value specified here as the headphone impedance. Value is in
hundredths-of-an-ohm (ohms * 100)
- cirrus,hpdet-ext-res : Impedance of external series resistor on hpdet.
Value is in hundredths-of-an-ohm (ohms * 100)
- cirrus,hpdet-short-circuit-imp : Specifies the maximum impedance in ohms
that will be considered as a short circuit
- cirrus,hpdet-channel : Set which channel is used for headphone impedance
measurement. 0 = left, 1 = right
- cirrus,micd-clamp-mode : Specifies the logic of the micdetect clamp block
- cirrus,hpd-pins : 4 cells specifying the clamp and sense pins to use.
<clamp_left sense_left clamp_right sense_right>
where clamp_x is the clamp pin for channel x and sense_x is the impedance
sense pin for channel x, as per the HPD_OUT_SEL field of HEADPHONE_DETECT_0
register. A value >0xFFFF means use the default.
(cs47l90, cs47l91)
- cirrus,micd-configs : Headset polarity configurations, variable length but
must be a multiple of 5 cells, each 5-cell group represents one
polarity configuration
first cell is the value of
ACCDET_SRC register field (CS47L35, CS47L85, WM1840),
MICD_SENSE_SEL register field (all other codecs)
second cell is the accessory detection ground as per the MICD_GND_SEL
register field
the third cell is the MICBIAS to be used as per the MICD_BIAS_SRC register
field
fourth cell is the value of the micd-pol-gpio pin, a non-zero value
indicates this should be on
fifth cell is
set to zero (cs47l35, cs47l85, wm1840)
value of HPn_GND_SEL register field (all other codecs)
Example:
codec: cs47l85@0 {
compatible = "cirrus,cs47l85";
accdet {
compatible = "cirrus,madera-extcon";
#address-cells = <1>;
#size-cells = <0>;
cirrus,gpsw = <3 0>;
cirrus,micd-pol-gpios = <&gpio 0>
acc@1 {
reg = <1>;
cirrus,micd-detect-debounce-ms = <10>;
cirrus,micd-bias-start-time = <0x1>;
cirrus,micd-rate = <0x1>;
cirrus,micd-dbtime = <0x1>;
cirrus,micd-timeout-ms = <10>;
cirrus,micd-force-micbias;
cirrus,micd-ranges = <
11 0x100
28 0x101
54 0x102
100 0x103
186 0x104
430 0x105
>;
cirrus,micd-configs = <
0x1 0 1 0 2
0x0 0 2 1 2
>;
};
};
};

View file

@ -1,19 +0,0 @@
Cirrus Logic Madera class audio codecs gpio driver
See also the core bindings for the parent MFD driver:
See Documentation/devicetree/bindinge/mfd/madera.txt
Required properties:
- gpio-controller : Indicates this device is a GPIO controller.
- #gpio-cells : Must be 2. The first cell is the pin number. The second cell
is reserved for future use and must be zero
Example:
codec: cs47l85@0 {
compatible = "cirrus,cs47l85";
gpio-controller;
#gpio-cells = <2>;
};

View file

@ -1,38 +0,0 @@
Cirrus Logic Madera class audio codec IRQ driver
See also the core bindings for the parent MFD driver:
See Documentation/devicetree/bindinge/mfd/madera.txt
Required properties:
- interrupts : The interrupt line the /IRQ signal for the device is
connected to.
- interrupt-controller : Madera class devices contain interrupt controllers
and may provide interrupt services to other devices.
- interrupt-parent : The parent interrupt controller.
- #interrupt-cells: the number of cells to describe an IRQ, this should be 2.
The first cell is the IRQ number.
The second cell is the flags, encoded as the trigger masks from
bindings/interrupt-controller/interrupts.txt
Optional properties:
- cirrus,irq-gpios : The GPIO the host IRQ is connected to. Used when the
host IRQ is edge-triggered to emulate a level-triggered IRQ. If specified
must be exactly one GPIO entry
- cirrus,irq_flags : host controller flags as defined in
bindings/interrupt-controller/interrupts.txt
Example:
codec: cs47l85@0 {
compatible = "cirrus,cs47l85";
interrupts = <&host_irq1>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&gic>;
};

View file

@ -1,49 +0,0 @@
Cirrus Logic Madera class audio codecs
See also the core bindings for the parent MFD driver:
See Documentation/devicetree/bindinge/mfd/madera.txt
Optional properties:
- cirrus,dmic-ref : DMIC reference for each input, one cell per input
<IN1 IN2 IN3 ...>
A value of 0 indicates MICVDD and is the default, other
values depend on the codec - see the datasheet for the INn_DMIC_SUP field
- cirrus,dmic-clksrc : DMIC clock source for each input (CS47L90, CS47L91).
One cell per input. A value of 0 will source DMIC from the internally
generated clock within the ADC subsystem and a value of 1 will source DMIC
and External digital speakers with same clock
- cirrus,inmode : A list of input mode settings for each input. A maximum
of 16 cells, with four cells per input in the order INnAL, INnAR INnBL INnBR.
For non-muxed inputs the first two cells for that input set the mode for
the left and right channel and the second two cells must be 0.
For muxed inputs (cs47l35 IN1, cs47l85 IN1 and IN2) the first two cells for
that input set the mode of the left and right A inputs and the second two
cells set the mode of the left and right B inputs.
Valid mode values are one of the MADERA_INMODE_xxx (see
include/dt-bindings/sound/madera.h). If the array is shorter than the number
of inputs the unspecified inputs default to MADERA_INMODE_DIFF.
- cirrus,out-mono : Mono bit for each output, must contain six cells if
specified. A non-zero value indicates the corresponding output is mono.
- cirrus,max-channels-clocked : The maximum number of channels to be clocked
on each AIF, useful for I2S systems with multiple data lines being mastered.
One cell for each AIF, use a value of zero for AIFs that should be handled
normally.
Example:
codec: cs47l35@0 {
compatible = "cirrus,cs47l35";
cirrus,dmic-ref = <0 0 1 0>;
cirrus,dmic-clksrc = <0 0 0 0>;
cirrus,inmode = <
2 2 1 1 /* IN1A digital, IN1B single-ended */
0 0 0 0 /* IN2 differential */
>;
cirrus,out-mono = <0 0 0 0 0 0>;
cirrus,max-channels-clocked = <2 0 0>;
};

View file

@ -1,91 +0,0 @@
Cirrus Logic Madera class audio codecs multi-function device
These devices are audio SoCs with extensive digital capabilities and a range
of analogue I/O.
See also the child driver bindings in:
bindings/extcon/extcon-madera.txt
bindings/gpio/gpio-madera.txt
bindings/interrupt-controller/cirrus,madera.txt
bindings/regulator/madera-ldo1.txt
bindings/regulator/madera-micsupp.txt
bindings/sound/madera.txt
bindings/switch/madera.txt
Required properties:
- compatible : One of the following chip-specific strings:
"cirrus,cs47l35"
"cirrus,cs47l85"
"cirrus,cs47l90"
"cirrus,cs47l91"
"cirrus,wm1840"
- reg : I2C slave address when connected using I2C, chip select number when
using SPI.
- DCVDD-supply : Power supply for the device as defined in
bindings/regulator/regulator.txt
Mandatory on CS47L35, CS47L90, CS47L91
Optional on CS47L85, WM1840
- AVDD-supply, DBVDD1-supply, DBVDD2-supply, CPVDD1-supply, CPVDD2-supply :
Power supplies for the device
- DBVDD3-supply, DBVDD4-supply : Power supplies for the device
(CS47L85, CS47L90, CS47L91, WM1840)
- SPKVDDL-supply, SPKVDDR-supply : Power supplies for the device
(CS47L85, WM1840)
- SPKVDD-supply : Power supplies for the device
(CS47L35)
Optional properties:
, MICVDD-supply : Power supply, only need to be specified if
powered externally
- reset-gpios : One entry specifying the GPIO controlling /RESET.
As defined in bindings/gpio.txt.
- cirrus,clk32k-src : set input source for codec 32kHz clock.
0 = default, 1 = MCLK1, 2 = MCLK2, 3 = None
- cirrus,gpio-defaults : A list of values for the GPn_CONFIGx registers.
There are two entries for each GPIO, corresponding to the GPn_CONFIG1 and
GPn_CONFIG2 registers for that GPIO. Defines for the appropriate values can
be found in <dt-bindings/mfd/madera.h>. If absent, no configuration of these
registers is performed. If any entry has a value >0xFFFF the chip default
will be used.
- cirrus,micbias1 : Configuration for the micbias regulator, there are 8 cells
<vout cap disA disB disC disD soft bypass>
where
vout is the output voltage in millivolts
cap is non-zero value if an external capacitor is fitted
disA,B,C,D non-zero if that output should be actively discharged
soft non-zero to enable soft-start
bypass non-zero to enable bypass
- cirrus,micbias2 : See cirrus,micbias1
- cirrus,micbias3 : See cirrus,micbias1
- cirrus,micbias4 : See cirrus,micbias1
Example:
codec: cs47l85@0 {
compatible = "cirrus,cs47l85";
reg = <0>;
reset-gpios = <&gpio 0>;
cirrus,gpio-defaults = <
Madera_GP_FN_TXLRCLK
Madera_GP_DEFAULT
Madera_GP_DEFAULT
Madera_GP_DEFAULT
Madera_GP_DEFAULT
>;
cirrus,micbias2 = <2600 0 1 0 0 0 1 0>;
};

View file

@ -1,25 +0,0 @@
Cirrus Logic Madera class audio codecs LDO1 regulator driver
Only required if you are using the codec internal LDO1 regulator.
See also the core bindings for the parent MFD driver:
See Documentation/devicetree/bindinge/mfd/madera.txt
Required properties:
- LDOVDD-supply : Power supply for the LDO1 regulator.
- cirrus,ldoena-gpios : One entry specifying the GPIO controlling LDOENA.
As defined in bindings/gpio.txt.
Optional subnodes:
- ldo1 : Initial data for the LDO1 regulator, as described in
bindings/regulator/regulator.txt
Example:
codec: cs47l85@0 {
compatible = "cirrus,cs47l85";
LDOVDD-supply = <&pmic_vdd1>;
cirrus,ldoena-gpios = <&gpio 0>;
};

View file

@ -1,24 +0,0 @@
Cirrus Logic Madera class audio codecs mic supply regulator driver
Only required if the codec has an internal mic supply regulator.
See also the core bindings for the parent MFD driver:
See Documentation/devicetree/bindinge/mfd/madera.txt
Optional subnodes:
- micvdd : Initial data for the MICVDD regulator, as covered in
Documentation/devicetree/bindings/regulator/regulator.txt
Example:
codec: cs47l85@0 {
compatible = "cirrus,cs47l85";
micvdd {
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <3300000>;
regulator-allow-bypass = <1>;
};
};

View file

@ -1,110 +0,0 @@
CS35L36 Speaker Amplifier
Required properties:
- compatible : "cirrus,cs35l36"
- reg : the I2C address of the device for I2C
- VA-supply, VP-supply : power supplies for the device,
as covered in
Documentation/devicetree/bindings/regulator/regulator.txt.
Optional properties:
- cirrus,sclk-force-output : Audio serial port SCLK force
output control. Forces the SCLK to continue to drive even
if no ASP_TXn channels are enabled.
- cirrus,lrclk-force-output : Audio serial port LRCLK force
output control. Forces the LRCLK to continue to drive even
if no ASP_TXn channels are enabled.
- cirrus,right-channel-amp : Boolean to determine which channel
the amplifier is to receive the audio data on. If present the
amplifier receives data on the right channel of I2S data.
If not present the amplifier receives data on the left
channel of I2S data
- cirrus,boost-ctl-millivolt : Boost Voltage Value. Configures the boost
converter's output voltage in mV. The range is from 2550mV to 10000mV with
increments of 50mV.
(Default) VP
- cirrus,boost-peak-milliamp : Boost-converter peak current limit in mA.
Configures the peak current by monitoring the current through the boost FET.
Range starts at 1600mA and goes to a maximum of 4500mA with increments of
50mA.
(Default) 4.50 Amps
- cirrus,amp-gain-zc : Boolean to determine if to use Amplifier gain-change
zero-cross
- cirrus,ldm-mode-select : Amplifier level-dependent muting enable mode selection.
Configures whether the amplifier level-dependent muting is enabled for the various
blocks when the selected audio source has been below the AMP_LDM_THLD for a period
of time configured by AMP_LDM_DELAY. Any and all bits can be set.
00000 - All level-dependent muting functionality disabled (Default)
xxxx1 - Amplifier level-dependent muting detection enabled (OUT+/-; switching)
xxx1x - Boost converter DCM detection enabled
xx1xx - VMON low power mode detection enabled
x1xxx - IMON low power mode detection enabled
1xxxx - VP brownout prevention detection enabled
- cirrus,pdm-ldm-exit : Boolean : Amplifier PDM mode digital volume ramp enable.
When AMP_PDM_MODE = 1 controls whether the digital volume soft ramp is enabled
or disabled when exiting a level-dependent muted condition. The AMP_RAMP_PDM_DN
control is used to control desired ramp rate.
- cirrus,pdm-ldm-enter : Boolean: Amplifier PDM mode digital volume ramp enable.
When AMP_PDM_MODE = 1 controls whether the digital volume soft ramp is enabled
or disabled when entering a level-dependent muted condition. The AMP_RAMP_PDM_UP
control is used to control desired ramp rate.
- cirrus,pdm-channel-select : PDM Channel select.
0x00 (Default) : Selects Channel A data when the PDM audio input is selected.
0x01 : Selects Channel B data when the PDM audio input is selected
- cirrus,weak-fet-disable : Boolean : The strength of the output drivers is
reduced when operating in a Weak-FET Drive Mode and must not be used to drive
a large load.
- cirrus,classh-wk-fet-delay : Weak-FET entry delay. Controls the delay
(in ms) before the Class H algorithm switches to the weak-FET voltage
(after the audio falls and remains below the value specified in WKFET_AMP_THLD).
0 = 0ms
1 = 5ms
2 = 10ms
3 = 50ms
4 = 100ms (Default)
5 = 200ms
6 = 500ms
7 = 1000ms
- cirrus,classh-weak-fet-thld-millivolt : Weak-FET amplifier drive threshold.
Configures the signal threshold at which the PWM output stage enters
weak-FET operation. The range is 50mV to 700mV in 50mV increments.
- cirrus,temp-warn-threshold : Amplifier overtemperature warning threshold.
Configures the threshold at which the overtemperature warning condition occurs.
When the threshold is met, the overtemperature warning attenuation is applied
and the TEMP_WARN_EINT interrupt status bit is set.
If TEMP_WARN_MASK = 0, INTb is asserted.
0 = 105C
1 = 115C
2 = 125C (Default)
3 = 135C
Example:
cs35l36: cs35l36@58 {
compatible = "cirrus,cs35l36";
reg = <0x58>;
VA-supply = <&dummy_vreg>;
VP-supply = <&dummy_vreg>;
reset-gpios = <&axi_gpio 54 0>;
cirrus,boost-ctl-millivolt = <10000>;
};

View file

@ -1,198 +0,0 @@
CS35L41 Speaker Amplifier
Required properties:
- compatible : "cirrus,cs35l41"
"cirrus,cs35l40"
- reg : the SPI chip select line for the device
- VA-supply, VP-supply : power supplies for the device,
as covered in
Documentation/devicetree/bindings/regulator/regulator.txt.
Boost hardware configuration:
These three properties should be used together to specify the external
component configuration of the part. See section 4.3.6 of the datasheet
for details regarding how these values are used to configure the
digital boost converter's control loop.
- cirrus,boost-peak-milliamp : Boost-converter peak current limit in mA.
Configures the peak current by monitoring the current through the boost FET.
Range starts at 1600 mA and goes to a maximum of 4500 mA with increments
of 50 mA.
(Default) 4.50 Amps
- cirrus,boost-ind-nanohenry : Boost inductor value, expressed in nH. Valid
values include 1000, 1200, 1500 and 2200.
- cirrus,boost-cap-microfarad : Total equivalent boost capacitance on the VBST
and VAMP pins, derated at 11 volts DC. The value must be rounded to the
nearest integer and expressed in uF.
Optional properties:
- cirrus,sclk-force-output : Audio serial port SCLK force
output control. Forces the SCLK to continue to drive even
if no ASP_TXn channels are enabled.
- cirrus,lrclk-force-output : Audio serial port LRCLK force
output control. Forces the LRCLK to continue to drive even
if no ASP_TXn channels are enabled.
- cirrus,right-channel-amp : Boolean to determine which channel
the amplifier is to receive the audio data on. If present the
amplifier receives data on the right channel of I2S data.
If not present the amplifier receives data on the left
channel of I2S data
- cirrus,boost-ctl-millivolt : Boost Voltage Value. Configures the
boost converter's output voltage in mV. The range is from 2550 mV to
11000 mV with increments of 50 mV.
(Default) VP
- cirrus,amp-gain-zc : Boolean to determine whether to use the amplifier
gain-change zero-crossing feature. If the feature is enabled, any
user-controlled amplifier gain change will occur on a zero-crossing point.
(Default) Disabled
- cirrus,asp-sdout-hiz : Audio serial port SDOUT Hi-Z control. Sets the Hi-Z
configuration for SDOUT pin of amplifier.
0 = Logic 0 during unused slots, and while all transmit channels disabled
1 = Hi-Z during unused slots but logic 0 while all transmit channels disabled
2 = (Default) Logic 0 during unused slots, but Hi-Z while all transmit channels disabled
3 = Hi-Z during unused slots and while all transmit channels disabled
- cirrus,temp-warn-threshold : Amplifier overtemperature warning threshold.
Configures the threshold at which the overtemperature warning condition occurs.
When the threshold is met, the ovetemperature warning attenuation is applied
and the TEMP_WARN_EINT interrupt status bit is set.
If TEMP_WARN_MASK = 0, INTb is asserted.
0 = 105C
1 = 115C
2 = 125C (Default)
3 = 135C
- cirrus,noise-gate-enable : DSP Noise Gate feature. If present, noise
gate feature will be enabled.
- cirrus,noise-gate-threshold : Threshold of audio signal input which the
noise gate considers the input audio to be at a low enough level to be
valid to enter a noise gating state of operation.
0 = -66 dBFS
1 = -72 dBFS
2 = -78 dBFS
3 = -84 dBFS (default)
4 = -90 dBFS
5 = -96 dBFS
6 = -102 dBFS
7 = -108 dBFS
- cirrus,noise-gate-delay : Time that the incoming audio signal must be
below the noise gate threshold prior to entering a noise gated state
0 = 5 ms
1 = 10 ms
2 = 25 ms
3 = 50 ms (default)
4 = 100 ms
5 = 250 ms
6 = 500 ms
7 = 1 s
8 = 5 s
9 = 10 s
10 = 20 s
11 = 30 s
12 = 40 s
13 = 50 s
14 = 60 s
15 = 120 s
Optional H/G Algorithm sub-node:
The cs35l41 node can have a single "cirrus,classh-internal-algo" sub-node
that will disable automatic control of the internal H/G Algorithm.
It is strongly recommended that the Datasheet be referenced when adjusting
or using these Class H Algorithm controls over the internal Algorithm.
Serious damage can occur to the Device and surrounding components.
- cirrus,classh-internal-algo : Sub-node for the Internal Class H Algorithm
See Section 4.4 Internal Class H Algorithm in the Datasheet.
If not used, the device manages the ClassH Algorithm internally.
Optional properties for the "cirrus,classh-internal-algo" Sub-node
Section 7.9 Boost Control
- cirrus,classh-bst-overide : Boolean
- cirrus,classh-bst-max-limit
Section 7.17 Class H, Weak-FET Control
- cirrus,classh-headroom
- cirrus,classh-release-rate
- cirrus,classh-mem-depth
- cirrus,classh-wk-fet-delay
- cirrus,classh-wk-fet-thld
Optional GPIO1 sub-node:
The cs35l41 node can have an single "cirrus,gpio-config1" sub-node for
configuring the GPIO1 pin.
- cirrus,gpio-polarity-invert : Boolean which specifies whether the GPIO1
level is inverted. If this property is not present the level is not inverted.
- cirrus,gpio-output-enable : Boolean which specifies whether the GPIO1 pin
is configured as an output. If this property is not present the
pin will be configured as an input.
- cirrus,gpio-src-select : Configures the function of the GPIO1 pin.
Note that the options are different from the GPIO2 pin.
0 = High Impedance (Default)
1 = GPIO
2 = Sync
3 = MCLK input
Optional GPIO2 sub-node:
The cs35l41 node can have an single "cirrus,gpio-config2" sub-node for
configuring the GPIO1 pin.
- cirrus,gpio-polarity-invert : Boolean which specifies whether the GPIO2
level is inverted. If this property is not present the level is not inverted.
- cirrus,gpio-output-enable : Boolean which specifies whether the GPIO2 pin
is configured as an output. If this property is not present the
pin will be configured as an input.
- cirrus,gpio-src-select : Configures the function of the GPIO2 pin.
Note that the options are different from the GPIO1 pin.
0 = High Impedance (Default)
1 = GPIO
2 = Open Drain INTB
3 = MCLK input
4 = Push-pull INTB (active low)
5 = Push-pull INT (active high)
Example:
cs35l41: cs35l41@2 {
compatible = "cirrus,cs35l41";
reg = <2>;
VA-supply = <&dummy_vreg>;
VP-supply = <&dummy_vreg>;
cirrus,boost-peak-milliamp = <4500>;
cirrus,boost-ind-nanohenry = <1000>;
cirrus,boost-cap-microfarad = <15>;
};

View file

@ -1,8 +0,0 @@
DLKM_DIR := motorola/kernel/modules
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := extcon-madera.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk

View file

@ -1,6 +0,0 @@
# add -Wall to try to catch everything we can.
EXTRA_CFLAGS += -Wall
EXTRA_CFLAGS += -I$(TOP)/motorola/kernel/modules/include
EXTRA_CFLAGS += -DCONFIG_EXTCON_MADERA_INPUT_EVENT
obj-m += extcon-madera.o

View file

@ -1,10 +0,0 @@
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
all:
$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS)
modules_install:
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install
clean:
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean

File diff suppressed because it is too large Load diff

View file

@ -1,8 +0,0 @@
DLKM_DIR := motorola/kernel/modules
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := gpio-madera.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk

View file

@ -1,5 +0,0 @@
# add -Wall to try to catch everything we can.
EXTRA_CFLAGS += -Wall
EXTRA_CFLAGS += -I$(TOP)/motorola/kernel/modules/include
obj-m += gpio-madera.o

View file

@ -1,10 +0,0 @@
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
all:
$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS)
modules_install:
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install
clean:
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean

View file

@ -1,186 +0,0 @@
/*
* GPIO support for Cirrus Logic Madera codecs
*
* Copyright 2015-2017 Cirrus Logic
*
* 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/device.h>
#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mfd/madera/core.h>
#include <linux/mfd/madera/pdata.h>
#include <linux/mfd/madera/registers.h>
struct madera_gpio {
struct madera *madera;
struct gpio_chip gpio_chip;
};
static int madera_gpio_get_direction(struct gpio_chip *chip,
unsigned int offset)
{
struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
struct madera *madera = madera_gpio->madera;
unsigned int val;
int ret;
ret = regmap_read(madera->regmap,
MADERA_GPIO1_CTRL_2 + (2 * offset), &val);
if (ret < 0)
return ret;
return (val & MADERA_GP1_DIR_MASK) >> MADERA_GP1_DIR_SHIFT;
}
static int madera_gpio_direction_in(struct gpio_chip *chip, unsigned int offset)
{
struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
struct madera *madera = madera_gpio->madera;
return regmap_update_bits(madera->regmap,
MADERA_GPIO1_CTRL_2 + (2 * offset),
MADERA_GP1_DIR_MASK, MADERA_GP1_DIR);
}
static int madera_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
struct madera *madera = madera_gpio->madera;
unsigned int val;
int ret;
ret = regmap_read(madera->regmap,
MADERA_GPIO1_CTRL_1 + (2 * offset), &val);
if (ret < 0)
return ret;
return !!(val & MADERA_GP1_LVL_MASK);
}
static int madera_gpio_direction_out(struct gpio_chip *chip,
unsigned int offset, int value)
{
struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
struct madera *madera = madera_gpio->madera;
unsigned int regval;
int ret;
if (value)
regval = MADERA_GP1_LVL;
else
regval = 0;
ret = regmap_update_bits(madera->regmap,
MADERA_GPIO1_CTRL_2 + (2 * offset),
MADERA_GP1_DIR_MASK, 0);
if (ret < 0)
return ret;
return regmap_update_bits(madera->regmap,
MADERA_GPIO1_CTRL_1 + (2 * offset),
MADERA_GP1_LVL_MASK, regval);
}
static void madera_gpio_set(struct gpio_chip *chip, unsigned int offset,
int value)
{
struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
struct madera *madera = madera_gpio->madera;
unsigned int regval;
int ret;
if (value)
regval = MADERA_GP1_LVL;
else
regval = 0;
ret = regmap_update_bits(madera->regmap,
MADERA_GPIO1_CTRL_1 + (2 * offset),
MADERA_GP1_LVL_MASK, regval);
if (ret)
dev_warn(madera->dev, "Failed to write to 0x%x (%d)\n",
MADERA_GPIO1_CTRL_1 + (2 * offset), ret);
}
static struct gpio_chip template_chip = {
.label = "madera",
.owner = THIS_MODULE,
.get_direction = madera_gpio_get_direction,
.direction_input = madera_gpio_direction_in,
.get = madera_gpio_get,
.direction_output = madera_gpio_direction_out,
.set = madera_gpio_set,
.can_sleep = true,
};
static int madera_gpio_probe(struct platform_device *pdev)
{
struct madera *madera = dev_get_drvdata(pdev->dev.parent);
struct madera_pdata *pdata = dev_get_platdata(madera->dev);
struct madera_gpio *madera_gpio;
int ret;
madera_gpio = devm_kzalloc(&pdev->dev, sizeof(*madera_gpio),
GFP_KERNEL);
if (!madera_gpio)
return -ENOMEM;
madera_gpio->madera = madera;
madera_gpio->gpio_chip = template_chip;
madera_gpio->gpio_chip.parent = &pdev->dev;
if (IS_ENABLED(CONFIG_OF_GPIO))
madera_gpio->gpio_chip.of_node = madera->dev->of_node;
switch (madera->type) {
case CS47L35:
madera_gpio->gpio_chip.ngpio = CS47L35_NUM_GPIOS;
break;
case CS47L85:
case WM1840:
madera_gpio->gpio_chip.ngpio = CS47L85_NUM_GPIOS;
break;
case CS47L90:
case CS47L91:
madera_gpio->gpio_chip.ngpio = CS47L90_NUM_GPIOS;
break;
default:
dev_err(&pdev->dev, "Unknown chip variant %d\n", madera->type);
return -EINVAL;
}
if (pdata && pdata->gpio_base)
madera_gpio->gpio_chip.base = pdata->gpio_base;
else
madera_gpio->gpio_chip.base = -1;
ret = devm_gpiochip_add_data(&pdev->dev, &madera_gpio->gpio_chip,
madera_gpio);
if (ret < 0) {
dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
return ret;
}
return 0;
}
static struct platform_driver madera_gpio_driver = {
.driver.name = "madera-gpio",
.driver.owner = THIS_MODULE,
.probe = madera_gpio_probe,
};
module_platform_driver(madera_gpio_driver);
MODULE_DESCRIPTION("GPIO interface for Madera codecs");
MODULE_AUTHOR("Nariman Poushin <nariman@opensource.wolfsonmicro.com>");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:madera-gpio");

View file

@ -1,9 +0,0 @@
DLKM_DIR := motorola/kernel/modules
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := cirrus_irq-madera.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk

View file

@ -1,13 +0,0 @@
# add -Wall to try to catch everything we can.
EXTRA_CFLAGS += -Wall
EXTRA_CFLAGS += -I$(TOP)/motorola/kernel/modules/include
ifeq ($(CONFIG_ARCH_SDM450), y)
EXTRA_CFLAGS += -DCONFIG_MADERA_IRQ_CS47L35
cirrus_irq-madera-objs = irq-madera.o irq-madera-cs47l35.o
else
EXTRA_CFLAGS += -DCONFIG_MADERA_IRQ_CS47L90
cirrus_irq-madera-objs = irq-madera.o irq-madera-cs47l90.o
endif
obj-m += cirrus_irq-madera.o

View file

@ -1,10 +0,0 @@
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
all:
$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS)
modules_install:
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install
clean:
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean

View file

@ -1,115 +0,0 @@
/*
* Interrupt support for Cirrus Logic CS47L35
*
* Copyright 2016 Cirrus Logic
*
* 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/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/regmap.h>
#include <linux/mfd/madera/core.h>
#include <linux/mfd/madera/registers.h>
#include "irq-madera.h"
static const struct regmap_irq cs47l35_irqs[MADERA_NUM_IRQ] = {
[MADERA_IRQ_BOOT_DONE] = { .reg_offset = 0,
.mask = MADERA_BOOT_DONE_EINT1 },
[MADERA_IRQ_CTRLIF_ERR] = { .reg_offset = 0,
.mask = MADERA_CTRLIF_ERR_EINT1 },
[MADERA_IRQ_FLL1_LOCK] = { .reg_offset = 1,
.mask = MADERA_FLL1_LOCK_EINT1 },
[MADERA_IRQ_FLL2_LOCK] = { .reg_offset = 1,
.mask = MADERA_FLL2_LOCK_EINT1},
[MADERA_IRQ_FLL3_LOCK] = { .reg_offset = 1,
.mask = MADERA_FLL3_LOCK_EINT1},
[MADERA_IRQ_MICDET1] = { .reg_offset = 5,
.mask = MADERA_MICDET1_EINT1 },
[MADERA_IRQ_HPDET] = { .reg_offset = 5,
.mask = MADERA_HPDET_EINT1},
[MADERA_IRQ_MICD_CLAMP_RISE] = { .reg_offset = 6,
.mask = MADERA_MICD_CLAMP_RISE_EINT1 },
[MADERA_IRQ_MICD_CLAMP_FALL] = { .reg_offset = 6,
.mask = MADERA_MICD_CLAMP_FALL_EINT1 },
[MADERA_IRQ_JD1_FALL] = { .reg_offset = 6,
.mask = MADERA_JD1_FALL_EINT1 },
[MADERA_IRQ_JD1_RISE] = { .reg_offset = 6,
.mask = MADERA_JD1_RISE_EINT1 },
[MADERA_IRQ_JD2_FALL] = { .reg_offset = 6,
.mask = MADERA_JD2_FALL_EINT1 },
[MADERA_IRQ_JD2_RISE] = { .reg_offset = 6,
.mask = MADERA_JD2_RISE_EINT1 },
[MADERA_IRQ_DRC2_SIG_DET] = { .reg_offset = 8,
.mask = MADERA_DRC2_SIG_DET_EINT1 },
[MADERA_IRQ_DRC1_SIG_DET] = { .reg_offset = 8,
.mask = MADERA_DRC1_SIG_DET_EINT1 },
[MADERA_IRQ_DSP_IRQ1] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ1_EINT1},
[MADERA_IRQ_DSP_IRQ2] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ2_EINT1},
[MADERA_IRQ_DSP_IRQ3] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ3_EINT1},
[MADERA_IRQ_DSP_IRQ4] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ4_EINT1},
[MADERA_IRQ_DSP_IRQ5] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ5_EINT1},
[MADERA_IRQ_DSP_IRQ6] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ6_EINT1},
[MADERA_IRQ_DSP_IRQ7] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ7_EINT1},
[MADERA_IRQ_DSP_IRQ8] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ8_EINT1},
[MADERA_IRQ_DSP_IRQ9] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ9_EINT1},
[MADERA_IRQ_DSP_IRQ10] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ10_EINT1},
[MADERA_IRQ_DSP_IRQ11] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ11_EINT1},
[MADERA_IRQ_DSP_IRQ12] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ12_EINT1},
[MADERA_IRQ_DSP_IRQ13] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ13_EINT1},
[MADERA_IRQ_DSP_IRQ14] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ14_EINT1},
[MADERA_IRQ_DSP_IRQ15] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ15_EINT1},
[MADERA_IRQ_DSP_IRQ16] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ16_EINT1},
[MADERA_IRQ_HP2R_SC] = { .reg_offset = 11,
.mask = MADERA_HP2R_SC_EINT1},
[MADERA_IRQ_HP2L_SC] = { .reg_offset = 11,
.mask = MADERA_HP2L_SC_EINT1},
[MADERA_IRQ_HP1R_SC] = { .reg_offset = 11,
.mask = MADERA_HP1R_SC_EINT1},
[MADERA_IRQ_HP1L_SC] = { .reg_offset = 11,
.mask = MADERA_HP1L_SC_EINT1},
[MADERA_IRQ_SPK_OVERHEAT_WARN] = { .reg_offset = 14,
.mask = MADERA_SPK_OVERHEAT_WARN_EINT1},
[MADERA_IRQ_SPK_OVERHEAT] = { .reg_offset = 14,
.mask = MADERA_SPK_SHUTDOWN_EINT1},
};
const struct regmap_irq_chip cs47l35_irq = {
.name = "cs47l35 IRQ",
.status_base = MADERA_IRQ1_STATUS_1,
.mask_base = MADERA_IRQ1_MASK_1,
.ack_base = MADERA_IRQ1_STATUS_1,
.num_regs = 15,
.irqs = cs47l35_irqs,
.num_irqs = ARRAY_SIZE(cs47l35_irqs),
};
EXPORT_SYMBOL_GPL(cs47l35_irq);

View file

@ -1,124 +0,0 @@
/*
* Interrupt support for Cirrus Logic CS47L85
*
* Copyright 2016 Cirrus Logic
*
* 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/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/regmap.h>
#include <linux/mfd/madera/core.h>
#include <linux/mfd/madera/registers.h>
#include "irq-madera.h"
static const struct regmap_irq cs47l85_irqs[MADERA_NUM_IRQ] = {
[MADERA_IRQ_BOOT_DONE] = { .reg_offset = 0,
.mask = MADERA_BOOT_DONE_EINT1 },
[MADERA_IRQ_CTRLIF_ERR] = { .reg_offset = 0,
.mask = MADERA_CTRLIF_ERR_EINT1 },
[MADERA_IRQ_FLL1_LOCK] = { .reg_offset = 1,
.mask = MADERA_FLL1_LOCK_EINT1 },
[MADERA_IRQ_FLL2_LOCK] = { .reg_offset = 1,
.mask = MADERA_FLL2_LOCK_EINT1},
[MADERA_IRQ_FLL3_LOCK] = { .reg_offset = 1,
.mask = MADERA_FLL3_LOCK_EINT1},
[MADERA_IRQ_MICDET1] = { .reg_offset = 5,
.mask = MADERA_MICDET1_EINT1 },
[MADERA_IRQ_HPDET] = { .reg_offset = 5,
.mask = MADERA_HPDET_EINT1},
[MADERA_IRQ_MICD_CLAMP_RISE] = { .reg_offset = 6,
.mask = MADERA_MICD_CLAMP_RISE_EINT1 },
[MADERA_IRQ_MICD_CLAMP_FALL] = { .reg_offset = 6,
.mask = MADERA_MICD_CLAMP_FALL_EINT1 },
[MADERA_IRQ_JD1_FALL] = { .reg_offset = 6,
.mask = MADERA_JD1_FALL_EINT1 },
[MADERA_IRQ_JD1_RISE] = { .reg_offset = 6,
.mask = MADERA_JD1_RISE_EINT1 },
[MADERA_IRQ_ASRC2_IN1_LOCK] = { .reg_offset = 8,
.mask = MADERA_ASRC2_IN1_LOCK_EINT1 },
[MADERA_IRQ_ASRC2_IN2_LOCK] = { .reg_offset = 8,
.mask = MADERA_ASRC2_IN2_LOCK_EINT1 },
[MADERA_IRQ_ASRC1_IN1_LOCK] = { .reg_offset = 8,
.mask = MADERA_ASRC1_IN1_LOCK_EINT1 },
[MADERA_IRQ_ASRC1_IN2_LOCK] = { .reg_offset = 8,
.mask = MADERA_ASRC1_IN2_LOCK_EINT1 },
[MADERA_IRQ_DRC2_SIG_DET] = { .reg_offset = 8,
.mask = MADERA_DRC2_SIG_DET_EINT1 },
[MADERA_IRQ_DRC1_SIG_DET] = { .reg_offset = 8,
.mask = MADERA_DRC1_SIG_DET_EINT1 },
[MADERA_IRQ_DSP_IRQ1] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ1_EINT1},
[MADERA_IRQ_DSP_IRQ2] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ2_EINT1},
[MADERA_IRQ_DSP_IRQ3] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ3_EINT1},
[MADERA_IRQ_DSP_IRQ4] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ4_EINT1},
[MADERA_IRQ_DSP_IRQ5] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ5_EINT1},
[MADERA_IRQ_DSP_IRQ6] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ6_EINT1},
[MADERA_IRQ_DSP_IRQ7] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ7_EINT1},
[MADERA_IRQ_DSP_IRQ8] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ8_EINT1},
[MADERA_IRQ_DSP_IRQ9] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ9_EINT1},
[MADERA_IRQ_DSP_IRQ10] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ10_EINT1},
[MADERA_IRQ_DSP_IRQ11] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ11_EINT1},
[MADERA_IRQ_DSP_IRQ12] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ12_EINT1},
[MADERA_IRQ_DSP_IRQ13] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ13_EINT1},
[MADERA_IRQ_DSP_IRQ14] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ14_EINT1},
[MADERA_IRQ_DSP_IRQ15] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ15_EINT1},
[MADERA_IRQ_DSP_IRQ16] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ16_EINT1},
[MADERA_IRQ_HP3R_SC] = { .reg_offset = 11,
.mask = MADERA_HP3R_SC_EINT1},
[MADERA_IRQ_HP3L_SC] = { .reg_offset = 11,
.mask = MADERA_HP3L_SC_EINT1},
[MADERA_IRQ_HP2R_SC] = { .reg_offset = 11,
.mask = MADERA_HP2R_SC_EINT1},
[MADERA_IRQ_HP2L_SC] = { .reg_offset = 11,
.mask = MADERA_HP2L_SC_EINT1},
[MADERA_IRQ_HP1R_SC] = { .reg_offset = 11,
.mask = MADERA_HP1R_SC_EINT1},
[MADERA_IRQ_HP1L_SC] = { .reg_offset = 11,
.mask = MADERA_HP1L_SC_EINT1},
[MADERA_IRQ_SPK_OVERHEAT_WARN] = { .reg_offset = 14,
.mask = MADERA_SPK_OVERHEAT_WARN_EINT1},
[MADERA_IRQ_SPK_OVERHEAT] = { .reg_offset = 14,
.mask = MADERA_SPK_SHUTDOWN_EINT1},
};
const struct regmap_irq_chip cs47l85_irq = {
.name = "cs47l85 IRQ",
.status_base = MADERA_IRQ1_STATUS_1,
.mask_base = MADERA_IRQ1_MASK_1,
.ack_base = MADERA_IRQ1_STATUS_1,
.num_regs = 15,
.irqs = cs47l85_irqs,
.num_irqs = ARRAY_SIZE(cs47l85_irqs),
};
EXPORT_SYMBOL_GPL(cs47l85_irq);

View file

@ -1,125 +0,0 @@
/*
* Interrupt support for Cirrus Logic CS47L90
*
* Copyright 2016 Cirrus Logic
*
* 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/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/regmap.h>
#include <linux/mfd/madera/core.h>
#include <linux/mfd/madera/registers.h>
#include "irq-madera.h"
static const struct regmap_irq cs47l90_irqs[MADERA_NUM_IRQ] = {
[MADERA_IRQ_BOOT_DONE] = { .reg_offset = 0,
.mask = MADERA_BOOT_DONE_EINT1 },
[MADERA_IRQ_CTRLIF_ERR] = { .reg_offset = 0,
.mask = MADERA_CTRLIF_ERR_EINT1 },
[MADERA_IRQ_FLL1_LOCK] = { .reg_offset = 1,
.mask = MADERA_FLL1_LOCK_EINT1 },
[MADERA_IRQ_FLL2_LOCK] = { .reg_offset = 1,
.mask = MADERA_FLL2_LOCK_EINT1},
[MADERA_IRQ_FLLAO_LOCK] = { .reg_offset = 1,
.mask = MADERA_FLLAO_LOCK_EINT1},
[MADERA_IRQ_MICDET1] = { .reg_offset = 5,
.mask = MADERA_MICDET1_EINT1 },
[MADERA_IRQ_MICDET2] = { .reg_offset = 5,
.mask = MADERA_MICDET2_EINT1 },
[MADERA_IRQ_HPDET] = { .reg_offset = 5,
.mask = MADERA_HPDET_EINT1},
[MADERA_IRQ_MICD_CLAMP_RISE] = { .reg_offset = 6,
.mask = MADERA_MICD_CLAMP_RISE_EINT1 },
[MADERA_IRQ_MICD_CLAMP_FALL] = { .reg_offset = 6,
.mask = MADERA_MICD_CLAMP_FALL_EINT1 },
[MADERA_IRQ_JD1_FALL] = { .reg_offset = 6,
.mask = MADERA_JD1_FALL_EINT1 },
[MADERA_IRQ_JD1_RISE] = { .reg_offset = 6,
.mask = MADERA_JD1_RISE_EINT1 },
[MADERA_IRQ_ASRC2_IN1_LOCK] = { .reg_offset = 8,
.mask = MADERA_ASRC2_IN1_LOCK_EINT1 },
[MADERA_IRQ_ASRC2_IN2_LOCK] = { .reg_offset = 8,
.mask = MADERA_ASRC2_IN2_LOCK_EINT1 },
[MADERA_IRQ_ASRC1_IN1_LOCK] = { .reg_offset = 8,
.mask = MADERA_ASRC1_IN1_LOCK_EINT1 },
[MADERA_IRQ_ASRC1_IN2_LOCK] = { .reg_offset = 8,
.mask = MADERA_ASRC1_IN2_LOCK_EINT1 },
[MADERA_IRQ_DRC2_SIG_DET] = { .reg_offset = 8,
.mask = MADERA_DRC2_SIG_DET_EINT1 },
[MADERA_IRQ_DRC1_SIG_DET] = { .reg_offset = 8,
.mask = MADERA_DRC1_SIG_DET_EINT1 },
[MADERA_IRQ_DSP_IRQ1] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ1_EINT1},
[MADERA_IRQ_DSP_IRQ2] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ2_EINT1},
[MADERA_IRQ_DSP_IRQ3] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ3_EINT1},
[MADERA_IRQ_DSP_IRQ4] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ4_EINT1},
[MADERA_IRQ_DSP_IRQ5] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ5_EINT1},
[MADERA_IRQ_DSP_IRQ6] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ6_EINT1},
[MADERA_IRQ_DSP_IRQ7] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ7_EINT1},
[MADERA_IRQ_DSP_IRQ8] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ8_EINT1},
[MADERA_IRQ_DSP_IRQ8] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ8_EINT1},
[MADERA_IRQ_DSP_IRQ9] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ9_EINT1},
[MADERA_IRQ_DSP_IRQ10] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ10_EINT1},
[MADERA_IRQ_DSP_IRQ11] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ11_EINT1},
[MADERA_IRQ_DSP_IRQ12] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ12_EINT1},
[MADERA_IRQ_DSP_IRQ13] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ13_EINT1},
[MADERA_IRQ_DSP_IRQ14] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ14_EINT1},
[MADERA_IRQ_DSP_IRQ15] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ15_EINT1},
[MADERA_IRQ_DSP_IRQ16] = { .reg_offset = 10,
.mask = MADERA_DSP_IRQ16_EINT1},
[MADERA_IRQ_DSP1_BUS_ERROR] = { .reg_offset = 32,
.mask = MADERA_ADSP_ERROR_STATUS_DSP1},
[MADERA_IRQ_DSP2_BUS_ERROR] = { .reg_offset = 32,
.mask = MADERA_ADSP_ERROR_STATUS_DSP2},
[MADERA_IRQ_DSP3_BUS_ERROR] = { .reg_offset = 32,
.mask = MADERA_ADSP_ERROR_STATUS_DSP3},
[MADERA_IRQ_DSP4_BUS_ERROR] = { .reg_offset = 32,
.mask = MADERA_ADSP_ERROR_STATUS_DSP4},
[MADERA_IRQ_DSP5_BUS_ERROR] = { .reg_offset = 32,
.mask = MADERA_ADSP_ERROR_STATUS_DSP5},
[MADERA_IRQ_DSP6_BUS_ERROR] = { .reg_offset = 32,
.mask = MADERA_ADSP_ERROR_STATUS_DSP6},
[MADERA_IRQ_DSP7_BUS_ERROR] = { .reg_offset = 32,
.mask = MADERA_ADSP_ERROR_STATUS_DSP7},
};
const struct regmap_irq_chip cs47l90_irq = {
.name = "cs47l90 IRQ",
.status_base = MADERA_IRQ1_STATUS_1,
.mask_base = MADERA_IRQ1_MASK_1,
.ack_base = MADERA_IRQ1_STATUS_1,
.num_regs = 33,
.irqs = cs47l90_irqs,
.num_irqs = ARRAY_SIZE(cs47l90_irqs),
};
EXPORT_SYMBOL_GPL(cs47l90_irq);

View file

@ -1,441 +0,0 @@
/*
* Interrupt support for Cirrus Logic Madera codecs
*
* Copyright 2016 Cirrus Logic
*
* 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/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/irqchip/irq-madera.h>
#include <linux/irqchip/irq-madera-pdata.h>
#include <linux/mfd/madera/core.h>
#include <linux/mfd/madera/pdata.h>
#include <linux/mfd/madera/registers.h>
#include "irq-madera.h"
struct madera_irq_priv {
struct device *dev;
unsigned int irq_sem;
int irq;
unsigned int irq_flags;
int irq_gpio;
struct regmap_irq_chip_data *irq_data;
struct irq_domain *domain;
struct madera *madera;
};
int madera_request_irq(struct madera *madera, int irq, const char *name,
irq_handler_t handler, void *data)
{
struct madera_irq_priv *priv;
if (irq < 0)
return irq;
if (!madera->irq_dev)
return -EINVAL;
priv = dev_get_drvdata(madera->irq_dev);
return request_threaded_irq(regmap_irq_get_virq(priv->irq_data, irq),
NULL, handler, IRQF_ONESHOT, name, data);
}
EXPORT_SYMBOL_GPL(madera_request_irq);
void madera_free_irq(struct madera *madera, int irq, void *data)
{
struct madera_irq_priv *priv;
if (irq < 0)
return;
if (!madera->irq_dev)
return;
priv = dev_get_drvdata(madera->irq_dev);
free_irq(regmap_irq_get_virq(priv->irq_data, irq), data);
}
EXPORT_SYMBOL_GPL(madera_free_irq);
int madera_set_irq_wake(struct madera *madera, int irq, int on)
{
struct madera_irq_priv *priv;
if (irq < 0)
return irq;
if (!madera->irq_dev)
return -EINVAL;
priv = dev_get_drvdata(madera->irq_dev);
return irq_set_irq_wake(regmap_irq_get_virq(priv->irq_data, irq), on);
}
EXPORT_SYMBOL_GPL(madera_set_irq_wake);
static irqreturn_t madera_irq_thread(int irq, void *data)
{
struct madera_irq_priv *priv = data;
bool poll;
int ret;
dev_dbg(priv->dev, "irq_thread handler\n");
/* The codec can generate IRQs while it is in low-power mode so
* we must do a runtime get before dispatching the IRQ
*/
ret = pm_runtime_get_sync(priv->madera->dev);
if (ret < 0) {
dev_err(priv->dev, "Failed to resume device: %d\n", ret);
return IRQ_NONE;
}
do {
poll = false;
handle_nested_irq(irq_find_mapping(priv->domain, 0));
/*
* Poll the IRQ pin status to see if we're really done
* if the interrupt controller can't do it for us.
*/
if (!gpio_is_valid(priv->irq_gpio)) {
break;
} else if (priv->irq_flags & IRQF_TRIGGER_RISING &&
gpio_get_value_cansleep(priv->irq_gpio)) {
poll = true;
} else if (priv->irq_flags & IRQF_TRIGGER_FALLING &&
!gpio_get_value_cansleep(priv->irq_gpio)) {
poll = true;
}
} while (poll);
pm_runtime_mark_last_busy(priv->madera->dev);
pm_runtime_put_autosuspend(priv->madera->dev);
return IRQ_HANDLED;
}
static void madera_irq_dummy(struct irq_data *data)
{
}
static int madera_irq_set_wake(struct irq_data *data, unsigned int on)
{
struct madera_irq_priv *priv = irq_data_get_irq_chip_data(data);
return irq_set_irq_wake(priv->irq, on);
}
static struct irq_chip madera_irq_chip = {
.name = "madera",
.irq_disable = madera_irq_dummy,
.irq_enable = madera_irq_dummy,
.irq_ack = madera_irq_dummy,
.irq_mask = madera_irq_dummy,
.irq_unmask = madera_irq_dummy,
.irq_set_wake = madera_irq_set_wake,
};
static struct lock_class_key madera_irq_lock_class;
static int madera_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
struct madera_irq_priv *priv = h->host_data;
irq_set_chip_data(virq, priv);
irq_set_lockdep_class(virq, &madera_irq_lock_class);
irq_set_chip_and_handler(virq, &madera_irq_chip, handle_simple_irq);
irq_set_nested_thread(virq, true);
irq_set_noprobe(virq);
return 0;
}
static const struct irq_domain_ops madera_domain_ops = {
.map = madera_irq_map,
.xlate = irq_domain_xlate_twocell,
};
#ifdef CONFIG_PM_SLEEP
static int madera_suspend_noirq(struct device *dev)
{
struct madera_irq_priv *priv = dev_get_drvdata(dev);
dev_dbg(priv->dev, "Late suspend, reenabling IRQ\n");
if (priv->irq_sem) {
enable_irq(priv->irq);
priv->irq_sem = 0;
}
return 0;
}
static int madera_suspend(struct device *dev)
{
struct madera_irq_priv *priv = dev_get_drvdata(dev);
dev_dbg(priv->dev, "Early suspend, disabling IRQ\n");
disable_irq(priv->irq);
priv->irq_sem = 1;
return 0;
}
static int madera_resume_noirq(struct device *dev)
{
struct madera_irq_priv *priv = dev_get_drvdata(dev);
dev_dbg(priv->dev, "Early resume, disabling IRQ\n");
disable_irq(priv->irq);
priv->irq_sem = 1;
return 0;
}
static int madera_resume(struct device *dev)
{
struct madera_irq_priv *priv = dev_get_drvdata(dev);
dev_dbg(priv->dev, "Late resume, reenabling IRQ\n");
if (priv->irq_sem) {
enable_irq(priv->irq);
priv->irq_sem = 0;
}
return 0;
}
#endif
static const struct dev_pm_ops madera_irq_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(madera_suspend, madera_resume)
#ifdef CONFIG_PM_SLEEP
.suspend_noirq = madera_suspend_noirq,
.resume_noirq = madera_resume_noirq,
#endif
};
static int madera_irq_of_get(struct madera_irq_priv *priv)
{
/* all our settings are under the parent DT node */
struct device_node *np = priv->madera->dev->of_node;
u32 value;
int ret;
priv->irq = irq_of_parse_and_map(np, 0);
if (priv->irq < 0)
return priv->irq;
ret = of_property_read_u32(np, "cirrus,irq_flags", &value);
if (ret == 0)
priv->irq_flags = value;
priv->irq_gpio = of_get_named_gpio(np, "cirrus,irq-gpios", 0);
return 0;
}
int madera_irq_probe(struct platform_device *pdev)
{
struct madera *madera = dev_get_drvdata(pdev->dev.parent);
struct madera_irq_priv *priv;
const struct regmap_irq_chip *irq = NULL;
struct irq_data *irq_data;
int flags = IRQF_ONESHOT;
int ret;
dev_info(&pdev->dev, "probe\n");
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->dev = &pdev->dev;
priv->madera = madera;
switch (madera->type) {
case CS47L35:
if (IS_ENABLED(CONFIG_MADERA_IRQ_CS47L35))
irq = &cs47l35_irq;
break;
case CS47L85:
case WM1840:
if (IS_ENABLED(CONFIG_MADERA_IRQ_CS47L85))
irq = &cs47l85_irq;
break;
case CS47L90:
case CS47L91:
if (IS_ENABLED(CONFIG_MADERA_IRQ_CS47L90))
irq = &cs47l90_irq;
break;
default:
dev_err(madera->dev, "Unsupported Madera device type %d\n",
madera->type);
return -EINVAL;
}
if (!irq) {
dev_err(madera->dev, "No support for %s\n",
madera_name_from_type(madera->type));
return -EINVAL;
}
if (IS_ENABLED(CONFIG_OF)) {
if (!dev_get_platdata(priv->dev)) {
ret = madera_irq_of_get(priv);
if (ret < 0)
return ret;
} else {
priv->irq = madera->irq;
priv->irq_flags = madera->pdata.irqchip.irq_flags;
priv->irq_gpio = madera->pdata.irqchip.irq_gpio;
/* pdata uses 0 to mean undefined, convert to an
* invalid GPIO number
*/
if (priv->irq_gpio == 0)
priv->irq_gpio = -1;
}
}
/* Read the flags from the interrupt controller if not specified */
if (!priv->irq_flags) {
irq_data = irq_get_irq_data(priv->irq);
if (!irq_data) {
dev_err(priv->dev, "Invalid IRQ: %d\n", priv->irq);
return -EINVAL;
}
priv->irq_flags = irqd_get_trigger_type(irq_data);
switch (priv->irq_flags) {
case IRQF_TRIGGER_LOW:
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
case IRQF_TRIGGER_FALLING:
break;
case IRQ_TYPE_NONE:
default:
/* Device default */
priv->irq_flags = IRQF_TRIGGER_LOW;
break;
}
}
flags |= priv->irq_flags;
if (flags & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_RISING)) {
ret = regmap_update_bits(madera->regmap, MADERA_IRQ1_CTRL,
MADERA_IRQ_POL_MASK, 0);
if (ret) {
dev_err(priv->dev,
"Couldn't set IRQ polarity: %d\n", ret);
return ret;
}
}
if (flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
/* A GPIO is recommended to emulate edge trigger */
if (gpio_is_valid(priv->irq_gpio)) {
if (gpio_to_irq(priv->irq_gpio) != priv->irq) {
dev_warn(priv->dev,
"IRQ %d is not GPIO %d (%d)\n",
priv->irq, priv->irq_gpio,
gpio_to_irq(priv->irq_gpio));
priv->irq = gpio_to_irq(priv->irq_gpio);
}
ret = devm_gpio_request_one(priv->dev, priv->irq_gpio,
GPIOF_IN, "madera IRQ");
if (ret) {
dev_err(priv->dev,
"Failed to request IRQ GPIO %d: %d\n",
priv->irq_gpio, ret);
return ret;
}
}
dev_dbg(priv->dev, "edge-trigger mode irq_gpio=%d\n",
priv->irq_gpio);
} else {
dev_dbg(priv->dev, "level-trigger mode\n");
}
priv->domain = irq_domain_add_linear(NULL, 1, &madera_domain_ops, priv);
ret = regmap_add_irq_chip(madera->regmap,
irq_create_mapping(priv->domain, 0),
IRQF_ONESHOT, 0, irq,
&priv->irq_data);
if (ret) {
dev_err(priv->dev, "add_irq_chip failed: %d\n", ret);
return ret;
}
ret = request_threaded_irq(priv->irq, NULL, madera_irq_thread,
flags, "madera", priv);
if (ret) {
dev_err(priv->dev,
"Failed to request threaded irq %d: %d\n",
priv->irq, ret);
regmap_del_irq_chip(priv->irq, priv->irq_data);
return ret;
}
platform_set_drvdata(pdev, priv);
madera->irq_dev = priv->dev;
return 0;
}
int madera_irq_remove(struct platform_device *pdev)
{
struct madera_irq_priv *priv = platform_get_drvdata(pdev);
priv->madera->irq_dev = NULL;
regmap_del_irq_chip(priv->irq, priv->irq_data);
free_irq(priv->irq, priv);
return 0;
}
static struct platform_driver madera_irq_driver = {
.probe = madera_irq_probe,
.remove = madera_irq_remove,
.driver = {
.name = "madera-irq",
.pm = &madera_irq_pm_ops,
}
};
module_platform_driver(madera_irq_driver);
MODULE_DESCRIPTION("Madera IRQ driver");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL v2");

View file

@ -1,20 +0,0 @@
/*
* Interrupt support for Cirrus Logic Madera codecs
*
* Copyright 2016 Cirrus Logic
*
* 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 _IRQ_MADERA
#define _IRQ_MADERA
struct regmap_irq_chip;
extern const struct regmap_irq_chip cs47l35_irq;
extern const struct regmap_irq_chip cs47l85_irq;
extern const struct regmap_irq_chip cs47l90_irq;
#endif

View file

@ -1,9 +0,0 @@
DLKM_DIR := motorola/kernel/modules
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := cirrus_madera-core.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk

View file

@ -1,12 +0,0 @@
# add -Wall to try to catch everything we can.
EXTRA_CFLAGS += -Wall
EXTRA_CFLAGS += -I$(TOP)/motorola/kernel/modules/include
ifeq ($(CONFIG_ARCH_SDM450), y)
EXTRA_CFLAGS += -DCONFIG_MFD_CS47L35
cirrus_madera-core-objs = madera-core.o madera-spi.o madera-core.o madera-spi.o cs47l35-tables.o
else
EXTRA_CFLAGS += -DCONFIG_MFD_CS47L90
cirrus_madera-core-objs = madera-core.o madera-spi.o madera-core.o madera-spi.o cs47l90-tables.o
endif
obj-m += cirrus_madera-core.o

View file

@ -1,10 +0,0 @@
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
all:
$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS)
modules_install:
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install
clean:
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,953 +0,0 @@
/*
* Core MFD support for Cirrus Logic Madera codecs
*
* Copyright 2015-2016 Cirrus Logic
*
* 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/delay.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/notifier.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/machine.h>
#include <linux/slab.h>
#include <linux/mfd/madera/core.h>
#include <linux/mfd/madera/registers.h>
#include "madera.h"
#define CS47L35_SILICON_ID 0x6360
#define CS47L85_SILICON_ID 0x6338
#define CS47L90_SILICON_ID 0x6364
struct madera_sysclk_state {
unsigned int fll;
unsigned int sysclk;
};
static const char * const madera_core_supplies[] = {
"AVDD",
"DBVDD1",
};
static const struct mfd_cell madera_ldo1_devs[] = {
{ .name = "madera-ldo1" },
};
static const char * const cs47l35_supplies[] = {
"MICVDD",
"DBVDD2",
"CPVDD1",
"CPVDD2",
"SPKVDD",
};
static const struct mfd_cell cs47l35_devs[] = {
{ .name = "madera-irq" },
{ .name = "madera-micsupp" },
{ .name = "madera-extcon" },
{ .name = "madera-gpio" },
{ .name = "madera-haptics" },
{ .name = "madera-pwm" },
{
.name = "cs47l35-codec",
.parent_supplies = cs47l35_supplies,
.num_parent_supplies = ARRAY_SIZE(cs47l35_supplies),
},
};
static const char * const cs47l85_supplies[] = {
"MICVDD",
"DBVDD2",
"DBVDD3",
"DBVDD4",
"CPVDD1",
"CPVDD2",
"SPKVDDL",
"SPKVDDR",
};
static const struct mfd_cell cs47l85_devs[] = {
{ .name = "madera-irq" },
{ .name = "madera-micsupp" },
{ .name = "madera-extcon" },
{ .name = "madera-gpio" },
{ .name = "madera-haptics" },
{ .name = "madera-pwm" },
{
.name = "cs47l85-codec",
.parent_supplies = cs47l85_supplies,
.num_parent_supplies = ARRAY_SIZE(cs47l85_supplies),
},
};
static const char * const cs47l90_supplies[] = {
"MICVDD",
"DBVDD2",
"DBVDD3",
"DBVDD4",
"CPVDD1",
"CPVDD2",
};
static const struct mfd_cell cs47l90_devs[] = {
{ .name = "madera-irq" },
{ .name = "madera-micsupp" },
{ .name = "madera-extcon" },
{ .name = "madera-gpio" },
{ .name = "madera-haptics" },
{ .name = "madera-pwm" },
{
.name = "cs47l90-codec",
.parent_supplies = cs47l90_supplies,
.num_parent_supplies = ARRAY_SIZE(cs47l90_supplies),
},
};
const char *madera_name_from_type(enum madera_type type)
{
switch (type) {
case CS47L35:
return "CS47L35";
case CS47L85:
return "CS47L85";
case CS47L90:
return "CS47L90";
case CS47L91:
return "CS47L91";
case WM1840:
return "WM1840";
default:
return "Unknown";
}
}
EXPORT_SYMBOL_GPL(madera_name_from_type);
#ifdef CONFIG_OF
const struct of_device_id madera_of_match[] = {
{ .compatible = "cirrus,cs47l35", .data = (void *)CS47L35 },
{ .compatible = "cirrus,cs47l85", .data = (void *)CS47L85 },
{ .compatible = "cirrus,cs47l90", .data = (void *)CS47L90 },
{ .compatible = "cirrus,cs47l91", .data = (void *)CS47L91 },
{ .compatible = "cirrus,wm1840", .data = (void *)WM1840 },
{},
};
EXPORT_SYMBOL_GPL(madera_of_match);
#endif
static int madera_poll_reg(struct madera *madera,
int timeout, unsigned int reg,
unsigned int mask, unsigned int target)
{
unsigned int val = 0;
int ret, i;
for (i = 0; i < timeout; i++) {
ret = regmap_read(madera->regmap, reg, &val);
if (ret != 0) {
dev_err(madera->dev, "Failed to read reg %u: %d\n",
reg, ret);
continue;
}
if ((val & mask) == target)
return 0;
usleep_range(1000, 1010);
}
dev_err(madera->dev, "Polling reg %u timed out: %x\n", reg, val);
return -ETIMEDOUT;
}
static int madera_wait_for_boot(struct madera *madera)
{
int ret, i;
unsigned int timeout = 5;
unsigned int val;
/* ensure chid can read correctly, then check boot done bit */
for (i = 0; i < timeout; i++) {
ret = regmap_read(madera->regmap, MADERA_SOFTWARE_RESET, &val);
if (ret != 0) {
dev_err(madera->dev, "Failed to read chip id, ret %d\n", ret);
continue;
}
if (val == CS47L35_SILICON_ID || val == CS47L90_SILICON_ID)
break;
usleep_range(1000, 1010);
}
if (i >= timeout)
return -ETIMEDOUT;
/*
* We can't use an interrupt as we need to runtime resume to do so,
* we won't race with the interrupt handler as it'll be blocked on
* runtime resume.
*/
ret = madera_poll_reg(madera, 5, MADERA_IRQ1_RAW_STATUS_1,
MADERA_BOOT_DONE_STS1, MADERA_BOOT_DONE_STS1);
if (!ret)
regmap_write(madera->regmap, MADERA_IRQ1_STATUS_1,
MADERA_BOOT_DONE_EINT1);
pm_runtime_mark_last_busy(madera->dev);
return ret;
}
static inline void madera_enable_reset(struct madera *madera)
{
if (gpio_is_valid(madera->pdata.reset))
gpio_set_value_cansleep(madera->pdata.reset, 0);
}
static void madera_disable_reset(struct madera *madera)
{
if (gpio_is_valid(madera->pdata.reset)) {
gpio_set_value_cansleep(madera->pdata.reset, 1);
usleep_range(1000, 1010);
}
}
static int madera_soft_reset(struct madera *madera)
{
int ret;
ret = regmap_write(madera->regmap, MADERA_SOFTWARE_RESET, 0);
if (ret != 0) {
dev_err(madera->dev, "Failed to soft reset device: %d\n", ret);
return ret;
}
usleep_range(1000, 1010);
return 0;
}
static int madera_dcvdd_notify(struct notifier_block *nb,
unsigned long action, void *data)
{
struct madera *madera = container_of(nb, struct madera,
dcvdd_notifier);
dev_dbg(madera->dev, "DCVDD notify %lx\n", action);
if (action & REGULATOR_EVENT_DISABLE)
madera->dcvdd_powered_off = true;
return NOTIFY_DONE;
}
#ifdef CONFIG_PM
static int madera_runtime_resume(struct device *dev)
{
struct madera *madera = dev_get_drvdata(dev);
bool force_reset = false;
int ret;
dev_dbg(madera->dev, "Leaving sleep mode\n");
/* If DCVDD didn't power off we must force a reset so that the
* cache syncs correctly. If we have a hardware reset this must
* be done before powering up DCVDD. If not, we'll use a software
* reset after powering-up DCVDD
*/
if (!madera->dcvdd_powered_off) {
dev_dbg(madera->dev, "DCVDD did not power off, forcing reset\n");
force_reset = true;
madera_enable_reset(madera);
}
ret = regulator_enable(madera->dcvdd);
if (ret) {
dev_err(madera->dev, "Failed to enable DCVDD: %d\n", ret);
return ret;
}
regcache_cache_only(madera->regmap, false);
regcache_cache_only(madera->regmap_32bit, false);
if (force_reset) {
if (gpio_is_valid(madera->pdata.reset)) {
madera_disable_reset(madera);
} else {
ret = madera_soft_reset(madera);
if (ret)
goto err;
}
}
ret = madera_wait_for_boot(madera);
if (ret)
goto err;
ret = regcache_sync(madera->regmap);
if (ret) {
dev_err(madera->dev,
"Failed to restore 16-bit register cache\n");
goto err;
}
ret = regcache_sync(madera->regmap_32bit);
if (ret) {
dev_err(madera->dev,
"Failed to restore 32-bit register cache\n");
goto err;
}
return 0;
err:
regcache_cache_only(madera->regmap_32bit, true);
regcache_cache_only(madera->regmap, true);
madera->dcvdd_powered_off = false;
regulator_disable(madera->dcvdd);
return ret;
}
static int madera_runtime_suspend(struct device *dev)
{
struct madera *madera = dev_get_drvdata(dev);
dev_dbg(madera->dev, "Entering sleep mode\n");
regcache_cache_only(madera->regmap, true);
regcache_mark_dirty(madera->regmap);
regcache_cache_only(madera->regmap_32bit, true);
regcache_mark_dirty(madera->regmap_32bit);
madera->dcvdd_powered_off = false;
regulator_disable(madera->dcvdd);
return 0;
}
#endif
const struct dev_pm_ops madera_pm_ops = {
SET_RUNTIME_PM_OPS(madera_runtime_suspend,
madera_runtime_resume,
NULL)
};
EXPORT_SYMBOL_GPL(madera_pm_ops);
int madera_get_num_micbias(struct madera *madera, unsigned int *n_micbiases,
unsigned int *n_child_micbiases)
{
unsigned int biases, children;
switch (madera->type) {
case CS47L35:
biases = 2;
children = 2;
break;
case CS47L85:
case WM1840:
biases = 4;
children = 0;
break;
default:
biases = 2;
children = 4;
break;
}
if (n_micbiases)
*n_micbiases = biases;
if (n_child_micbiases)
*n_child_micbiases = children;
return 0;
}
EXPORT_SYMBOL_GPL(madera_get_num_micbias);
#ifdef CONFIG_OF
unsigned long madera_of_get_type(struct device *dev)
{
const struct of_device_id *id = of_match_device(madera_of_match, dev);
if (id)
return (unsigned long)id->data;
else
return 0;
}
EXPORT_SYMBOL_GPL(madera_of_get_type);
static void madera_of_report_error(struct madera *madera, const char *prop,
bool mandatory, int err)
{
switch (err) {
case -ENOENT:
if (mandatory)
dev_err(madera->dev,
"Mandatory DT property %s is missing\n", prop);
break;
default:
dev_err(madera->dev,
"DT property %s is malformed: %d\n", prop, err);
break;
}
}
int madera_of_read_uint_array(struct madera *madera, const char *prop,
bool mandatory,
unsigned int *dest, int minlen, int maxlen)
{
struct device_node *np = madera->dev->of_node;
struct property *tempprop;
const __be32 *cur;
u32 val;
int n_elems, i, ret;
n_elems = of_property_count_u32_elems(np, prop);
if (n_elems < 0) {
/* of_property_count_u32_elems uses -EINVAL to mean missing */
if (n_elems == -EINVAL)
ret = -ENOENT;
else
ret = n_elems;
goto err;
}
if (n_elems < minlen) {
ret = -EOVERFLOW;
goto err;
}
if (n_elems == 0)
return 0;
i = 0;
of_property_for_each_u32(np, prop, tempprop, cur, val) {
if (i == maxlen)
break;
dest[i++] = val;
}
return i;
err:
madera_of_report_error(madera, prop, mandatory, ret);
return ret;
}
EXPORT_SYMBOL_GPL(madera_of_read_uint_array);
int madera_of_read_uint(struct madera *madera, const char *prop,
bool mandatory, unsigned int *data)
{
u32 value;
int ret;
ret = of_property_read_u32(madera->dev->of_node, prop, &value);
if (ret < 0) {
/* of_property_read_u32 uses EINVAL to mean missing */
if (ret == -EINVAL)
ret = -ENOENT;
madera_of_report_error(madera, prop, mandatory, ret);
return ret;
}
*data = value;
return 0;
}
EXPORT_SYMBOL_GPL(madera_of_read_uint);
static int madera_of_get_gpio_defaults(struct madera *madera, const char *prop)
{
struct madera_pdata *pdata = &madera->pdata;
int n;
n = madera_of_read_uint_array(madera, prop, false,
pdata->gpio_defaults,
0, ARRAY_SIZE(pdata->gpio_defaults));
if (n < 0)
return n;
/*
* All values are literal except out of range values
* which are chip default, translate into platform
* data which uses 0 as chip default and out of range
* as zero.
*/
while (n > 0) {
--n;
if (pdata->gpio_defaults[n] > 0xffff)
pdata->gpio_defaults[n] = 0; /* use chip default */
else if (pdata->gpio_defaults[n] == 0)
pdata->gpio_defaults[n] = 0xffffffff; /* set to zero */
}
return 0;
}
static int madera_of_get_micbias(struct madera *madera,
const char *prop, int index)
{
int ret, i;
int j = 0;
u32 micbias_config[4 + MADERA_MAX_CHILD_MICBIAS] = {0};
BUILD_BUG_ON(ARRAY_SIZE(madera->pdata.micbias[0].discharge) !=
MADERA_MAX_CHILD_MICBIAS);
ret = madera_of_read_uint_array(madera, prop, false, micbias_config,
ARRAY_SIZE(micbias_config),
ARRAY_SIZE(micbias_config));
if (ret > 0) {
madera->pdata.micbias[index].mV = micbias_config[j++];
madera->pdata.micbias[index].ext_cap = micbias_config[j++];
for (i = 0; i < MADERA_MAX_CHILD_MICBIAS; i++)
madera->pdata.micbias[index].discharge[i] =
micbias_config[j++];
madera->pdata.micbias[index].soft_start = micbias_config[j++];
madera->pdata.micbias[index].bypass = micbias_config[j];
}
return ret;
}
static int madera_of_get_core_pdata(struct madera *madera)
{
struct madera_pdata *pdata = &madera->pdata;
pdata->reset = of_get_named_gpio(madera->dev->of_node,
"reset-gpios", 0);
if (pdata->reset < 0)
madera_of_report_error(madera, "reset-gpios", false,
pdata->reset);
madera_of_read_uint(madera, "cirrus,clk32k-src", false,
&pdata->clk32k_src);
madera_of_get_micbias(madera, "cirrus,micbias1", 0);
madera_of_get_micbias(madera, "cirrus,micbias2", 1);
madera_of_get_micbias(madera, "cirrus,micbias3", 2);
madera_of_get_micbias(madera, "cirrus,micbias4", 3);
/* We have to deal with the gpio defaults here. If none of the pins
* will be used as a GPIO it's not mandatory to include the GPIO
* child driver but the hardware block must still be setup correctly
*/
madera_of_get_gpio_defaults(madera, "cirrus,gpio-defaults");
return 0;
}
#endif
static void madera_configure_gpio(struct madera *madera)
{
unsigned int val;
int i;
/* We can't leave this to the GPIO driver because most of the
* pins are used as digital audio interfaces, not GPIOs,
* so must be configured correctly on boot#
*/
for (i = 0; i < ARRAY_SIZE(madera->pdata.gpio_defaults); i++) {
val = madera->pdata.gpio_defaults[i];
if (val == 0)
continue; /* leave at chip default */
if (val > 0xffff)
val = 0; /* write as zero */
regmap_write(madera->regmap, MADERA_GPIO1_CTRL_1 + i, val);
}
}
static int madera_configure_clk32k(struct madera *madera)
{
unsigned int src_val;
int ret = 0;
switch (madera->pdata.clk32k_src) {
case 0:
/* Default to MCLK2 */
src_val = MADERA_32KZ_MCLK2 - 1;
break;
case MADERA_32KZ_MCLK1:
case MADERA_32KZ_MCLK2:
case MADERA_32KZ_SYSCLK:
src_val = (unsigned int)madera->pdata.clk32k_src - 1;
break;
default:
dev_err(madera->dev, "Invalid 32kHz clock source: %d\n",
madera->pdata.clk32k_src);
return -EINVAL;
}
ret = regmap_update_bits(madera->regmap, MADERA_CLOCK_32K_1,
MADERA_CLK_32K_ENA_MASK | MADERA_CLK_32K_SRC_MASK,
MADERA_CLK_32K_ENA | src_val);
if (ret)
dev_err(madera->dev, "Failed to init 32kHz clock: %d\n", ret);
return ret;
}
static void madera_configure_micbias(struct madera *madera)
{
unsigned int max_micbias = 0, num_child_micbias = 0;
unsigned int val, mask;
int i, j;
madera_get_num_micbias(madera, &max_micbias, &num_child_micbias);
for (i = 0; i < max_micbias; i++) {
if (!madera->pdata.micbias[i].mV &&
!madera->pdata.micbias[i].bypass)
continue;
/* Apply default for bypass mode */
if (!madera->pdata.micbias[i].mV)
madera->pdata.micbias[i].mV = 2800;
val = (madera->pdata.micbias[i].mV - 1500) / 100;
mask = MADERA_MICB1_LVL_MASK | MADERA_MICB1_EXT_CAP |
MADERA_MICB1_BYPASS | MADERA_MICB1_RATE;
val <<= MADERA_MICB1_LVL_SHIFT;
if (madera->pdata.micbias[i].ext_cap)
val |= MADERA_MICB1_EXT_CAP;
if (num_child_micbias == 0) {
mask |= MADERA_MICB1_DISCH;
if (madera->pdata.micbias[i].discharge[0])
val |= MADERA_MICB1_DISCH;
}
if (madera->pdata.micbias[i].soft_start)
val |= MADERA_MICB1_RATE;
if (madera->pdata.micbias[i].bypass)
val |= MADERA_MICB1_BYPASS;
regmap_update_bits(madera->regmap, MADERA_MIC_BIAS_CTRL_1 + i,
mask, val);
if (num_child_micbias) {
val = 0;
mask = 0;
for (j = 0; j < num_child_micbias; j++) {
mask |= (MADERA_MICB1A_DISCH << (j * 4));
if (madera->pdata.micbias[i].discharge[j])
val |= (MADERA_MICB1A_DISCH << (j * 4));
}
regmap_update_bits(madera->regmap,
MADERA_MIC_BIAS_CTRL_5 + (i * 2),
mask, val);
}
}
}
int madera_dev_init(struct madera *madera)
{
struct device *dev = madera->dev;
const char *name;
unsigned int hwid, reg;
int (*patch_fn)(struct madera *) = NULL;
const struct mfd_cell *mfd_devs;
int n_devs, i;
int ret;
dev_set_drvdata(madera->dev, madera);
mutex_init(&madera->reg_setting_lock);
BLOCKING_INIT_NOTIFIER_HEAD(&madera->notifier);
/* default headphone impedance in case the extcon driver is not used */
for (i = 0; i < ARRAY_SIZE(madera->hp_impedance_x100); ++i)
madera->hp_impedance_x100[i] = 3200;
if (dev_get_platdata(madera->dev)) {
memcpy(&madera->pdata, dev_get_platdata(madera->dev),
sizeof(madera->pdata));
/* We use 0 in pdata to indicate a GPIO has not been set,
* translate to -1 so that gpio_is_valid() will work
*/
if (!madera->pdata.reset)
madera->pdata.reset = -1;
} else if (IS_ENABLED(CONFIG_OF)) {
madera_of_get_core_pdata(madera);
}
regcache_cache_only(madera->regmap, true);
regcache_cache_only(madera->regmap_32bit, true);
for (i = 0; i < ARRAY_SIZE(madera_core_supplies); i++)
madera->core_supplies[i].supply = madera_core_supplies[i];
madera->num_core_supplies = ARRAY_SIZE(madera_core_supplies);
switch (madera->type) {
case CS47L35:
case CS47L90:
case CS47L91:
break;
case CS47L85:
case WM1840:
ret = mfd_add_devices(madera->dev, -1, madera_ldo1_devs,
ARRAY_SIZE(madera_ldo1_devs), NULL, 0, NULL);
if (ret != 0) {
dev_err(dev, "Failed to add LDO1 child: %d\n", ret);
return ret;
}
break;
default:
dev_err(madera->dev, "Unknown device type %d\n", madera->type);
return -EINVAL;
}
ret = devm_regulator_bulk_get(dev, madera->num_core_supplies,
madera->core_supplies);
if (ret) {
dev_err(dev, "Failed to request core supplies: %d\n", ret);
goto err_devs;
}
/**
* Don't use devres here because the only device we have to get
* against is the MFD device and DCVDD will likely be supplied by
* one of its children. Meaning that the regulator will be
* destroyed by the time devres calls regulator put.
*/
madera->dcvdd = regulator_get(madera->dev, "DCVDD");
if (IS_ERR(madera->dcvdd)) {
ret = PTR_ERR(madera->dcvdd);
dev_err(dev, "Failed to request DCVDD: %d\n", ret);
goto err_devs;
}
madera->dcvdd_notifier.notifier_call = madera_dcvdd_notify;
ret = regulator_register_notifier(madera->dcvdd,
&madera->dcvdd_notifier);
if (ret) {
dev_err(dev, "Failed to register DCVDD notifier %d\n", ret);
goto err_dcvdd;
}
if (gpio_is_valid(madera->pdata.reset)) {
/* Start out with /RESET low to put the chip into reset */
ret = devm_gpio_request_one(madera->dev, madera->pdata.reset,
GPIOF_DIR_OUT | GPIOF_INIT_LOW,
"madera /RESET");
if (ret) {
dev_err(dev, "Failed to request /RESET: %d\n", ret);
goto err_notifier;
}
}
/* Ensure period of reset asserted before we apply the supplies */
msleep(20);
ret = regulator_bulk_enable(madera->num_core_supplies,
madera->core_supplies);
if (ret) {
dev_err(dev, "Failed to enable core supplies: %d\n", ret);
goto err_notifier;
}
ret = regulator_enable(madera->dcvdd);
if (ret) {
dev_err(dev, "Failed to enable DCVDD: %d\n", ret);
goto err_enable;
}
madera_disable_reset(madera);
regcache_cache_only(madera->regmap, false);
regcache_cache_only(madera->regmap_32bit, false);
/* If we don't have a /RESET GPIO use a soft reset */
if (!madera->pdata.reset) {
ret = madera_soft_reset(madera);
if (ret)
goto err_reset;
}
ret = madera_wait_for_boot(madera);
if (ret) {
dev_err(madera->dev, "Device failed initial boot: %d\n", ret);
goto err_reset;
}
/* Verify that this is a chip we know about before we
* starting doing any writes to its registers
*/
ret = regmap_read(madera->regmap, MADERA_SOFTWARE_RESET, &reg);
if (ret) {
dev_err(dev, "Failed to read ID register: %d\n", ret);
goto err_reset;
}
switch (reg) {
case CS47L35_SILICON_ID:
case CS47L85_SILICON_ID:
case CS47L90_SILICON_ID:
break;
default:
dev_err(madera->dev, "Unknown device ID: %x\n", reg);
ret = -EINVAL;
goto err_reset;
}
/* Read the device ID information & do device specific stuff */
ret = regmap_read(madera->regmap, MADERA_SOFTWARE_RESET, &hwid);
if (ret) {
dev_err(dev, "Failed to read ID register: %d\n", ret);
goto err_reset;
}
ret = regmap_read(madera->regmap, MADERA_HARDWARE_REVISION,
&madera->rev);
if (ret) {
dev_err(dev, "Failed to read revision register: %d\n", ret);
goto err_reset;
}
madera->rev &= MADERA_HW_REVISION_MASK;
name = madera_name_from_type(madera->type);
switch (hwid) {
case CS47L35_SILICON_ID:
if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
switch (madera->type) {
case CS47L35:
patch_fn = cs47l35_patch;
mfd_devs = cs47l35_devs;
n_devs = ARRAY_SIZE(cs47l35_devs);
break;
default:
ret = -EINVAL;
break;
}
} else {
ret = -EINVAL;
}
break;
case CS47L85_SILICON_ID:
if (IS_ENABLED(CONFIG_MFD_CS47L85)) {
switch (madera->type) {
case CS47L85:
case WM1840:
patch_fn = cs47l85_patch;
mfd_devs = cs47l85_devs;
n_devs = ARRAY_SIZE(cs47l85_devs);
break;
default:
ret = -EINVAL;
break;
}
} else {
ret = -EINVAL;
}
break;
case CS47L90_SILICON_ID:
if (IS_ENABLED(CONFIG_MFD_CS47L90)) {
switch (madera->type) {
case CS47L90:
case CS47L91:
patch_fn = cs47l90_patch;
mfd_devs = cs47l90_devs;
n_devs = ARRAY_SIZE(cs47l90_devs);
break;
default:
ret = -EINVAL;
break;
}
} else {
ret = -EINVAL;
}
break;
default:
ret = -EINVAL;
break;
}
if (ret == -EINVAL) {
dev_err(madera->dev, "Device ID 0x%x is not a %s\n",
hwid, name);
goto err_reset;
}
dev_info(dev, "%s silicon revision %d\n", name, madera->rev);
/* Apply hardware patch */
if (patch_fn) {
ret = patch_fn(madera);
if (ret) {
dev_err(madera->dev, "Failed to apply patch %d\n", ret);
goto err_reset;
}
}
madera_configure_gpio(madera);
ret = madera_configure_clk32k(madera);
if (ret)
goto err_reset;
madera_configure_micbias(madera);
pm_runtime_set_active(madera->dev);
pm_runtime_enable(madera->dev);
pm_runtime_set_autosuspend_delay(madera->dev, 100);
pm_runtime_use_autosuspend(madera->dev);
pm_runtime_get(madera->dev);
ret = mfd_add_devices(madera->dev, -1, mfd_devs, n_devs, NULL, 0, NULL);
if (ret) {
dev_err(madera->dev, "Failed to add subdevices: %d\n", ret);
goto err_reset;
}
return 0;
err_reset:
madera_enable_reset(madera);
regulator_disable(madera->dcvdd);
err_enable:
regulator_bulk_disable(madera->num_core_supplies,
madera->core_supplies);
err_notifier:
regulator_unregister_notifier(madera->dcvdd, &madera->dcvdd_notifier);
err_dcvdd:
regulator_put(madera->dcvdd);
err_devs:
mfd_remove_devices(dev);
return ret;
}
EXPORT_SYMBOL_GPL(madera_dev_init);
int madera_dev_exit(struct madera *madera)
{
pm_runtime_disable(madera->dev);
regulator_disable(madera->dcvdd);
regulator_unregister_notifier(madera->dcvdd, &madera->dcvdd_notifier);
regulator_put(madera->dcvdd);
mfd_remove_devices(madera->dev);
madera_enable_reset(madera);
regulator_bulk_disable(madera->num_core_supplies,
madera->core_supplies);
return 0;
}
EXPORT_SYMBOL_GPL(madera_dev_exit);

View file

@ -1,132 +0,0 @@
/*
* SPI bus interface to Cirrus Logic Madera codecs
*
* Copyright 2015 Cirrus Logic
*
* 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/err.h>
#include <linux/spi/spi.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/mfd/madera/core.h>
#include "madera.h"
static int madera_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
struct madera *madera;
const struct regmap_config *regmap_16bit_config = NULL;
const struct regmap_config *regmap_32bit_config = NULL;
unsigned long type;
int ret;
dev_info(&spi->dev, "***********%s***********\n", __func__);
if (spi->dev.of_node)
type = madera_of_get_type(&spi->dev);
else
type = id->driver_data;
switch (type) {
case CS47L35:
if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
regmap_16bit_config = &cs47l35_16bit_spi_regmap;
regmap_32bit_config = &cs47l35_32bit_spi_regmap;
}
break;
case CS47L85:
case WM1840:
if (IS_ENABLED(CONFIG_MFD_CS47L85)) {
regmap_16bit_config = &cs47l85_16bit_spi_regmap;
regmap_32bit_config = &cs47l85_32bit_spi_regmap;
}
break;
case CS47L90:
case CS47L91:
if (IS_ENABLED(CONFIG_MFD_CS47L90)) {
regmap_16bit_config = &cs47l90_16bit_spi_regmap;
regmap_32bit_config = &cs47l90_32bit_spi_regmap;
}
break;
default:
dev_err(&spi->dev,
"Unknown Madera SPI device type %ld\n", type);
return -EINVAL;
}
if (!regmap_16bit_config) {
dev_err(&spi->dev,
"Kernel does not include support for %s\n",
madera_name_from_type(type));
return -EINVAL;
}
madera = devm_kzalloc(&spi->dev, sizeof(*madera), GFP_KERNEL);
if (!madera)
return -ENOMEM;
madera->regmap = devm_regmap_init_spi(spi, regmap_16bit_config);
if (IS_ERR(madera->regmap)) {
ret = PTR_ERR(madera->regmap);
dev_err(&spi->dev,
"Failed to allocate 16-bit register map: %d\n", ret);
return ret;
}
madera->regmap_32bit = devm_regmap_init_spi(spi, regmap_32bit_config);
if (IS_ERR(madera->regmap_32bit)) {
ret = PTR_ERR(madera->regmap_32bit);
dev_err(&spi->dev,
"Failed to allocate 32-bit register map: %d\n", ret);
return ret;
}
madera->type = type;
madera->dev = &spi->dev;
madera->irq = spi->irq;
return madera_dev_init(madera);
}
static int madera_spi_remove(struct spi_device *spi)
{
struct madera *madera = spi_get_drvdata(spi);
madera_dev_exit(madera);
return 0;
}
static const struct spi_device_id madera_spi_ids[] = {
{ "cs47l35", CS47L35 },
{ "cs47l85", CS47L85 },
{ "cs47l90", CS47L90 },
{ "cs47l91", CS47L91 },
{ "wm1840", WM1840 },
{ },
};
MODULE_DEVICE_TABLE(spi, madera_spi_ids);
static struct spi_driver madera_spi_driver = {
.driver = {
.name = "madera",
.owner = THIS_MODULE,
.pm = &madera_pm_ops,
.of_match_table = of_match_ptr(madera_of_match),
},
.probe = madera_spi_probe,
.remove = madera_spi_remove,
.id_table = madera_spi_ids,
};
module_spi_driver(madera_spi_driver);
MODULE_DESCRIPTION("Madera SPI bus interface");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL v2");

View file

@ -1,54 +0,0 @@
/*
* madera.h -- MFD internals for Cirrus Logic Madera codecs
*
* Copyright 2015-2016 Cirrus Logic
*
* 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 _MADERA_MFD_H
#define _MADERA_MFD_H
#include <linux/pm.h>
#include <linux/of.h>
struct madera;
extern const struct dev_pm_ops madera_pm_ops;
extern const struct of_device_id madera_of_match[];
int madera_dev_init(struct madera *madera);
int madera_dev_exit(struct madera *madera);
int madera_irq_init(struct madera *madera);
int madera_irq_exit(struct madera *madera);
#ifdef CONFIG_OF
unsigned long madera_of_get_type(struct device *dev);
#else
static inline unsigned long madera_of_get_type(struct device *dev)
{
return 0;
}
#endif
extern const struct regmap_config cs47l35_16bit_spi_regmap;
extern const struct regmap_config cs47l35_32bit_spi_regmap;
extern const struct regmap_config cs47l35_16bit_i2c_regmap;
extern const struct regmap_config cs47l35_32bit_i2c_regmap;
extern int cs47l35_patch(struct madera *madera);
extern const struct regmap_config cs47l85_16bit_spi_regmap;
extern const struct regmap_config cs47l85_32bit_spi_regmap;
extern const struct regmap_config cs47l85_16bit_i2c_regmap;
extern const struct regmap_config cs47l85_32bit_i2c_regmap;
extern int cs47l85_patch(struct madera *madera);
extern const struct regmap_config cs47l90_16bit_spi_regmap;
extern const struct regmap_config cs47l90_32bit_spi_regmap;
extern const struct regmap_config cs47l90_16bit_i2c_regmap;
extern const struct regmap_config cs47l90_32bit_i2c_regmap;
extern int cs47l90_patch(struct madera *madera);
#endif

View file

@ -1,14 +0,0 @@
DLKM_DIR := motorola/kernel/modules
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := madera-ldo1.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk
include $(CLEAR_VARS)
LOCAL_MODULE := madera-micsupp.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk

View file

@ -1,5 +0,0 @@
# add -Wall to try to catch everything we can.
EXTRA_CFLAGS += -Wall
EXTRA_CFLAGS += -I$(TOP)/motorola/kernel/modules/include
obj-m += madera-ldo1.o madera-micsupp.o

View file

@ -1,10 +0,0 @@
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
all:
$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS)
modules_install:
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install
clean:
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean

View file

@ -1,208 +0,0 @@
/*
* madera-ldo1.c -- Driver for the LDO1 regulator on Madera codecs
*
* Copyright 2015-2016 Cirrus Logic
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/bitops.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/regulator/madera-ldo1.h>
#include <linux/mfd/madera/core.h>
#include <linux/mfd/madera/pdata.h>
#include <linux/mfd/madera/registers.h>
struct madera_ldo1 {
struct regulator_dev *regulator;
struct regulator_consumer_supply supply;
struct regulator_init_data init_data;
};
static const struct regulator_ops madera_ldo1_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
};
static const struct regulator_desc madera_ldo1 = {
.name = "LDO1",
.supply_name = "LDOVDD",
.type = REGULATOR_VOLTAGE,
.ops = &madera_ldo1_ops,
.vsel_reg = MADERA_LDO1_CONTROL_1,
.vsel_mask = MADERA_LDO1_VSEL_MASK,
.min_uV = 900000,
.uV_step = 25000,
.n_voltages = 13,
.enable_time = 3000,
.owner = THIS_MODULE,
};
static const struct regulator_init_data madera_ldo1_default = {
.constraints = {
.min_uV = 1200000,
.max_uV = 1200000,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = 1,
};
static int madera_ldo1_of_get_pdata(struct madera *madera,
struct regulator_config *config,
const struct regulator_desc *desc)
{
struct madera_pdata *pdata = &madera->pdata;
struct madera_ldo1 *ldo1 = config->driver_data;
struct device_node *init_node, *dcvdd_node;
struct regulator_init_data *init_data;
init_node = of_get_child_by_name(madera->dev->of_node, "ldo1");
dcvdd_node = of_parse_phandle(madera->dev->of_node, "DCVDD-supply", 0);
if (init_node) {
config->of_node = init_node;
init_data = of_get_regulator_init_data(madera->dev, init_node,
desc);
if (init_data) {
init_data->consumer_supplies = &ldo1->supply;
init_data->num_consumer_supplies = 1;
if (dcvdd_node && dcvdd_node != init_node)
madera->internal_dcvdd = false;
pdata->ldo1.init_data = init_data;
}
} else if (dcvdd_node) {
madera->internal_dcvdd = false;
}
if (madera->internal_dcvdd) {
pdata->ldo1.ldoena = of_get_named_gpio(madera->dev->of_node,
"cirrus,ldoena-gpios",
0);
if (pdata->ldo1.ldoena < 0) {
if (pdata->ldo1.ldoena != -ENOENT)
dev_warn(madera->dev,
"Malformed cirrus,ldoena-gpios ignored: %d\n",
pdata->ldo1.ldoena);
pdata->ldo1.ldoena = 0;
}
}
of_node_put(dcvdd_node);
return 0;
}
static int madera_ldo1_probe(struct platform_device *pdev)
{
struct madera *madera = dev_get_drvdata(pdev->dev.parent);
const struct regulator_desc *desc;
struct regulator_config config = { };
struct madera_ldo1 *ldo1;
int ret;
madera->internal_dcvdd = true;
ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL);
if (!ldo1)
return -ENOMEM;
/*
* Since the chip usually supplies itself we provide some
* default init_data for it. This will be overridden with
* platform data if provided.
*/
desc = &madera_ldo1;
ldo1->init_data = madera_ldo1_default;
ldo1->init_data.consumer_supplies = &ldo1->supply;
ldo1->supply.supply = "DCVDD";
ldo1->supply.dev_name = dev_name(madera->dev);
config.dev = madera->dev;
config.driver_data = ldo1;
config.regmap = madera->regmap;
if (IS_ENABLED(CONFIG_OF)) {
if (!dev_get_platdata(madera->dev)) {
ret = madera_ldo1_of_get_pdata(madera, &config, desc);
if (ret < 0)
return ret;
}
}
/* pdata entries default to 0 if not explicitly set. If the
* value is 0 this means 'undefined'
*/
if (madera->pdata.ldo1.ldoena == 0)
madera->pdata.ldo1.ldoena = -1;
if (madera->pdata.ldo1.init_data)
ldo1->init_data = *madera->pdata.ldo1.init_data;
config.ena_gpio = madera->pdata.ldo1.ldoena;
config.ena_gpio_flags = GPIOF_OUT_INIT_LOW;
config.init_data = &ldo1->init_data;
/*
* LDO1 can only be used to supply DCVDD so if it has no
* consumers then DCVDD is supplied externally.
*/
if (config.init_data->num_consumer_supplies == 0)
madera->internal_dcvdd = false;
ldo1->regulator = devm_regulator_register(&pdev->dev, desc, &config);
of_node_put(config.of_node);
if (IS_ERR(ldo1->regulator)) {
ret = PTR_ERR(ldo1->regulator);
dev_err(madera->dev, "Failed to register LDO1 supply: %d\n",
ret);
return ret;
}
platform_set_drvdata(pdev, ldo1);
return 0;
}
static struct platform_driver madera_ldo1_driver = {
.probe = madera_ldo1_probe,
.driver = {
.name = "madera-ldo1",
},
};
module_platform_driver(madera_ldo1_driver);
MODULE_DESCRIPTION("Madera LDO1 driver");
MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.wolfsonmicro.com>");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:madera-ldo1");

View file

@ -1,322 +0,0 @@
/*
* madera-micsupp.c -- Driver for the mic supply regulator on Madera codecs
*
* Copyright 2015-2016 Cirrus Logic
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <sound/soc.h>
#include <linux/regulator/madera-micsupp.h>
#include <linux/mfd/madera/core.h>
#include <linux/mfd/madera/pdata.h>
#include <linux/mfd/madera/registers.h>
struct madera_micsupp {
struct regulator_dev *regulator;
struct madera *madera;
struct regulator_consumer_supply supply;
struct regulator_init_data init_data;
struct work_struct check_cp_work;
};
static void madera_micsupp_check_cp(struct work_struct *work)
{
struct madera_micsupp *micsupp =
container_of(work, struct madera_micsupp, check_cp_work);
struct snd_soc_dapm_context *dapm = micsupp->madera->dapm;
struct madera *madera = micsupp->madera;
struct regmap *regmap = madera->regmap;
unsigned int reg;
int ret;
if (dapm) {
ret = regmap_read(regmap, MADERA_MIC_CHARGE_PUMP_1, &reg);
if (ret) {
dev_err(madera->dev,
"Failed to read CP state: %d\n", ret);
return;
}
if ((reg & (MADERA_CPMIC_ENA | MADERA_CPMIC_BYPASS)) ==
MADERA_CPMIC_ENA) {
snd_soc_dapm_enable_pin(dapm, "MICSUPP");
madera->micvdd_regulated = true;
} else {
snd_soc_dapm_disable_pin(dapm, "MICSUPP");
madera->micvdd_regulated = false;
}
snd_soc_dapm_sync(dapm);
}
}
static int madera_micsupp_enable(struct regulator_dev *rdev)
{
struct madera_micsupp *micsupp = rdev_get_drvdata(rdev);
int ret;
ret = regulator_enable_regmap(rdev);
if (ret == 0)
schedule_work(&micsupp->check_cp_work);
return ret;
}
static int madera_micsupp_disable(struct regulator_dev *rdev)
{
struct madera_micsupp *micsupp = rdev_get_drvdata(rdev);
int ret;
ret = regulator_disable_regmap(rdev);
if (ret == 0)
schedule_work(&micsupp->check_cp_work);
return ret;
}
static int madera_micsupp_set_bypass(struct regulator_dev *rdev, bool ena)
{
struct madera_micsupp *micsupp = rdev_get_drvdata(rdev);
int ret;
ret = regulator_set_bypass_regmap(rdev, ena);
udelay(1000);
if (ret == 0)
schedule_work(&micsupp->check_cp_work);
return ret;
}
static const struct regulator_ops madera_micsupp_ops = {
.enable = madera_micsupp_enable,
.disable = madera_micsupp_disable,
.is_enabled = regulator_is_enabled_regmap,
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_bypass = regulator_get_bypass_regmap,
.set_bypass = madera_micsupp_set_bypass,
};
static const struct regulator_linear_range madera_micsupp_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0, 0x14, 25000),
REGULATOR_LINEAR_RANGE(1500000, 0x15, 0x27, 100000),
};
static const struct regulator_desc madera_micsupp = {
.name = "MICVDD",
.supply_name = "CPVDD1",
.type = REGULATOR_VOLTAGE,
.n_voltages = 40,
.ops = &madera_micsupp_ops,
.vsel_reg = MADERA_LDO2_CONTROL_1,
.vsel_mask = MADERA_LDO2_VSEL_MASK,
.enable_reg = MADERA_MIC_CHARGE_PUMP_1,
.enable_mask = MADERA_CPMIC_ENA,
.bypass_reg = MADERA_MIC_CHARGE_PUMP_1,
.bypass_mask = MADERA_CPMIC_BYPASS,
.linear_ranges = madera_micsupp_ranges,
.n_linear_ranges = ARRAY_SIZE(madera_micsupp_ranges),
.enable_time = 3000,
.owner = THIS_MODULE,
};
static const struct regulator_init_data madera_micsupp_default = {
.constraints = {
.valid_ops_mask = REGULATOR_CHANGE_STATUS |
REGULATOR_CHANGE_VOLTAGE |
REGULATOR_CHANGE_BYPASS,
.min_uV = 900000,
.max_uV = 3300000,
},
.num_consumer_supplies = 1,
};
static int madera_micsupp_of_get_pdata(struct madera *madera,
struct regulator_config *config,
const struct regulator_desc *desc)
{
struct madera_pdata *pdata = &madera->pdata;
struct madera_micsupp *micsupp = config->driver_data;
struct device_node *np;
struct regulator_init_data *init_data;
np = of_get_child_by_name(madera->dev->of_node, "micvdd");
if (np) {
config->of_node = np;
init_data = of_get_regulator_init_data(madera->dev, np, desc);
if (init_data) {
init_data->consumer_supplies = &micsupp->supply;
init_data->num_consumer_supplies = 1;
pdata->micsupp.init_data = init_data;
}
}
return 0;
}
static unsigned int madera_get_max_micbias(struct madera *madera)
{
unsigned int num_micbias, i, micbias_mv;
unsigned int max_micbias = 0;
int ret;
madera_get_num_micbias(madera, &num_micbias, NULL);
for (i = 0; i < num_micbias; i++) {
ret = regmap_read(madera->regmap, MADERA_MIC_BIAS_CTRL_1 + i,
&micbias_mv);
if (ret) {
dev_err(madera->dev,
"Failed to read micbias level: %d\n", ret);
return 0;
}
micbias_mv = (micbias_mv & MADERA_MICB1_LVL_MASK) >>
MADERA_MICB1_LVL_SHIFT;
micbias_mv = 1500 + (100 * micbias_mv);
if (micbias_mv > max_micbias)
max_micbias = micbias_mv;
}
return max_micbias * 1000;
}
static int madera_micsupp_probe(struct platform_device *pdev)
{
struct madera *madera = dev_get_drvdata(pdev->dev.parent);
const struct regulator_desc *desc;
struct regulator_config config = { };
struct madera_micsupp *micsupp;
int ret;
unsigned int max_micbias;
micsupp = devm_kzalloc(&pdev->dev, sizeof(*micsupp), GFP_KERNEL);
if (!micsupp)
return -ENOMEM;
micsupp->madera = madera;
INIT_WORK(&micsupp->check_cp_work, madera_micsupp_check_cp);
/*
* Since the chip usually supplies itself we provide some
* default init_data for it. This will be overridden with
* platform data if provided.
*/
desc = &madera_micsupp;
micsupp->init_data = madera_micsupp_default;
micsupp->init_data.consumer_supplies = &micsupp->supply;
micsupp->supply.supply = "MICVDD";
micsupp->supply.dev_name = dev_name(madera->dev);
config.dev = madera->dev;
config.driver_data = micsupp;
config.regmap = madera->regmap;
if (IS_ENABLED(CONFIG_OF)) {
if (!dev_get_platdata(madera->dev)) {
ret = madera_micsupp_of_get_pdata(madera, &config,
desc);
if (ret < 0)
return ret;
}
}
max_micbias = madera_get_max_micbias(madera);
if (max_micbias) {
/* micvdd must be 200mV more than maximum micbias */
max_micbias += 200000;
if (micsupp->init_data.constraints.max_uV >= max_micbias) {
micsupp->init_data.constraints.max_uV = max_micbias;
micsupp->init_data.constraints.min_uV = max_micbias;
micsupp->init_data.constraints.apply_uV = true;
micsupp->init_data.constraints.valid_ops_mask &=
~REGULATOR_CHANGE_VOLTAGE;
}
}
if (madera->pdata.micsupp.init_data)
config.init_data = madera->pdata.micsupp.init_data;
else
config.init_data = &micsupp->init_data;
if (max_micbias) {
if (config.init_data->constraints.max_uV < max_micbias)
dev_err(madera->dev,
"micvdd must be atleast set to %duV\n",
max_micbias);
}
/* Default to bypassed mode */
regmap_update_bits(madera->regmap, MADERA_MIC_CHARGE_PUMP_1,
MADERA_CPMIC_BYPASS, MADERA_CPMIC_BYPASS);
micsupp->regulator = devm_regulator_register(&pdev->dev, desc,
&config);
of_node_put(config.of_node);
if (IS_ERR(micsupp->regulator)) {
ret = PTR_ERR(micsupp->regulator);
dev_err(madera->dev, "Failed to register mic supply: %d\n",
ret);
return ret;
}
platform_set_drvdata(pdev, micsupp);
return 0;
}
static struct platform_driver madera_micsupp_driver = {
.probe = madera_micsupp_probe,
.driver = {
.name = "madera-micsupp",
},
};
module_platform_driver(madera_micsupp_driver);
/* Module information */
MODULE_DESCRIPTION("Madera microphone supply driver");
MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.wolfsonmicro.com>");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:madera-micsupp");

View file

@ -1,68 +0,0 @@
/*
* Device Tree defines for Madera codec extcon driver
*
* Copyright 2016 Cirrus Logic
*
* 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 DT_BINDINGS_EXTCON_MADERA_H
#define DT_BINDINGS_EXTCON_MADERA_H
/* output clamp pin for cirrus,hpd-pins */
#define MADERA_HPD_OUT_OUT1L 0
#define MADERA_HPD_OUT_OUT1R 1
#define MADERA_HPD_OUT_OUT2L 2
#define MADERA_HPD_OUT_OUT2R 3
/* Sense pin selection for cirrus,hpd-pins */
#define MADERA_HPD_SENSE_MICDET1 0
#define MADERA_HPD_SENSE_MICDET2 1
#define MADERA_HPD_SENSE_MICDET3 2
#define MADERA_HPD_SENSE_MICDET4 3
#define MADERA_HPD_SENSE_HPDET1 4
#define MADERA_HPD_SENSE_HPDET2 5
#define MADERA_HPD_SENSE_JD1 6
#define MADERA_HPD_SENSE_JD2 7
/* source setting for cirrus,micd-configs (cs47l35, cs47l85) */
#define MADERA_ACCD_SENSE_MICDET1 0
#define MADERA_ACCD_SENSE_MICDET2 1
/* bias setting for cirrus,micd-configs (cs47l35, cs47l85) */
#define MADERA_ACCD_BIAS_SRC_MICBIAS1 1
#define MADERA_ACCD_BIAS_SRC_MICBIAS2 2
/* source setting for cirrus,micd-configs */
#define MADERA_MICD1_SENSE_MICDET1 0
#define MADERA_MICD1_SENSE_MICDET2 1
#define MADERA_MICD1_SENSE_MICDET3 2
#define MADERA_MICD1_SENSE_MICDET4 3
/* ground setting for cirrus,micd-configs */
#define MADERA_MICD1_GND_MICDET1 0
#define MADERA_MICD1_GND_MICDET2 1
#define MADERA_MICD1_GND_MICDET3 2
#define MADERA_MICD1_GND_MICDET4 3
/* bias setting for cirrus,micd-configs */
#define MADERA_MICD_BIAS_SRC_MICBIAS1A 0x0
#define MADERA_MICD_BIAS_SRC_MICBIAS1B 0x1
#define MADERA_MICD_BIAS_SRC_MICBIAS1C 0x2
#define MADERA_MICD_BIAS_SRC_MICBIAS1D 0x3
#define MADERA_MICD_BIAS_SRC_MICBIAS2A 0x4
#define MADERA_MICD_BIAS_SRC_MICBIAS2B 0x5
#define MADERA_MICD_BIAS_SRC_MICBIAS2C 0x6
#define MADERA_MICD_BIAS_SRC_MICBIAS2D 0x7
#define MADERA_MICD_BIAS_SRC_MICVDD 0xF
/* HP gnd setting for cirrus,micd-configs */
#define MADERA_HPD_GND_HPOUTFB1 0
#define MADERA_HPD_GND_HPOUTFB2 1
#define MADERA_HPD_GND_HPOUTFB3 2
#define MADERA_HPD_GND_HPOUTFB4 3
#endif

View file

@ -1,123 +0,0 @@
/*
* Device Tree defines for Madera codecs
*
* Copyright 2015-2016 Cirrus Logic
*
* 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 _DT_BINDINGS_MFD_MADERA_H
#define _DT_BINDINGS_MFD_MADERA_H
/* GPIO Function Definitions */
#define MADERA_GP_FN_ALTERNATE 0x00
#define MADERA_GP_FN_GPIO 0x01
#define MADERA_GP_FN_DSP_GPIO 0x02
#define MADERA_GP_FN_IRQ1 0x03
#define MADERA_GP_FN_IRQ2 0x04
#define MADERA_GP_FN_FLL1_CLOCK 0x10
#define MADERA_GP_FN_FLL2_CLOCK 0x11
#define MADERA_GP_FN_FLL3_CLOCK 0x12
#define MADERA_GP_FN_FLLAO_CLOCK 0x13
#define MADERA_GP_FN_FLL1_LOCK 0x18
#define MADERA_GP_FN_FLL2_LOCK 0x19
#define MADERA_GP_FN_FLL3_LOCK 0x1A
#define MADERA_GP_FN_FLLAO_LOCK 0x1B
#define MADERA_GP_FN_OPCLK_OUT 0x40
#define MADERA_GP_FN_OPCLK_ASYNC_OUT 0x41
#define MADERA_GP_FN_PWM1 0x48
#define MADERA_GP_FN_PWM2 0x49
#define MADERA_GP_FN_SPDIF_OUT 0x4C
#define MADERA_GP_FN_HEADPHONE_DET 0x50
#define MADERA_GP_FN_MIC_DET 0x58
#define MADERA_GP_FN_DRC1_SIGNAL_DETECT 0x80
#define MADERA_GP_FN_DRC2_SIGNAL_DETECT 0x81
#define MADERA_GP_FN_ASRC1_IN1_LOCK 0x88
#define MADERA_GP_FN_ASRC1_IN2_LOCK 0x89
#define MADERA_GP_FN_ASRC2_IN1_LOCK 0x8A
#define MADERA_GP_FN_ASRC2_IN2_LOCK 0x8B
#define MADERA_GP_FN_DSP_IRQ1 0xA0
#define MADERA_GP_FN_DSP_IRQ2 0xA1
#define MADERA_GP_FN_DSP_IRQ3 0xA2
#define MADERA_GP_FN_DSP_IRQ4 0xA3
#define MADERA_GP_FN_DSP_IRQ5 0xA4
#define MADERA_GP_FN_DSP_IRQ6 0xA5
#define MADERA_GP_FN_DSP_IRQ7 0xA6
#define MADERA_GP_FN_DSP_IRQ8 0xA7
#define MADERA_GP_FN_DSP_IRQ9 0xA8
#define MADERA_GP_FN_DSP_IRQ10 0xA9
#define MADERA_GP_FN_DSP_IRQ11 0xAA
#define MADERA_GP_FN_DSP_IRQ12 0xAB
#define MADERA_GP_FN_DSP_IRQ13 0xAC
#define MADERA_GP_FN_DSP_IRQ14 0xAD
#define MADERA_GP_FN_DSP_IRQ15 0xAE
#define MADERA_GP_FN_DSP_IRQ16 0xAF
#define MADERA_GP_FN_HPOUT1L_SC 0xB0
#define MADERA_GP_FN_HPOUT1R_SC 0xB1
#define MADERA_GP_FN_HPOUT2L_SC 0xB2
#define MADERA_GP_FN_HPOUT2R_SC 0xB3
#define MADERA_GP_FN_HPOUT3L_SC 0xB4
#define MADERA_GP_FN_HPOUT4R_SC 0xB5
#define MADERA_GP_FN_SPKOUTL_SC 0xB6
#define MADERA_GP_FN_SPKOUTR_SC 0xB7
#define MADERA_GP_FN_HPOUT1L_ENA 0xC0
#define MADERA_GP_FN_HPOUT1R_ENA 0xC1
#define MADERA_GP_FN_HPOUT2L_ENA 0xC2
#define MADERA_GP_FN_HPOUT2R_ENA 0xC3
#define MADERA_GP_FN_HPOUT3L_ENA 0xC4
#define MADERA_GP_FN_HPOUT4R_ENA 0xC5
#define MADERA_GP_FN_SPKOUTL_ENA 0xC6
#define MADERA_GP_FN_SPKOUTR_ENA 0xC7
#define MADERA_GP_FN_HPOUT1L_DIS 0xD0
#define MADERA_GP_FN_HPOUT1R_DIS 0xD1
#define MADERA_GP_FN_HPOUT2L_DIS 0xD2
#define MADERA_GP_FN_HPOUT2R_DIS 0xD3
#define MADERA_GP_FN_HPOUT3L_DIS 0xD4
#define MADERA_GP_FN_HPOUT4R_DIS 0xD5
#define MADERA_GP_FN_SPKOUTL_DIS 0xD6
#define MADERA_GP_FN_SPKOUTR_DIS 0xD7
#define MADERA_GP_FN_SPK_SHUTDOWN 0xE0
#define MADERA_GP_FN_SPK_OVH_SHUTDOWN 0xE1
#define MADERA_GP_FN_SPK_OVH_WARN 0xE2
#define MADERA_GP_FN_TIMER1_STATUS 0x140
#define MADERA_GP_FN_TIMER2_STATUS 0x141
#define MADERA_GP_FN_TIMER3_STATUS 0x142
#define MADERA_GP_FN_TIMER4_STATUS 0x143
#define MADERA_GP_FN_TIMER5_STATUS 0x144
#define MADERA_GP_FN_TIMER6_STATUS 0x145
#define MADERA_GP_FN_TIMER7_STATUS 0x146
#define MADERA_GP_FN_TIMER8_STATUS 0x147
#define MADERA_GP_FN_EVENTLOG1_FIFO_STS 0x150
#define MADERA_GP_FN_EVENTLOG2_FIFO_STS 0x151
#define MADERA_GP_FN_EVENTLOG3_FIFO_STS 0x152
#define MADERA_GP_FN_EVENTLOG4_FIFO_STS 0x153
#define MADERA_GP_FN_EVENTLOG5_FIFO_STS 0x154
#define MADERA_GP_FN_EVENTLOG6_FIFO_STS 0x155
#define MADERA_GP_FN_EVENTLOG7_FIFO_STS 0x156
#define MADERA_GP_FN_EVENTLOG8_FIFO_STS 0x157
/* GPIOn_CTRL_1 Configuration Bits */
#define MADERA_GPN_LVL 0x8000
#define MADERA_GPN_OP_CFG_MASK 0x4000
#define MADERA_GPN_DB_MASK 0x2000
#define MADERA_GPN_POL_MASK 0x0800
/* GPIOn_CTRL_2 Configuration Bits */
#define MADERA_GPN_DIR_MASK 0x8000
#define MADERA_GPN_PU_MASK 0x4000
#define MADERA_GPN_PD_MASK 0x2000
/* Provide some defines for the most common GPIO configs */
#define MADERA_GP_DEFAULT 0xffffffff
#define MADERA_GP_BUSKEEP (MADERA_GPN_PU_MASK | MADERA_GPN_PD_MASK)
#define MADERA_GP_OUTPUT MADERA_GP_FN_GPIO
#define MADERA_GP_INPUT (MADERA_GP_FN_GPIO | MADERA_GPN_DIR)
#define MADERA_32KZ_MCLK1 1
#define MADERA_32KZ_MCLK2 2
#define MADERA_32KZ_SYSCLK 3
#endif

View file

@ -1,18 +0,0 @@
/*
* Device Tree defines for Madera codecs
*
* Copyright 2016 Cirrus Logic
*
* 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 _DT_BINDINGS_SOUND_MADERA_H
#define _DT_BINDINGS_SOUND_MADERA_H
#define MADERA_INMODE_DIFF 0
#define MADERA_INMODE_SE 1
#define MADERA_INMODE_DMIC 2
#endif

View file

@ -1,156 +0,0 @@
/*
* Platform data for Madera codecs
*
* Copyright 2017 Cirrus Logic
*
* 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 EXTCON_MADERA_PDATA_H
#define EXTCON_MADERA_PDATA_H
#include <linux/kernel.h>
#define MADERA_MAX_ACCESSORY 1
/* Treat INT_MAX impedance as open circuit */
#define MADERA_HP_Z_OPEN INT_MAX
struct madera_jd_state;
/** Bias and sense configuration for probing MICDET */
struct madera_micd_config {
/** cs47l35, cs47l85, WM1840: value of the ACCDET_SRC field
* other codecs: value of MICDn_SENSE_SEL field
* See datasheet for field values
*/
u32 src;
/** cs47l35, cs47l85, wm1840: unused
* other codecs: value of MICDn_GND_SEL
*
* See datasheet for field values
*/
u32 gnd;
/** MICBIAS number to enable */
u32 bias;
/** State of polarity gpio during probe (true == gpio asserted) */
bool gpio;
/** cs47l35, cs47l85, wm1840: unused
* other codecs: value of HPn_GND_SEL
*
* See datasheet for field values
*/
u32 hp_gnd;
};
struct madera_micd_range {
int max; /** Ohms */
int key; /** Key to report to input layer */
};
/** pdata sub-structure for accessory detect configuration */
struct madera_accdet_pdata {
/** set to true to enable this accessory detect */
bool enabled;
/** which output this accdet is for (1 = OUT1, ...) */
u32 output;
/** Time in milliseconds to keep wake lock during jack detection */
u32 jd_wake_time;
/** Set whether JD2 is used for jack detection */
bool jd_use_jd2;
/** set to true if jackdet contact opens on insert */
bool jd_invert;
/** If non-zero don't run headphone detection, just report this value
* Specified as hundredths-of-an-ohm, that is (ohms * 100)
*/
u32 fixed_hpdet_imp_x100;
/** Impedance of external series resistor on hpdet.
* Specified as hundredths-of-an-ohm, that is (ohms * 100)
*/
u32 hpdet_ext_res_x100;
/** If non-zero, specifies the maximum impedance in ohms
* that will be considered as a short circuit.
*/
u32 hpdet_short_circuit_imp;
/**
* Channel to use for headphone detection, valid values are 0 for
* left and 1 for right
*/
u32 hpdet_channel;
/* Extra delay time to wait the headset plug in totally (milliseconds) */
u32 init_mic_delay_ms;
/** Extra debounce timeout during initial mic detect (milliseconds) */
u32 micd_detect_debounce_ms;
/** Extra software debounces during button detection */
u32 micd_manual_debounce;
/** GPIO for mic detection polarity */
int micd_pol_gpio;
/** Mic detect ramp rate */
u32 micd_bias_start_time;
/** Setting for the codec MICD_RATE field
* See the datasheet for documentation of the field values
*/
u32 micd_rate;
/** Mic detect debounce level */
u32 micd_dbtime;
/** Mic detect timeout (milliseconds) */
u32 micd_timeout_ms;
/** Mic detect clamp function */
u32 micd_clamp_mode;
/** Force MICBIAS on for mic detect */
bool micd_force_micbias;
/** Declare an open circuit as a 4 pole jack */
bool micd_open_circuit_declare;
/** Use software comparison to determine mic presence */
bool micd_software_compare;
/** Mic detect level parameters */
const struct madera_micd_range *micd_ranges;
int num_micd_ranges;
/** Headset polarity configurations */
const struct madera_micd_config *micd_configs;
int num_micd_configs;
/**
* 4 entries:
* [HPL_clamp_pin, HPL_impedance_measurement_pin,
* HPR_clamp_pin, HPR_impedance_measurement_pin]
*
* 0 = use default setting
* values 0x1..0xffff = set to this value
* >0xffff = set to 0
*/
u32 hpd_pins[4];
/** Override the normal jack detection */
const struct madera_jd_state *custom_jd;
};
#endif

View file

@ -1,163 +0,0 @@
/*
* extcon-madera.h - public extcon driver API for Cirrus Logic Madera codecs
*
* Copyright 2015-2017 Cirrus Logic
*
* 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 EXTCON_MADERA_H
#define EXTCON_MADERA_H
#include <linux/mfd/madera/registers.h>
/* Conversion between ohms and hundredths of an ohm. */
static inline unsigned int madera_hohm_to_ohm(unsigned int hohms)
{
if (hohms == INT_MAX)
return hohms;
else
return (hohms + 50) / 100;
}
static inline unsigned int madera_ohm_to_hohm(unsigned int ohms)
{
if (ohms >= (INT_MAX / 100))
return INT_MAX;
else
return ohms * 100;
}
#define MADERA_MICD_LVL_1_TO_7 \
(MADERA_MICD_LVL_1 | MADERA_MICD_LVL_2 | \
MADERA_MICD_LVL_3 | MADERA_MICD_LVL_4 | \
MADERA_MICD_LVL_5 | MADERA_MICD_LVL_6 | \
MADERA_MICD_LVL_7)
#define MADERA_MICD_LVL_0_TO_7 (MADERA_MICD_LVL_0 | MADERA_MICD_LVL_1_TO_7)
#define MADERA_MICD_LVL_0_TO_8 (MADERA_MICD_LVL_0_TO_7 | MADERA_MICD_LVL_8)
/* Notify data structure for MADERA_NOTIFY_HPDET */
struct madera_hpdet_notify_data {
unsigned int impedance_x100; /* ohms * 100 */
};
/* Notify data structure for MADERA_NOTIFY_MICDET */
struct madera_micdet_notify_data {
unsigned int impedance_x100; /* ohms * 100 */
bool present;
int out_num; /* 1 = OUT1, 2 = OUT2 */
};
struct madera_micd_bias {
unsigned int bias;
bool enabled;
};
struct madera_hpdet_trims {
int off_x4;
int grad_x4;
};
struct madera_extcon {
struct device *dev;
struct madera *madera;
const struct madera_accdet_pdata *pdata;
struct mutex lock;
struct regulator *micvdd;
struct input_dev *input;
struct extcon_dev *edev;
struct gpio_desc *micd_pol_gpio[2];
struct gpio_desc *usbc_det_gpio[2];
u16 last_jackdet;
int hp_tuning_level;
const struct madera_hpdet_calibration_data *hpdet_ranges;
int num_hpdet_ranges;
unsigned int hpdet_init_range;
const struct madera_hpdet_trims *hpdet_trims;
int micd_mode;
const struct madera_micd_config *micd_modes;
int num_micd_modes;
const struct madera_micd_range *micd_ranges;
int num_micd_ranges;
int micd_res_old;
int micd_debounce;
int micd_count;
struct completion manual_mic_completion;
struct delayed_work micd_detect_work;
bool have_mic;
bool detecting;
int jack_flips;
const struct madera_jd_state *state;
const struct madera_jd_state *old_state;
struct delayed_work state_timeout_work;
struct madera_micd_bias micd_bias;
bool usbc_headset_support;
bool usbc_connected;
struct notifier_block psy_nb;
struct power_supply *usb_psy;
};
enum madera_accdet_mode {
MADERA_ACCDET_MODE_MIC,
MADERA_ACCDET_MODE_HPL,
MADERA_ACCDET_MODE_HPR,
MADERA_ACCDET_MODE_HPM,
MADERA_ACCDET_MODE_ADC,
MADERA_ACCDET_MODE_INVALID,
};
struct madera_jd_state {
enum madera_accdet_mode mode;
int (*start)(struct madera_extcon *);
void (*restart)(struct madera_extcon *);
int (*reading)(struct madera_extcon *, int);
void (*stop)(struct madera_extcon *);
int (*timeout_ms)(struct madera_extcon *);
void (*timeout)(struct madera_extcon *);
};
int madera_jds_set_state(struct madera_extcon *info,
const struct madera_jd_state *new_state);
void madera_set_headphone_imp(struct madera_extcon *info, int ohms_x100);
extern const struct madera_jd_state madera_hpdet_left;
extern const struct madera_jd_state madera_hpdet_right;
extern const struct madera_jd_state madera_micd_button;
extern const struct madera_jd_state madera_micd_microphone;
extern const struct madera_jd_state madera_micd_adc_mic;
int madera_hpdet_start(struct madera_extcon *info);
void madera_hpdet_restart(struct madera_extcon *info);
void madera_hpdet_stop(struct madera_extcon *info);
int madera_hpdet_reading(struct madera_extcon *info, int val);
int madera_micd_start(struct madera_extcon *info);
void madera_micd_stop(struct madera_extcon *info);
int madera_micd_button_reading(struct madera_extcon *info, int val);
int madera_micd_mic_start(struct madera_extcon *info);
void madera_micd_mic_stop(struct madera_extcon *info);
int madera_micd_mic_reading(struct madera_extcon *info, int val);
int madera_micd_mic_timeout_ms(struct madera_extcon *info);
void madera_micd_mic_timeout(struct madera_extcon *info);
void madera_extcon_report(struct madera_extcon *info, int which, bool attached);
#endif

View file

@ -1,25 +0,0 @@
/*
* Platform data for Cirrus Logic Madera codecs irqchip driver
*
* Copyright 2016 Cirrus Logic
*
* 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 _IRQCHIP_MADERA_PDATA_H
#define _IRQCHIP_MADERA_PDATA_H
struct madera_irqchip_pdata {
/** Mode for primary IRQ (defaults to active low) */
unsigned int irq_flags;
/** GPIO for primary IRQ
* Required if the codec IRQ output is connected to an edge-triggered
* input on the host interrupt controller
*/
int irq_gpio;
};
#endif

View file

@ -1,98 +0,0 @@
/*
* Interrupt support for Cirrus Logic Madera codecs
*
* Copyright 2016 Cirrus Logic
*
* 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 _IRQCHIP_MADERA_H
#define _IRQCHIP_MADERA_H
#define MADERA_IRQ_BOOT_DONE 0
#define MADERA_IRQ_CTRLIF_ERR 1
#define MADERA_IRQ_FLL1_LOCK 2
#define MADERA_IRQ_FLL2_LOCK 3
#define MADERA_IRQ_FLL3_LOCK 4
#define MADERA_IRQ_FLLAO_LOCK 5
#define MADERA_IRQ_CLK_SYS_ERR 6
#define MADERA_IRQ_CLK_ASYNC_ERR 7
#define MADERA_IRQ_CLK_DSP_ERR 8
#define MADERA_IRQ_HPDET 9
#define MADERA_IRQ_MICDET1 10
#define MADERA_IRQ_MICDET2 11
#define MADERA_IRQ_JD1_RISE 12
#define MADERA_IRQ_JD1_FALL 13
#define MADERA_IRQ_JD2_RISE 14
#define MADERA_IRQ_JD2_FALL 15
#define MADERA_IRQ_MICD_CLAMP_RISE 16
#define MADERA_IRQ_MICD_CLAMP_FALL 17
#define MADERA_IRQ_DRC2_SIG_DET 18
#define MADERA_IRQ_DRC1_SIG_DET 19
#define MADERA_IRQ_ASRC1_IN1_LOCK 20
#define MADERA_IRQ_ASRC1_IN2_LOCK 21
#define MADERA_IRQ_ASRC2_IN1_LOCK 22
#define MADERA_IRQ_ASRC2_IN2_LOCK 23
#define MADERA_IRQ_DSP_IRQ1 24
#define MADERA_IRQ_DSP_IRQ2 25
#define MADERA_IRQ_DSP_IRQ3 26
#define MADERA_IRQ_DSP_IRQ4 27
#define MADERA_IRQ_DSP_IRQ5 28
#define MADERA_IRQ_DSP_IRQ6 29
#define MADERA_IRQ_DSP_IRQ7 30
#define MADERA_IRQ_DSP_IRQ8 31
#define MADERA_IRQ_DSP_IRQ9 32
#define MADERA_IRQ_DSP_IRQ10 33
#define MADERA_IRQ_DSP_IRQ11 34
#define MADERA_IRQ_DSP_IRQ12 35
#define MADERA_IRQ_DSP_IRQ13 36
#define MADERA_IRQ_DSP_IRQ14 37
#define MADERA_IRQ_DSP_IRQ15 38
#define MADERA_IRQ_DSP_IRQ16 39
#define MADERA_IRQ_HP1L_SC 40
#define MADERA_IRQ_HP1R_SC 41
#define MADERA_IRQ_HP2L_SC 42
#define MADERA_IRQ_HP2R_SC 43
#define MADERA_IRQ_HP3L_SC 44
#define MADERA_IRQ_HP3R_SC 45
#define MADERA_IRQ_SPKOUTL_SC 46
#define MADERA_IRQ_SPKOUTR_SC 47
#define MADERA_IRQ_HP1L_ENABLE_DONE 48
#define MADERA_IRQ_HP1R_ENABLE_DONE 49
#define MADERA_IRQ_HP2L_ENABLE_DONE 50
#define MADERA_IRQ_HP2R_ENABLE_DONE 51
#define MADERA_IRQ_HP3L_ENABLE_DONE 52
#define MADERA_IRQ_HP3R_ENABLE_DONE 53
#define MADERA_IRQ_SPKOUTL_ENABLE_DONE 54
#define MADERA_IRQ_SPKOUTR_ENABLE_DONE 55
#define MADERA_IRQ_SPK_SHUTDOWN 56
#define MADERA_IRQ_SPK_OVERHEAT 57
#define MADERA_IRQ_SPK_OVERHEAT_WARN 58
#define MADERA_IRQ_GPIO1 59
#define MADERA_IRQ_GPIO2 60
#define MADERA_IRQ_GPIO3 61
#define MADERA_IRQ_GPIO4 62
#define MADERA_IRQ_GPIO5 63
#define MADERA_IRQ_GPIO6 64
#define MADERA_IRQ_GPIO7 65
#define MADERA_IRQ_GPIO8 66
#define MADERA_IRQ_DSP1_BUS_ERROR 67
#define MADERA_IRQ_DSP2_BUS_ERROR 68
#define MADERA_IRQ_DSP3_BUS_ERROR 69
#define MADERA_IRQ_DSP4_BUS_ERROR 70
#define MADERA_IRQ_DSP5_BUS_ERROR 71
#define MADERA_IRQ_DSP6_BUS_ERROR 72
#define MADERA_IRQ_DSP7_BUS_ERROR 73
#define MADERA_NUM_IRQ 74
struct madera;
extern int madera_request_irq(struct madera *madera, int irq, const char *name,
irq_handler_t handler, void *data);
extern void madera_free_irq(struct madera *madera, int irq, void *data);
extern int madera_set_irq_wake(struct madera *madera, int irq, int on);
#endif

View file

@ -1,103 +0,0 @@
/*
* Madera MFD internals
*
* Copyright 2015-2016 Cirrus Logic
*
* 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 _MADERA_CORE_H
#define _MADERA_CORE_H
#include <linux/interrupt.h>
#include <linux/regmap.h>
#include <linux/notifier.h>
#include <linux/regulator/consumer.h>
#include <linux/mfd/madera/pdata.h>
#include <linux/irqchip/irq-madera.h>
enum madera_type {
CS47L35 = 1,
CS47L85 = 2,
CS47L90 = 3,
CS47L91 = 4,
WM1840 = 7,
};
#define MADERA_MAX_CORE_SUPPLIES 2
/* Notifier events */
#define MADERA_NOTIFY_VOICE_TRIGGER 0x1
#define MADERA_NOTIFY_HPDET 0x2
#define MADERA_NOTIFY_MICDET 0x4
struct snd_soc_dapm_context;
struct madera_extcon_info;
struct madera {
struct regmap *regmap;
struct regmap *regmap_32bit;
struct device *dev;
enum madera_type type;
unsigned int rev;
int num_core_supplies;
struct regulator_bulk_data core_supplies[MADERA_MAX_CORE_SUPPLIES];
struct regulator *dcvdd;
struct notifier_block dcvdd_notifier;
bool internal_dcvdd;
bool micvdd_regulated;
bool bypass_cache;
bool dcvdd_powered_off;
struct madera_pdata pdata;
struct device *irq_dev;
int irq;
unsigned int out_clamp[MADERA_MAX_OUTPUT];
unsigned int out_shorted[MADERA_MAX_OUTPUT];
bool hpdet_clamp[MADERA_MAX_ACCESSORY];
unsigned int hp_ena;
unsigned int hp_impedance_x100[MADERA_MAX_ACCESSORY];
struct madera_extcon_info *extcon_info;
struct snd_soc_dapm_context *dapm;
struct mutex reg_setting_lock;
struct blocking_notifier_head notifier;
};
extern int madera_of_read_uint_array(struct madera *madera, const char *prop,
bool mandatory,
unsigned int *dest,
int minlen, int maxlen);
extern int madera_of_read_uint(struct madera *madera, const char *prop,
bool mandatory, unsigned int *data);
extern int madera_get_num_micbias(struct madera *madera,
unsigned int *n_micbiases,
unsigned int *n_child_micbiases);
extern const char *madera_name_from_type(enum madera_type type);
static inline int madera_of_read_int(struct madera *madera, const char *prop,
bool mandatory, int *data)
{
return madera_of_read_uint(madera, prop, mandatory,
(unsigned int *)data);
}
static inline int madera_call_notifiers(struct madera *madera,
unsigned long event,
void *data)
{
return blocking_notifier_call_chain(&madera->notifier, event, data);
}
#endif

View file

@ -1,94 +0,0 @@
/*
* Platform data for Madera codecs
*
* Copyright 2015-2016 Cirrus Logic
*
* 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 _MADERA_PDATA_H
#define _MADERA_PDATA_H
#include <linux/kernel.h>
#include <dt-bindings/mfd/madera.h>
#include <linux/regulator/madera-ldo1.h>
#include <linux/regulator/madera-micsupp.h>
#include <linux/irqchip/irq-madera-pdata.h>
#include <sound/madera-pdata.h>
#include <linux/extcon/extcon-madera-pdata.h>
#define MADERA_MAX_GPIO_REGS 80
#define CS47L35_NUM_GPIOS 16
#define CS47L85_NUM_GPIOS 40
#define CS47L90_NUM_GPIOS 38
#define MADERA_MAX_MICBIAS 4
#define MADERA_MAX_CHILD_MICBIAS 4
#define MADERA_MAX_GPSW 2
struct regulator_init_data;
struct madera_micbias {
int mV; /** Regulated voltage */
unsigned int ext_cap:1; /** External capacitor fitted */
unsigned int discharge[MADERA_MAX_CHILD_MICBIAS]; /** Actively discharge */
unsigned int soft_start:1; /** Disable aggressive startup ramp rate */
unsigned int bypass:1; /** Use bypass mode */
};
struct madera_pdata {
int reset; /** GPIO controlling /RESET, if any */
/** Substruct of pdata for the LDO1 regulator */
struct madera_ldo1_pdata ldo1;
/** Substruct of pdata for the MICSUPP regulator */
struct madera_micsupp_pdata micsupp;
/** Substruct of pdata for the irqchip driver */
struct madera_irqchip_pdata irqchip;
/** If a direct 32kHz clock is provided on an MCLK specify it here */
unsigned int clk32k_src;
/** Base GPIO */
int gpio_base;
/** Pin state for GPIO pins
* Defines default pin function and state for each GPIO. The values in
* here are written into the GPn_CONFIGx register block. There are
* two entries for each GPIO pin, for the GPn_CONFIG1 and GPn_CONFIG2
* registers.
*
* See the codec datasheet for a description of the contents of the
* GPn_CONFIGx registers.
*
* 0 = leave at chip default
* values 0x1..0xffff = set to this value
* 0xffffffff = set to 0
*/
unsigned int gpio_defaults[MADERA_MAX_GPIO_REGS];
/** MICBIAS configurations */
struct madera_micbias micbias[MADERA_MAX_MICBIAS];
/** Substructure of pdata for the ASoC codec driver
* See include/sound/madera-pdata.h
*/
struct madera_codec_pdata codec;
/** General purpose switch mode setting
* See the SW1_MODE field in the datasheet for the available values
*/
unsigned int gpsw[MADERA_MAX_GPSW];
/** Accessory detection configurations */
struct madera_accdet_pdata accdet[MADERA_MAX_ACCESSORY];
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,24 +0,0 @@
/*
* Platform data for Madera codecs LDO1 regulator
*
* Copyright 2016 Cirrus Logic
*
* 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 _MADERA_LDO1_H_
#define _MADERA_LDO1_H_
struct regulator_init_data;
struct madera_ldo1_pdata {
/** GPIO controlling LODENA, if any */
int ldoena;
/** Regulator configuration for LDO1 */
const struct regulator_init_data *init_data;
};
#endif

View file

@ -1,21 +0,0 @@
/*
* Platform data for Madera codecs MICSUPP regulator
*
* Copyright 2016 Cirrus Logic
*
* 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 _MADERA_MICSUPP_H_
#define _MADERA_MICSUPP_H_
struct regulator_init_data;
struct madera_micsupp_pdata {
/** Regulator configuration for MICSUPP */
const struct regulator_init_data *init_data;
};
#endif

View file

@ -1,102 +0,0 @@
/*
* linux/sound/cs35l35.h -- Platform data for CS35l35
*
* Copyright (c) 2016 Cirrus Logic Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __CS35L35_H
#define __CS35L35_H
struct classh_cfg {
/*
* Class H Algorithm Control Variables
* You can either have it done
* automatically or you can adjust
* these variables for tuning
*
* if you do not enable the internal algorithm
* you will get a set of mixer controls for
* Class H tuning
*
* Section 4.3 of the datasheet
*/
/* Internal ClassH Algorithm */
bool classh_bst_override;
bool classh_algo_enable;
int classh_bst_max_limit;
int classh_mem_depth;
int classh_release_rate;
int classh_headroom;
int classh_wk_fet_disable;
int classh_wk_fet_delay;
int classh_wk_fet_thld;
int classh_vpch_auto;
int classh_vpch_rate;
int classh_vpch_man;
};
struct monitor_cfg {
/*
* Signal Monitor Data
* highly configurable signal monitoring
* data positioning and different types of
* monitoring data.
*
* Section 4.8.2 - 4.8.4 of the datasheet
*/
bool is_present;
bool imon_specs;
bool vmon_specs;
bool vpmon_specs;
bool vbstmon_specs;
bool vpbrstat_specs;
bool zerofill_specs;
u8 imon_dpth;
u8 imon_loc;
u8 imon_frm;
u8 vmon_dpth;
u8 vmon_loc;
u8 vmon_frm;
u8 vpmon_dpth;
u8 vpmon_loc;
u8 vpmon_frm;
u8 vbstmon_dpth;
u8 vbstmon_loc;
u8 vbstmon_frm;
u8 vpbrstat_dpth;
u8 vpbrstat_loc;
u8 vpbrstat_frm;
u8 zerofill_dpth;
u8 zerofill_loc;
u8 zerofill_frm;
};
struct cs35l35_platform_data {
/* Stereo (2 Device) */
bool stereo;
/* serial port drive strength */
int sp_drv_str;
/* Boost Power Down with FET */
bool bst_pdn_fet_on;
/* Boost Voltage : used if ClassH Algo Enabled */
int bst_vctl;
/* Amp Gain Zero Cross */
bool gain_zc;
/* Audio Input Location */
int aud_channel;
/* Advisory Input Location */
int adv_channel;
/* Shared Boost for stereo */
bool shared_bst;
/* ClassH Algorithm */
struct classh_cfg classh_algo;
/* Monitor Config */
struct monitor_cfg mon_cfg;
};
#endif /* __CS35L35_H */

View file

@ -1,51 +0,0 @@
/*
* linux/sound/cs35l36.h -- Platform data for CS35L36
*
* Copyright (c) 2016 Cirrus Logic Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __CS35L36_H
#define __CS35L36_H
/* INT/GPIO pin configuration */
struct irq_cfg {
bool is_present;
int irq_drv_sel;
int irq_pol;
int irq_gpio_sel;
int irq_out_en;
int irq_src_sel;
};
struct cs35l36_platform_data {
bool sclk_frc;
bool lrclk_frc;
bool multi_amp_mode;
bool dcm_mode;
int ldm_mode_sel;
bool amp_gain_zc;
bool amp_pcm_inv;
bool pdm_ldm_exit;
bool pdm_ldm_enter;
bool imon_pol_inv;
bool vmon_pol_inv;
int boost_ind;
int bst_vctl;
int bst_vctl_sel;
int bst_ipk;
int vpr_en;
int vpr_thrld;
int vpr_atk_vol;
int vpr_atk_rate;
int vpr_wait;
int vpr_rel_rate;
bool extern_boost;
int temp_warn_thld;
struct irq_cfg irq_config;
};
#endif /* __CS35L36_H */

View file

@ -1,82 +0,0 @@
/*
* linux/sound/cs35l41.h -- Platform data for CS35L41
*
* Copyright (c) 2018 Cirrus Logic Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __CS35L41_H
#define __CS35L41_H
struct classh_cfg {
bool classh_bst_override;
bool classh_algo_enable;
int classh_bst_max_limit;
int classh_mem_depth;
int classh_release_rate;
int classh_headroom;
int classh_wk_fet_delay;
int classh_wk_fet_thld;
};
struct irq_cfg {
bool is_present;
bool irq_pol_inv;
bool irq_out_en;
int irq_src_sel;
};
struct cs35l41_platform_data {
bool sclk_frc;
bool lrclk_frc;
bool right_channel;
bool amp_gain_zc;
bool ng_enable;
int bst_ind;
int bst_vctrl;
int bst_ipk;
int bst_cap;
int temp_warn_thld;
int ng_pcm_thld;
int ng_delay;
int dout_hiz;
struct irq_cfg irq_config1;
struct irq_cfg irq_config2;
struct classh_cfg classh_config;
};
struct cs35l41_private {
struct wm_adsp dsp; /* needs to be first member */
struct snd_soc_codec *codec;
struct cs35l41_platform_data pdata;
struct device *dev;
struct regmap *regmap;
struct regulator_bulk_data supplies[2];
int num_supplies;
int irq;
int clksrc;
int extclk_freq;
int extclk_cfg;
int sclk;
unsigned int cspl_cmd;
unsigned int gpi_glob_en;
bool dspa_mode;
bool i2s_mode;
bool swire_mode;
bool halo_booted;
bool enabled;
bool bus_spi;
struct mutex rate_lock;
/* GPIO for /RST */
struct gpio_desc *reset_gpio;
struct completion global_pup_done;
struct completion global_pdn_done;
};
int cs35l41_probe(struct cs35l41_private *cs35l41,
struct cs35l41_platform_data *pdata);
#endif /* __CS35L41_H */

View file

@ -1,74 +0,0 @@
/*
* Platform data for Madera codec driver
*
* Copyright 2016 Cirrus Logic
*
* 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 _MADERA_CODEC_PDATA_H
#define _MADERA_CODEC_PDATA_H
#include <linux/kernel.h>
#include <dt-bindings/mfd/madera.h>
#define MADERA_MAX_INPUT 6
#define MADERA_MAX_MUXED_CHANNELS 4
#define MADERA_MAX_OUTPUT 6
#define MADERA_MAX_AIF 4
#define MADERA_MAX_PDM_SPK 2
#define MADERA_MAX_DSP 7
struct madera_codec_pdata {
/**
* Maximum number of channels that clocks will be generated for,
* useful for systems where an I2S bus with multiple data
* lines is mastered.
*/
int max_channels_clocked[MADERA_MAX_AIF];
/** Reference voltage for DMIC inputs */
int dmic_ref[MADERA_MAX_INPUT];
/** Clock Source for DMICs
* The meaning of the values here depends on the codec. See the
* datasheet for a list of valid values for the INn_DMIC_SUP fields
* [0] = IN1, [1]=IN2 [2]=IN3
*/
int dmic_clksrc[MADERA_MAX_INPUT];
/** Mode of input structures
* One of the MADERA_INMODE_xxx values
* Two-dimensional array [input_number][channel number]
* Four slots per input in the order:
* [n][0]=INnAL [n][1]=INnAR [n][2]=INnBL [n][3]=INnBR
*/
int inmode[MADERA_MAX_INPUT][MADERA_MAX_MUXED_CHANNELS];
/** Output mono mode control
* For each output set the value to TRUE to indicate that
* the output is mono
* [0]=OUT1, [1]=OUT2, ...
*/
bool out_mono[MADERA_MAX_OUTPUT];
/** PDM mute control settings.
* See the PDM_SPKn_CTRL_1 register in the datasheet for the
* meaning of the values.
*/
unsigned int pdm_mute[MADERA_MAX_PDM_SPK];
/** PDM speaker format
* See the PDM_SPKn_FMT field in the datasheet for the
* meaning of the values
*/
unsigned int pdm_fmt[MADERA_MAX_PDM_SPK];
/** Override default list of firmwares */
struct wm_adsp_fw_defs *fw_defs[MADERA_MAX_DSP];
int num_fw_defs[MADERA_MAX_DSP];
};
#endif

View file

@ -1,59 +1,6 @@
DLKM_DIR := motorola/kernel/modules
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := cirrus_madera.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk
include $(CLEAR_VARS)
LOCAL_MODULE := cirrus_wm_adsp.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk
include $(CLEAR_VARS)
LOCAL_MODULE := cirrus_cs35l35.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk
include $(CLEAR_VARS)
LOCAL_MODULE := cirrus_cs35l36.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk
include $(CLEAR_VARS)
LOCAL_MODULE := cirrus_cs47l35.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk
include $(CLEAR_VARS)
LOCAL_MODULE := cirrus_cs47l90.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk
include $(CLEAR_VARS)
LOCAL_MODULE := aov_trigger.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk
include $(CLEAR_VARS)
ifeq ($(CIRRUS_AMP_CODEC),cs35l41_spi)
KERNEL_CFLAGS += CONFIG_SND_SOC_CS35L41_SPI=y
else ifeq ($(CIRRUS_AMP_CODEC),cs35l41_i2c)
KERNEL_CFLAGS += CONFIG_SND_SOC_CS35L41_I2C=y
endif
LOCAL_MODULE := cirrus_cs35l41.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk
include $(CLEAR_VARS)
LOCAL_MODULE := cirrus_playback.ko
LOCAL_MODULE_TAGS := optional

View file

@ -14,7 +14,6 @@ EXTRA_CFLAGS += -I$(TOP)/kernel/techpack/audio/include
EXTRA_CFLAGS += -I$(TOP)/kernel/techpack/audio/include/uapi
endif
EXTRA_CFLAGS += -DCONFIG_SND_SOC_AOV_TRIGGER
ifneq (,$(filter channel%, $(TARGET_PRODUCT)))
EXTRA_CFLAGS += -DCONFIG_TAS2560_REGMAP -DCONFIG_TAS2560_CODEC -DCONFIG_TAS2560_MISC -DCONFIG_SND_SOC_TAS2560
@ -31,34 +30,6 @@ EXTRA_CFLAGS += -DTFA98XX_GIT_VERSIONS=\"$(GIT_VERSION)\"
EXTRA_CFLAGS += -DTFA9874_NONDSP_STEREO
EXTRA_CFLAGS += -I$(TOP)/motorola/kernel/modules/sound/soc/codecs/inc
EXTRA_CFLAGS += -Werror
cirrus_madera-objs = madera.o madera-slimbus.o
obj-m += cirrus_madera.o
cirrus_wm_adsp-objs = wm_adsp.o
obj-m += cirrus_wm_adsp.o
cirrus_cs35l35-objs = cs35l35.o
obj-m += cirrus_cs35l35.o
cirrus_cs35l36-objs = cs35l36.o cs35l36-tables.o
obj-m += cirrus_cs35l36.o
cirrus_cs47l35-objs = cs47l35.o
obj-m += cirrus_cs47l35.o
cirrus_cs47l90-objs = cs47l90.o
obj-m += cirrus_cs47l90.o
obj-m += aov_trigger.o
cirrus_cs35l41-objs = cs35l41.o cs35l41-tables.o
obj-m += cirrus_cs35l41.o
ifneq ($(filter m y,$(CONFIG_SND_SOC_CS35L41_SPI)),)
cirrus_cs35l41-objs += cs35l41-spi.o
else
cirrus_cs35l41-objs += cs35l41-i2c.o
endif
cirrus_playback-objs = msm-cirrus-playback.o
obj-m += cirrus_playback.o

View file

@ -1,313 +0,0 @@
/*
* Copyright (c) 2014, Motorola Mobility, LLC.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only 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/errno.h>
#include <linux/export.h>
#include <linux/kobject.h>
#include <linux/mutex.h>
#include <linux/printk.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <sound/soc.h>
// #include <linux/wakelock.h>
#include <linux/mfd/madera/core.h>
#include "madera.h"
#define MAX_DSP_TO_CHECK 4
#define MAX_NUM_PANIC_CODE 4
struct dsp_event_info {
int panic;
int event;
u16 panic_code[MAX_NUM_PANIC_CODE];
};
static bool aov_trigger_active;
static struct kobject aov_trigger_kobj;
static struct snd_soc_codec *aov_codec;
static struct notifier_block aov_trigger_nb;
static struct wakeup_source aov_wake_src;
static struct dsp_event_info dsp_info[MAX_DSP_TO_CHECK];
static DEFINE_MUTEX(dsp_info_mutex);
static struct attribute aov_sysfs_attr_trigger = {
.name = "trigger",
.mode = S_IRUSR | S_IRGRP
};
static struct attribute aov_sysfs_attr_register = {
.name = "register",
.mode = S_IWUSR | S_IWGRP
};
static struct attribute aov_sysfs_attr_event = {
.name = "event",
.mode = S_IRUSR | S_IRGRP
};
static const char *reg_cmd = "register";
static const char *unreg_cmd = "unregister";
static int aov_trigger_notify(struct notifier_block *nb,
unsigned long event, void *data)
{
struct madera_voice_trigger_info *trig_info = data;
int dsp;
if (aov_codec == NULL)
return -EPERM;
/*
* Once a trigger is received, unregister from
* trigger notification. Client needs to re-arm
* the rigger.
*/
dev_dbg(aov_codec->dev, "received madera notity event: 0x%lx", event);
if ((event == MADERA_NOTIFY_VOICE_TRIGGER) &&
(trig_info->core_num >= 0) &&
(trig_info->core_num < MAX_DSP_TO_CHECK)) {
dsp = trig_info->core_num;
switch (trig_info->code) {
case MADERA_TRIGGER_VOICE:
if (!aov_trigger_active)
return 0;
aov_trigger_active = false;
dev_info(aov_codec->dev,
"DSP%d: notify aov trigger.", dsp);
sysfs_notify(&aov_trigger_kobj, NULL,
aov_sysfs_attr_trigger.name);
__pm_wakeup_event(&aov_wake_src, 500);
break;
case MADERA_TRIGGER_TEXT:
mutex_lock(&dsp_info_mutex);
dsp_info[dsp].event = 1;
mutex_unlock(&dsp_info_mutex);
dev_info(aov_codec->dev,
"DSP%d: aov notify text event.", dsp);
sysfs_notify(&aov_trigger_kobj, NULL,
aov_sysfs_attr_event.name);
break;
case MADERA_TRIGGER_PANIC:
mutex_lock(&dsp_info_mutex);
dsp_info[dsp].panic = 1;
memcpy(dsp_info[dsp].panic_code, trig_info->err_msg,
sizeof(u16) * MAX_NUM_PANIC_CODE);
mutex_unlock(&dsp_info_mutex);
dev_info(aov_codec->dev,
"DSP%d: aov notify panic.", dsp);
sysfs_notify(&aov_trigger_kobj, NULL,
aov_sysfs_attr_event.name);
break;
}
}
return 0;
}
static void aov_register_trigger(void)
{
if (aov_codec == NULL)
return;
aov_trigger_active = true;
dev_dbg(aov_codec->dev, "registered aov trigger.");
}
static void aov_unregister_trigger(void)
{
if (aov_codec == NULL)
return;
aov_trigger_active = false;
dev_dbg(aov_codec->dev, "unregistered aov trigger.");
}
static void aov_sysfs_release(struct kobject *kobj)
{
aov_codec = NULL;
}
static ssize_t aov_sysfs_show(struct kobject *kobj,
struct attribute *attr, char *buf)
{
int i, j;
int count;
char *ptr = buf;
if (attr != &aov_sysfs_attr_event)
return 0;
mutex_lock(&dsp_info_mutex);
for (i = 0; i < MAX_DSP_TO_CHECK; i++) {
count = scnprintf(ptr, PAGE_SIZE - (ptr - buf),
"dsp %d: panic:%d event:%d code:",
i, dsp_info[i].panic, dsp_info[i].event);
ptr += count;
for (j = 0; j < MAX_NUM_PANIC_CODE; j++) {
count = scnprintf(ptr, PAGE_SIZE - (ptr - buf),
"%04x", dsp_info[i].panic_code[j]);
ptr += count;
}
count = scnprintf(ptr, PAGE_SIZE - (ptr - buf), "\n");
ptr += count;
}
memset(dsp_info, 0, sizeof(struct dsp_event_info) * MAX_DSP_TO_CHECK);
mutex_unlock(&dsp_info_mutex);
return ptr - buf;
}
static ssize_t aov_sysfs_store(struct kobject *kobj,
struct attribute *attr,
const char *buf, size_t count)
{
ssize_t ret = -EIO;
if (attr != &aov_sysfs_attr_register)
return ret;
if (!strncmp(reg_cmd, buf, strlen(reg_cmd))) {
aov_register_trigger();
ret = count;
} else if (!strncmp(unreg_cmd, buf, strlen(unreg_cmd))) {
aov_unregister_trigger();
ret = count;
}
return ret;
}
static const struct sysfs_ops aov_sysfs_ops = {
.show = aov_sysfs_show,
.store = aov_sysfs_store,
};
static struct kobj_type ktype_aov_trigger = {
.sysfs_ops = &aov_sysfs_ops,
.default_attrs = NULL,
.release = aov_sysfs_release,
};
void aov_trigger_register_notifier(struct snd_soc_codec *codec)
{
if (!aov_codec) {
aov_trigger_nb.notifier_call = aov_trigger_notify;
aov_codec = codec;
madera_register_notifier(aov_codec, &aov_trigger_nb);
}
}
EXPORT_SYMBOL_GPL(aov_trigger_register_notifier);
static int aov_trigger_probe(struct platform_device *pdev)
{
int ret = 0;
static int aov_trigger_init_called;
if (aov_trigger_init_called)
return ret;
aov_trigger_init_called = 1;
ret = kobject_init_and_add(&aov_trigger_kobj,
&ktype_aov_trigger,
kernel_kobj, "aov");
if (ret)
goto exit;
sysfs_attr_init(&aov_sysfs_attr_trigger);
ret = sysfs_create_file(&aov_trigger_kobj,
&aov_sysfs_attr_trigger);
if (ret) {
dev_err(&pdev->dev,
"%s: trigger node creation failed, ret=%d\n",
__func__, ret);
goto exit_remove_kobj;
}
sysfs_attr_init(&aov_sysfs_attr_register);
ret = sysfs_create_file(&aov_trigger_kobj,
&aov_sysfs_attr_register);
if (ret) {
dev_err(&pdev->dev,
"%s: register node creation failed, ret=%d\n",
__func__, ret);
goto exit_remove_trigger;
}
sysfs_attr_init(&aov_sysfs_attr_event);
ret = sysfs_create_file(&aov_trigger_kobj,
&aov_sysfs_attr_event);
if (ret) {
dev_err(&pdev->dev,
"%s: event node creation failed, ret=%d\n",
__func__, ret);
goto exit_remove_register;
}
wakeup_source_init(&aov_wake_src, "aov_wakelock");
goto exit;
exit_remove_register:
sysfs_remove_file(&aov_trigger_kobj,
&aov_sysfs_attr_register);
exit_remove_trigger:
sysfs_remove_file(&aov_trigger_kobj,
&aov_sysfs_attr_trigger);
exit_remove_kobj:
kobject_put(&aov_trigger_kobj);
exit:
return ret;
}
static int aov_trigger_remove(struct platform_device *pdev)
{
sysfs_remove_file(&aov_trigger_kobj, &aov_sysfs_attr_event);
sysfs_remove_file(&aov_trigger_kobj, &aov_sysfs_attr_register);
sysfs_remove_file(&aov_trigger_kobj, &aov_sysfs_attr_trigger);
wakeup_source_trash(&aov_wake_src);
kobject_del(&aov_trigger_kobj);
return 0;
}
static struct of_device_id aov_trigger_match_table[] = {
{ .compatible = "mmi,aov-trigger",
},
{}
};
static struct platform_driver aov_trigger_driver = {
.probe = aov_trigger_probe,
.remove = aov_trigger_remove,
.driver = {
.name = "aov-trigger",
.of_match_table = of_match_ptr(aov_trigger_match_table),
.owner = THIS_MODULE,
},
};
static int __init aov_trigger_init(void)
{
return platform_driver_register(&aov_trigger_driver);
}
static void __exit aov_trigger_exit(void)
{
platform_driver_unregister(&aov_trigger_driver);
}
module_init(aov_trigger_init);
module_exit(aov_trigger_exit);
MODULE_DESCRIPTION("Motorola AOV trigger driver");
MODULE_LICENSE("GPL");

View file

@ -1,20 +0,0 @@
/*
* Copyright (c) 2014, Motorola Mobility, LLC.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only 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 __AOV_TRIGGER_H
#define __AOV_TRIGGER_H
struct snd_soc_codec;
void aov_trigger_register_notifier(struct snd_soc_codec *codec);
#endif /* __AOV_TRIGGER_H */

File diff suppressed because it is too large Load diff

View file

@ -1,291 +0,0 @@
/*
* cs35l35.h -- CS35L35 ALSA SoC audio driver
*
* Copyright 2016 Cirrus Logic, Inc.
*
* Author: Brian Austin <brian.austin@cirrus.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#ifndef __CS35L35_H__
#define __CS35L35_H__
#define CS35L35_FIRSTREG 0x01
#define CS35L35_LASTREG 0x7E
#define CS35L35_CHIP_ID 0x00035A35
#define CS35L35_DEVID_AB 0x01 /* Device ID A & B [RO] */
#define CS35L35_DEVID_CD 0x02 /* Device ID C & D [RO] */
#define CS35L35_DEVID_E 0x03 /* Device ID E [RO] */
#define CS35L35_FAB_ID 0x04 /* Fab ID [RO] */
#define CS35L35_REV_ID 0x05 /* Revision ID [RO] */
#define CS35L35_PWRCTL1 0x06 /* Power Ctl 1 */
#define CS35L35_PWRCTL2 0x07 /* Power Ctl 2 */
#define CS35L35_PWRCTL3 0x08 /* Power Ctl 3 */
#define CS35L35_CLK_CTL1 0x0A /* Clocking Ctl 1 */
#define CS35L35_CLK_CTL2 0x0B /* Clocking Ctl 2 */
#define CS35L35_CLK_CTL3 0x0C /* Clocking Ctl 3 */
#define CS35L35_SP_FMT_CTL1 0x0D /* Serial Port Format CTL1 */
#define CS35L35_SP_FMT_CTL2 0x0E /* Serial Port Format CTL2 */
#define CS35L35_SP_FMT_CTL3 0x0F /* Serial Port Format CTL3 */
#define CS35L35_MAG_COMP_CTL 0x13 /* Magnitude Comp CTL */
#define CS35L35_AMP_INP_DRV_CTL 0x14 /* Amp Input Drive Ctl */
#define CS35L35_AMP_DIG_VOL_CTL 0x15 /* Amplifier Dig Volume Ctl */
#define CS35L35_AMP_DIG_VOL 0x16 /* Amplifier Dig Volume */
#define CS35L35_ADV_DIG_VOL 0x17 /* Advisory Digital Volume */
#define CS35L35_PROTECT_CTL 0x18 /* Amp Gain - Prot Ctl Param */
#define CS35L35_AMP_GAIN_AUD_CTL 0x19 /* Amp Serial Port Gain Ctl */
#define CS35L35_AMP_GAIN_PDM_CTL 0x1A /* Amplifier Gain PDM Ctl */
#define CS35L35_AMP_GAIN_ADV_CTL 0x1B /* Amplifier Gain Ctl */
#define CS35L35_GPI_CTL 0x1C /* GPI Ctl */
#define CS35L35_BST_CVTR_V_CTL 0x1D /* Boost Conv Voltage Ctl */
#define CS35L35_BST_PEAK_I 0x1E /* Boost Conv Peak Current */
#define CS35L35_BST_RAMP_CTL 0x20 /* Boost Conv Soft Ramp Ctl */
#define CS35L35_BST_CONV_COEF_1 0x21 /* Boost Conv Coefficients 1 */
#define CS35L35_BST_CONV_COEF_2 0x22 /* Boost Conv Coefficients 2 */
#define CS35L35_BST_CONV_SLOPE_COMP 0x23 /* Boost Conv Slope Comp */
#define CS35L35_BST_CONV_SW_FREQ 0x24 /* Boost Conv L BST SW Freq */
#define CS35L35_CLASS_H_CTL 0x30 /* CLS H Control */
#define CS35L35_CLASS_H_HEADRM_CTL 0x31 /* CLS H Headroom Ctl */
#define CS35L35_CLASS_H_RELEASE_RATE 0x32 /* CLS H Release Rate */
#define CS35L35_CLASS_H_FET_DRIVE_CTL 0x33 /* CLS H Weak FET Drive Ctl */
#define CS35L35_CLASS_H_VP_CTL 0x34 /* CLS H VP Ctl */
#define CS35L35_CLASS_H_STATUS 0x38 /* CLS H Status */
#define CS35L35_VPBR_CTL 0x3A /* VPBR Ctl */
#define CS35L35_VPBR_VOL_CTL 0x3B /* VPBR Volume Ctl */
#define CS35L35_VPBR_TIMING_CTL 0x3C /* VPBR Timing Ctl */
#define CS35L35_VPBR_MODE_VOL_CTL 0x3D /* VPBR Mode/Attack Vol Ctl */
#define CS35L35_VPBR_ATTEN_STATUS 0x4B /* VPBR Attenuation Status */
#define CS35L35_SPKR_MON_CTL 0x4E /* Speaker Monitoring Ctl */
#define CS35L35_IMON_SCALE_CTL 0x51 /* IMON Scale Ctl */
#define CS35L35_AUDIN_RXLOC_CTL 0x52 /* Audio Input RX Loc Ctl */
#define CS35L35_ADVIN_RXLOC_CTL 0x53 /* Advisory Input RX Loc Ctl */
#define CS35L35_VMON_TXLOC_CTL 0x54 /* VMON TX Loc Ctl */
#define CS35L35_IMON_TXLOC_CTL 0x55 /* IMON TX Loc Ctl */
#define CS35L35_VPMON_TXLOC_CTL 0x56 /* VPMON TX Loc Ctl */
#define CS35L35_VBSTMON_TXLOC_CTL 0x57 /* VBSTMON TX Loc Ctl */
#define CS35L35_VPBR_STATUS_TXLOC_CTL 0x58 /* VPBR Status TX Loc Ctl */
#define CS35L35_ZERO_FILL_LOC_CTL 0x59 /* Zero Fill Loc Ctl */
#define CS35L35_AUDIN_DEPTH_CTL 0x5A /* Audio Input Depth Ctl */
#define CS35L35_SPKMON_DEPTH_CTL 0x5B /* SPK Mon Output Depth Ctl */
#define CS35L35_SUPMON_DEPTH_CTL 0x5C /* Supply Mon Out Depth Ctl */
#define CS35L35_ZEROFILL_DEPTH_CTL 0x5D /* Zero Fill Mon Output Ctl */
#define CS35L35_MULT_DEV_SYNCH1 0x62 /* Multidevice Synch */
#define CS35L35_MULT_DEV_SYNCH2 0x63 /* Multidevice Synch 2 */
#define CS35L35_PROT_RELEASE_CTL 0x64 /* Protection Release Ctl */
#define CS35L35_DIAG_MODE_REG_LOCK 0x68 /* Diagnostic Mode Reg Lock */
#define CS35L35_DIAG_MODE_CTL_1 0x69 /* Diagnostic Mode Ctl 1 */
#define CS35L35_DIAG_MODE_CTL_2 0x6A /* Diagnostic Mode Ctl 2 */
#define CS35L35_INT_MASK_1 0x70 /* Interrupt Mask 1 */
#define CS35L35_INT_MASK_2 0x71 /* Interrupt Mask 2 */
#define CS35L35_INT_MASK_3 0x72 /* Interrupt Mask 3 */
#define CS35L35_INT_MASK_4 0x73 /* Interrupt Mask 4 */
#define CS35L35_INT_STATUS_1 0x74 /* Interrupt Status 1 */
#define CS35L35_INT_STATUS_2 0x75 /* Interrupt Status 2 */
#define CS35L35_INT_STATUS_3 0x76 /* Interrupt Status 3 */
#define CS35L35_INT_STATUS_4 0x77 /* Interrupt Status 4 */
#define CS35L35_PLL_STATUS 0x78 /* PLL Status */
#define CS35L35_OTP_TRIM_STATUS 0x7E /* OTP Trim Status */
#define CS35L35_MAX_REGISTER 0x7F
/* CS35L35_PWRCTL1 */
#define CS35L35_SFT_RST 0x80
#define CS35L35_DISCHG_FLT 0x02
#define CS35L35_PDN_ALL 0x01
/* CS35L35_PWRCTL2 */
#define CS35L35_PDN_VMON 0x80
#define CS35L35_PDN_IMON 0x40
#define CS35L35_PDN_CLASSH 0x20
#define CS35L35_PDN_VPBR 0x10
#define CS35L35_PDN_BST 0x04
#define CS35L35_PDN_AMP 0x01
/* CS35L35_PWRCTL3 */
#define CS35L35_PDN_VBSTMON_OUT 0x10
#define CS35L35_PDN_VMON_OUT 0x08
#define CS35L35_AUDIN_DEPTH_MASK 0x03
#define CS35L35_AUDIN_DEPTH_SHIFT 0
#define CS35L35_ADVIN_DEPTH_MASK 0x12
#define CS35L35_ADVIN_DEPTH_SHIFT 2
#define CS35L35_SDIN_DEPTH_8 0x01
#define CS35L35_SDIN_DEPTH_16 0x02
#define CS35L35_SDIN_DEPTH_24 0x03
#define CS35L35_SDOUT_DEPTH_8 0x01
#define CS35L35_SDOUT_DEPTH_12 0x02
#define CS35L35_SDOUT_DEPTH_16 0x03
#define CS35L35_AUD_IN_LR_MASK 0x80
#define CS35L35_AUD_IN_LR_SHIFT 7
#define CS35L35_ADV_IN_LR_MASK 0x80
#define CS35L35_ADV_IN_LR_SHIFT 7
#define CS35L35_AUD_IN_LOC_MASK 0x0F
#define CS35L35_AUD_IN_LOC_SHIFT 0
#define CS35L35_ADV_IN_LOC_MASK 0x0F
#define CS35L35_ADV_IN_LOC_SHIFT 0
#define CS35L35_IMON_DEPTH_MASK 0x03
#define CS35L35_IMON_DEPTH_SHIFT 0
#define CS35L35_VMON_DEPTH_MASK 0x0C
#define CS35L35_VMON_DEPTH_SHIFT 2
#define CS35L35_VBSTMON_DEPTH_MASK 0x03
#define CS35L35_VBSTMON_DEPTH_SHIFT 0
#define CS35L35_VPMON_DEPTH_MASK 0x0C
#define CS35L35_VPMON_DEPTH_SHIFT 2
#define CS35L35_VPBRSTAT_DEPTH_MASK 0x18
#define CS35L35_VPBRSTAT_DEPTH_SHIFT 4
#define CS35L35_ZEROFILL_DEPTH_MASK 0x03
#define CS35L35_ZEROFILL_DEPTH_SHIFT 0x00
#define CS35L35_MON_TXLOC_MASK 0x3F
#define CS35L35_MON_TXLOC_SHIFT 0
#define CS35L35_MON_FRM_MASK 0x80
#define CS35L35_MON_FRM_SHIFT 7
#define CS35L35_MS_MASK 0x80
#define CS35L35_MS_SHIFT 7
#define CS35L35_SPMODE_MASK 0x40
#define CS35L35_SP_DRV_MASK 0x10
#define CS35L35_SP_DRV_SHIFT 4
#define CS35L35_CLK_CTL2_MASK 0xFF
#define CS35L35_CLK_DIV_MASK 0x3
#define CS35L35_PDM_MODE_MASK 0x40
#define CS35L35_PDM_MODE_SHIFT 6
#define CS35L35_CLK_SOURCE_MASK 0x03
#define CS35L35_CLK_SOURCE_SHIFT 0
#define CS35L35_CLK_SOURCE_MCLK 0
#define CS35L35_CLK_SOURCE_SCLK 1
#define CS35L35_CLK_SOURCE_PDM 2
#define CS35L35_SP_SCLKS_MASK 0x0F
#define CS35L35_SP_SCLKS_SHIFT 0x00
#define CS35L35_SP_SCLKS_16FS 0x03
#define CS35L35_SP_SCLKS_32FS 0x07
#define CS35L35_SP_SCLKS_48FS 0x0B
#define CS35L35_SP_SCLKS_64FS 0x0F
#define CS35L35_SP_RATE_MASK 0xC0
#define CS35L35_PDN_BST_MASK 0x06
#define CS35L35_PDN_BST_FETON_SHIFT 1
#define CS35L35_PDN_BST_FETOFF_SHIFT 2
#define CS35L35_PWR2_PDN_MASK 0xE0
#define CS35L35_PWR3_PDN_MASK 0x1E
#define CS35L35_PDN_ALL_MASK 0x01
#define CS35L35_DISCHG_FILT_MASK 0x02
#define CS35L35_DISCHG_FILT_SHIFT 1
#define CS35L35_MCLK_DIS_MASK 0x04
#define CS35L35_MCLK_DIS_SHIFT 2
#define CS35L35_BST_CTL_MASK 0x7F
#define CS35L35_BST_CTL_SHIFT 0
#define CS35L35_AMP_MUTE_MASK 0x20
#define CS35L35_AMP_MUTE_SHIFT 5
#define CS35L35_AMP_GAIN_ZC_MASK 0x10
#define CS35L35_AMP_GAIN_ZC_SHIFT 4
/* Class H Algorithm Control */
#define CS35L35_CH_STEREO_MASK 0x40
#define CS35L35_CH_STEREO_SHIFT 6
#define CS35L35_CH_BST_OVR_MASK 0x04
#define CS35L35_CH_BST_OVR_SHIFT 2
#define CS35L35_CH_BST_LIM_MASK 0x08
#define CS35L35_CH_BST_LIM_SHIFT 3
#define CS35L35_CH_MEM_DEPTH_MASK 0x01
#define CS35L35_CH_MEM_DEPTH_SHIFT 0
#define CS35L35_CH_HDRM_CTL_MASK 0x3F
#define CS35L35_CH_HDRM_CTL_SHIFT 0
#define CS35L35_CH_REL_RATE_MASK 0xFF
#define CS35L35_CH_REL_RATE_SHIFT 0
#define CS35L35_CH_WKFET_DIS_MASK 0x80
#define CS35L35_CH_WKFET_DIS_SHIFT 7
#define CS35L35_CH_WKFET_DEL_MASK 0x70
#define CS35L35_CH_WKFET_DEL_SHIFT 4
#define CS35L35_CH_WKFET_THLD_MASK 0x0F
#define CS35L35_CH_WKFET_THLD_SHIFT 0
#define CS35L35_CH_VP_AUTO_MASK 0x80
#define CS35L35_CH_VP_AUTO_SHIFT 7
#define CS35L35_CH_VP_RATE_MASK 0x60
#define CS35L35_CH_VP_RATE_SHIFT 5
#define CS35L35_CH_VP_MAN_MASK 0x1F
#define CS35L35_CH_VP_MAN_SHIFT 0
/* CS35L35_PROT_RELEASE_CTL */
#define CS35L35_CAL_ERR_RLS 0x80
#define CS35L35_SHORT_RLS 0x04
#define CS35L35_OTW_RLS 0x02
#define CS35L35_OTE_RLS 0x01
/* INT Mask Registers */
#define CS35L35_INT1_CRIT_MASK 0x38
#define CS35L35_INT2_CRIT_MASK 0xEF
#define CS35L35_INT3_CRIT_MASK 0xEE
#define CS35L35_INT4_CRIT_MASK 0xFF
/* PDN DONE Masks */
#define CS35L35_M_PDN_DONE_SHIFT 4
#define CS35L35_M_PDN_DONE_MASK 0x10
/* CS35L35_INT_1 */
#define CS35L35_CAL_ERR 0x80
#define CS35L35_OTP_ERR 0x40
#define CS35L35_LRCLK_ERR 0x20
#define CS35L35_SPCLK_ERR 0x10
#define CS35L35_MCLK_ERR 0x08
#define CS35L35_AMP_SHORT 0x04
#define CS35L35_OTW 0x02
#define CS35L35_OTE 0x01
/* CS35L35_INT_2 */
#define CS35L35_PDN_DONE 0x10
#define CS35L35_VPBR_ERR 0x02
#define CS35L35_VPBR_CLR 0x01
/* CS35L35_INT_3 */
#define CS35L35_BST_HIGH 0x10
#define CS35L35_BST_HIGH_FLAG 0x08
#define CS35L35_BST_IPK_FLAG 0x04
#define CS35L35_LBST_SHORT 0x01
/* CS35L35_INT_4 */
#define CS35L35_VMON_OVFL 0x08
#define CS35L35_IMON_OVFL 0x04
#define CS35L35_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE)
struct cs35l35_private {
struct i2c_client *i2c_client;
struct snd_soc_codec *codec;
struct cs35l35_platform_data pdata;
struct regmap *regmap;
struct regulator_bulk_data supplies[2];
int num_supplies;
int sysclk;
int sclk;
int mclk_pll;
int mclk_div;
int mclk_sp_base;
bool tdm_mode;
bool pdm_mode;
bool i2s_enabled;
bool slave_mode;
bool pdm_mclk_switch;
/* GPIO for /RST */
struct gpio_desc *reset_gpio;
/* GPIO for INT */
struct gpio_desc *irq_gpio;
struct completion pdn_done;
};
static const char * const cs35l35_supplies[] = {
"VA",
"VP",
};
#endif

View file

@ -1,367 +0,0 @@
/*
* cs35l36-tables.c -- CS35L36 ALSA SoC audio driver
*
* Copyright 2016 Cirrus Logic, Inc.
*
* Author: Brian Austin <brian.austin@cirrus.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include "cs35l36.h"
struct reg_default cs35l36_reg[CS35L36_MAX_CACHE_REG] = {
{CS35L36_TESTKEY_CTRL, 0x00000000},
{CS35L36_USERKEY_CTL, 0x00000000},
{CS35L36_OTP_CTRL1, 0x00002460},
{CS35L36_OTP_CTRL2, 0x00000000},
{CS35L36_OTP_CTRL3, 0x00000000},
{CS35L36_OTP_CTRL4, 0x00000000},
{CS35L36_OTP_CTRL5, 0x00000000},
{CS35L36_PAC_CTL1, 0x00000004},
{CS35L36_PAC_CTL2, 0x00000000},
{CS35L36_PAC_CTL3, 0x00000000},
{CS35L36_PWR_CTRL1, 0x00000000},
{CS35L36_PWR_CTRL2, 0x00003321},
{CS35L36_PWR_CTRL3, 0x01000010},
{CS35L36_CTRL_OVRRIDE, 0x00000002},
{CS35L36_AMP_OUT_MUTE, 0x00000000},
{CS35L36_OTP_TRIM_STATUS, 0x00000000},
{CS35L36_DISCH_FILT, 0x00000000},
{CS35L36_PROTECT_REL_ERR, 0x00000000},
{CS35L36_PAD_INTERFACE, 0x00000038},
{CS35L36_PLL_CLK_CTRL, 0x00000010},
{CS35L36_GLOBAL_CLK_CTRL, 0x00000003},
{CS35L36_ADC_CLK_CTRL, 0x00000000},
{CS35L36_SWIRE_CLK_CTRL, 0x00000000},
{CS35L36_SP_SCLK_CLK_CTRL, 0x00000000},
{CS35L36_MDSYNC_EN, 0x00000000},
{CS35L36_MDSYNC_TX_ID, 0x00000000},
{CS35L36_MDSYNC_PWR_CTRL, 0x00000000},
{CS35L36_MDSYNC_DATA_TX, 0x00000000},
{CS35L36_MDSYNC_TX_STATUS, 0x00000002},
{CS35L36_MDSYNC_RX_STATUS, 0x00000000},
{CS35L36_MDSYNC_ERR_STATUS, 0x00000000},
{CS35L36_BSTCVRT_VCTRL1, 0x00000000},
{CS35L36_BSTCVRT_VCTRL2, 0x00000001},
{CS35L36_BSTCVRT_PEAK_CUR, 0x0000004A},
{CS35L36_BSTCVRT_SFT_RAMP, 0x00000003},
{CS35L36_BSTCVRT_COEFF, 0x00002424},
{CS35L36_BSTCVRT_SLOPE_LBST, 0x00005800},
{CS35L36_BSTCVRT_SW_FREQ, 0x00010000},
{CS35L36_BSTCVRT_DCM_CTRL, 0x00002001},
{CS35L36_BSTCVRT_DCM_MODE_FORCE, 0x00000000},
{CS35L36_BSTCVRT_OVERVOLT_CTRL, 0x00000130},
{CS35L36_VPI_LIMIT_MODE, 0x00000000},
{CS35L36_VPI_LIMIT_MINMAX, 0x00003000},
{CS35L36_VPI_VP_THLD, 0x00101010},
{CS35L36_VPI_TRACK_CTRL, 0x00000000},
{CS35L36_VPI_TRIG_MODE_CTRL, 0x00000000},
{CS35L36_VPI_TRIG_STEPS, 0x00000000},
{CS35L36_VI_SPKMON_FILT, 0x00000003},
{CS35L36_VI_SPKMON_GAIN, 0x00000909},
{CS35L36_VI_SPKMON_IP_SEL, 0x00000000},
{CS35L36_DTEMP_WARN_THLD, 0x00000002},
{CS35L36_DTEMP_STATUS, 0x00000000},
{CS35L36_VPVBST_FS_SEL, 0x00000001},
{CS35L36_VPVBST_VP_CTRL, 0x000001C0},
{CS35L36_VPVBST_VBST_CTRL, 0x000001C0},
{CS35L36_ASP_TX_PIN_CTRL, 0x00000028},
{CS35L36_ASP_RATE_CTRL, 0x00090000},
{CS35L36_ASP_FORMAT, 0x00000002},
{CS35L36_ASP_FRAME_CTRL, 0x00180018},
{CS35L36_ASP_TX1_TX2_SLOT, 0x00010000},
{CS35L36_ASP_TX3_TX4_SLOT, 0x00030002},
{CS35L36_ASP_TX5_TX6_SLOT, 0x00050004},
{CS35L36_ASP_TX7_TX8_SLOT, 0x00070006},
{CS35L36_ASP_RX1_SLOT, 0x00000000},
{CS35L36_ASP_RX_TX_EN, 0x00000000},
{CS35L36_ASP_RX1_SEL, 0x00000008},
{CS35L36_ASP_TX1_SEL, 0x00000018},
{CS35L36_ASP_TX2_SEL, 0x00000019},
{CS35L36_ASP_TX3_SEL, 0x00000028},
{CS35L36_ASP_TX4_SEL, 0x00000029},
{CS35L36_ASP_TX5_SEL, 0x00000020},
{CS35L36_ASP_TX6_SEL, 0x00000000},
{CS35L36_SWIRE_P1_TX1_SEL, 0x00000018},
{CS35L36_SWIRE_P1_TX2_SEL, 0x00000019},
{CS35L36_SWIRE_P2_TX1_SEL, 0x00000028},
{CS35L36_SWIRE_P2_TX2_SEL, 0x00000029},
{CS35L36_SWIRE_P2_TX3_SEL, 0x00000020},
{CS35L36_SWIRE_DP1_FIFO_CFG, 0x0000001B},
{CS35L36_SWIRE_DP2_FIFO_CFG, 0x0000001B},
{CS35L36_SWIRE_DP3_FIFO_CFG, 0x0000001B},
{CS35L36_SWIRE_PCM_RX_DATA, 0x00000000},
{CS35L36_SWIRE_FS_SEL, 0x00000001},
{CS35L36_AMP_DIG_VOL_CTRL, 0x00008000},
{CS35L36_VPBR_CFG, 0x02AA1905},
{CS35L36_VBBR_CFG, 0x02AA1905},
{CS35L36_VPBR_STATUS, 0x00000000},
{CS35L36_VBBR_STATUS, 0x00000000},
{CS35L36_OVERTEMP_CFG, 0x00000001},
{CS35L36_AMP_ERR_VOL, 0x00000000},
{CS35L36_CLASSH_CFG, 0x000B0405},
{CS35L36_CLASSH_FET_DRV_CFG, 0x00000111},
{CS35L36_NG_CFG, 0x00000033},
{CS35L36_AMP_GAIN_CTRL, 0x00000273},
{CS35L36_PWM_MOD_IO_CTRL, 0x00000000},
{CS35L36_PWM_MOD_STATUS, 0x00000000},
{CS35L36_DAC_MSM_CFG, 0x00000000},
{CS35L36_AMP_SLOPE_CTRL, 0x00000B00},
{CS35L36_AMP_PDM_VOLUME, 0x00000000},
{CS35L36_AMP_PDM_RATE_CTRL, 0x00000000},
{CS35L36_PDM_CH_SEL, 0x00000000},
{CS35L36_AMP_NG_CTRL, 0x0000212F},
{CS35L36_PDM_HIGHFILT_CTRL, 0x00000000},
{CS35L36_PAC_INT0_CTRL, 0x00000001},
{CS35L36_PAC_INT1_CTRL, 0x00000001},
{CS35L36_PAC_INT2_CTRL, 0x00000001},
{CS35L36_PAC_INT3_CTRL, 0x00000001},
{CS35L36_PAC_INT4_CTRL, 0x00000001},
{CS35L36_PAC_INT5_CTRL, 0x00000001},
{CS35L36_PAC_INT6_CTRL, 0x00000001},
{CS35L36_PAC_INT7_CTRL, 0x00000001},
};
bool cs35l36_readable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case CS35L36_SW_RESET:
case CS35L36_SW_REV:
case CS35L36_HW_REV:
case CS35L36_TESTKEY_CTRL:
case CS35L36_USERKEY_CTL:
case CS35L36_OTP_MEM30:
case CS35L36_OTP_CTRL1:
case CS35L36_OTP_CTRL2:
case CS35L36_OTP_CTRL3:
case CS35L36_OTP_CTRL4:
case CS35L36_OTP_CTRL5:
case CS35L36_PAC_CTL1:
case CS35L36_PAC_CTL2:
case CS35L36_PAC_CTL3:
case CS35L36_DEVICE_ID:
case CS35L36_FAB_ID:
case CS35L36_REV_ID:
case CS35L36_PWR_CTRL1:
case CS35L36_PWR_CTRL2:
case CS35L36_PWR_CTRL3:
case CS35L36_CTRL_OVRRIDE:
case CS35L36_AMP_OUT_MUTE:
case CS35L36_OTP_TRIM_STATUS:
case CS35L36_DISCH_FILT:
case CS35L36_PROTECT_REL_ERR:
case CS35L36_PAD_INTERFACE:
case CS35L36_PLL_CLK_CTRL:
case CS35L36_GLOBAL_CLK_CTRL:
case CS35L36_ADC_CLK_CTRL:
case CS35L36_SWIRE_CLK_CTRL:
case CS35L36_SP_SCLK_CLK_CTRL:
case CS35L36_MDSYNC_EN:
case CS35L36_MDSYNC_TX_ID:
case CS35L36_MDSYNC_PWR_CTRL:
case CS35L36_MDSYNC_DATA_TX:
case CS35L36_MDSYNC_TX_STATUS:
case CS35L36_MDSYNC_RX_STATUS:
case CS35L36_MDSYNC_ERR_STATUS:
case CS35L36_BSTCVRT_VCTRL1:
case CS35L36_BSTCVRT_VCTRL2:
case CS35L36_BSTCVRT_PEAK_CUR:
case CS35L36_BSTCVRT_SFT_RAMP:
case CS35L36_BSTCVRT_COEFF:
case CS35L36_BSTCVRT_SLOPE_LBST:
case CS35L36_BSTCVRT_SW_FREQ:
case CS35L36_BSTCVRT_DCM_CTRL:
case CS35L36_BSTCVRT_DCM_MODE_FORCE:
case CS35L36_BSTCVRT_OVERVOLT_CTRL:
case CS35L36_BST_TST_MANUAL:
case CS35L36_BST_ANA2_TEST:
case CS35L36_VPI_LIMIT_MODE:
case CS35L36_VPI_LIMIT_MINMAX:
case CS35L36_VPI_VP_THLD:
case CS35L36_VPI_TRACK_CTRL:
case CS35L36_VPI_TRIG_MODE_CTRL:
case CS35L36_VPI_TRIG_STEPS:
case CS35L36_VI_SPKMON_FILT:
case CS35L36_VI_SPKMON_GAIN:
case CS35L36_VI_SPKMON_IP_SEL:
case CS35L36_DTEMP_WARN_THLD:
case CS35L36_DTEMP_STATUS:
case CS35L36_VPVBST_FS_SEL:
case CS35L36_VPVBST_VP_CTRL:
case CS35L36_VPVBST_VBST_CTRL:
case CS35L36_ASP_TX_PIN_CTRL:
case CS35L36_ASP_RATE_CTRL:
case CS35L36_ASP_FORMAT:
case CS35L36_ASP_FRAME_CTRL:
case CS35L36_ASP_TX1_TX2_SLOT:
case CS35L36_ASP_TX3_TX4_SLOT:
case CS35L36_ASP_TX5_TX6_SLOT:
case CS35L36_ASP_TX7_TX8_SLOT:
case CS35L36_ASP_RX1_SLOT:
case CS35L36_ASP_RX_TX_EN:
case CS35L36_ASP_RX1_SEL:
case CS35L36_ASP_TX1_SEL:
case CS35L36_ASP_TX2_SEL:
case CS35L36_ASP_TX3_SEL:
case CS35L36_ASP_TX4_SEL:
case CS35L36_ASP_TX5_SEL:
case CS35L36_ASP_TX6_SEL:
case CS35L36_SWIRE_P1_TX1_SEL:
case CS35L36_SWIRE_P1_TX2_SEL:
case CS35L36_SWIRE_P2_TX1_SEL:
case CS35L36_SWIRE_P2_TX2_SEL:
case CS35L36_SWIRE_P2_TX3_SEL:
case CS35L36_SWIRE_DP1_FIFO_CFG:
case CS35L36_SWIRE_DP2_FIFO_CFG:
case CS35L36_SWIRE_DP3_FIFO_CFG:
case CS35L36_SWIRE_PCM_RX_DATA:
case CS35L36_SWIRE_FS_SEL:
case CS35L36_AMP_DIG_VOL_CTRL:
case CS35L36_VPBR_CFG:
case CS35L36_VBBR_CFG:
case CS35L36_VPBR_STATUS:
case CS35L36_VBBR_STATUS:
case CS35L36_OVERTEMP_CFG:
case CS35L36_AMP_ERR_VOL:
case CS35L36_CLASSH_CFG:
case CS35L36_CLASSH_FET_DRV_CFG:
case CS35L36_NG_CFG:
case CS35L36_AMP_GAIN_CTRL:
case CS35L36_PWM_MOD_IO_CTRL:
case CS35L36_PWM_MOD_STATUS:
case CS35L36_DAC_MSM_CFG:
case CS35L36_AMP_SLOPE_CTRL:
case CS35L36_AMP_PDM_VOLUME:
case CS35L36_AMP_PDM_RATE_CTRL:
case CS35L36_PDM_CH_SEL:
case CS35L36_AMP_NG_CTRL:
case CS35L36_PDM_HIGHFILT_CTRL:
case CS35L36_INT1_STATUS:
case CS35L36_INT2_STATUS:
case CS35L36_INT3_STATUS:
case CS35L36_INT4_STATUS:
case CS35L36_INT1_RAW_STATUS:
case CS35L36_INT2_RAW_STATUS:
case CS35L36_INT3_RAW_STATUS:
case CS35L36_INT4_RAW_STATUS:
case CS35L36_INT1_MASK:
case CS35L36_INT2_MASK:
case CS35L36_INT3_MASK:
case CS35L36_INT4_MASK:
case CS35L36_INT1_EDGE_LVL_CTRL:
case CS35L36_INT3_EDGE_LVL_CTRL:
case CS35L36_PAC_INT_STATUS:
case CS35L36_PAC_INT_RAW_STATUS:
case CS35L36_PAC_INT_FLUSH_CTRL:
case CS35L36_PAC_INT0_CTRL:
case CS35L36_PAC_INT1_CTRL:
case CS35L36_PAC_INT2_CTRL:
case CS35L36_PAC_INT3_CTRL:
case CS35L36_PAC_INT4_CTRL:
case CS35L36_PAC_INT5_CTRL:
case CS35L36_PAC_INT6_CTRL:
case CS35L36_PAC_INT7_CTRL:
return true;
default:
if (reg >= CS35L36_PAC_PMEM_WORD0 &&
reg <= CS35L36_PAC_PMEM_WORD1023)
return true;
else
return false;
}
}
bool cs35l36_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case CS35L36_SW_RESET:
case CS35L36_SW_REV:
case CS35L36_HW_REV:
case CS35L36_DEVICE_ID:
case CS35L36_FAB_ID:
case CS35L36_REV_ID:
case CS35L36_PWR_CTRL1:
case CS35L36_INT1_STATUS:
case CS35L36_INT2_STATUS:
case CS35L36_INT3_STATUS:
case CS35L36_INT4_STATUS:
case CS35L36_INT1_RAW_STATUS:
case CS35L36_INT2_RAW_STATUS:
case CS35L36_INT3_RAW_STATUS:
case CS35L36_INT4_RAW_STATUS:
case CS35L36_INT1_MASK:
case CS35L36_INT2_MASK:
case CS35L36_INT3_MASK:
case CS35L36_INT4_MASK:
case CS35L36_INT1_EDGE_LVL_CTRL:
case CS35L36_INT3_EDGE_LVL_CTRL:
case CS35L36_PAC_INT_STATUS:
case CS35L36_PAC_INT_RAW_STATUS:
case CS35L36_PAC_INT_FLUSH_CTRL:
return true;
default:
if (reg >= CS35L36_PAC_PMEM_WORD0 &&
reg <= CS35L36_PAC_PMEM_WORD1023)
return true;
else
return false;
}
}
const unsigned int cs35l36_aou_low_power_patch[] = {
0x022f0902, 0x01080a08, 0xe0c00000, 0x80028775,
0x020000fb, 0xe0c02c08, 0xd2200a12, 0x0c878501,
0x53fdf453, 0xf875fbf4, 0x32e0d002, 0x0a12e0c0,
0x8501d220, 0xf4530c87, 0xfbf453fd, 0xd004f875,
0x81c132e0, 0x00000d01, 0x02000000, 0xf9751608,
0xfaf5e482, 0xfcf5fbf5, 0x7520fd75, 0xff7555e8,
0xf5d6f555, 0xaae875d7, 0xf5aaff75, 0x75d7f5d6,
0xfaf580f9, 0xfc75fbf5, 0x4efd755c, 0x7501e875,
0xfaf580f9, 0xfc75fbf5, 0x54fd755c, 0x750fe875,
0xfaf580f9, 0xfc75fbf5, 0x5cfd755c, 0x530ee885,
0x0e43700e, 0xe80e8504, 0xf580f975, 0x75fbf5fa,
0xfd7520fc, 0x0de88530, 0x758f0d53, 0xfaf582f9,
0xfcf5fbf5, 0x7520fd75, 0xff75cce8, 0xf5d6f5cc,
0x33e875d7, 0xf533ff75, 0x7dd7f5d6, 0x12027f01,
0xf975170b, 0xfaf5e480, 0x75d0fb75, 0xfd7502fc,
0x01e87524, 0xf580f975, 0xd0fb75fa, 0x7502fc75,
0xe87526fd, 0x047ffd4e, 0x75170b12, 0xf5e480f9,
0xd0fb75fa, 0x7502fc75, 0xe87528fd, 0x80f97501,
0xfb75faf5, 0x02fc75d0, 0x752afd75, 0x78224ee8,
0xd8f6e47f, 0x208175fd, 0x02760902, 0x93e4db0a,
0x93e4f8a3, 0xf60340a3, 0x08f20180, 0x2980f4df,
0xf8a393e4, 0x0c240754, 0xc433c3c8, 0x20440f54,
0x044083c8, 0x018056f4, 0xe4dff646, 0x02010b80,
0x20100804, 0x08908040, 0x017ee442, 0xa3bc6093,
0x303f54ff, 0x1f5409e5, 0xa393e4fe, 0xcf0e0160,
0xe025c054, 0xb840a860, 0xfaa393e4, 0xf8a393e4,
0xc8a393e4, 0xcac882c5, 0xf0ca83c5, 0x82c5c8a3,
0x83c5cac8, 0xdee9dfca, 0x75be80e7, 0xf5e482f9,
0xf5fbf5fa, 0x20fd75fc, 0x7555e875, 0xd6f555ff,
0xe875d7f5, 0xaaff75aa, 0xd7f5d6f5, 0xf580f975,
0x75fbf5fa, 0xfd7520fc, 0x0de88530, 0x7580e875,
0xfaf580f9, 0xfc75fbf5, 0x30fd752d, 0x7504e843,
0xfaf582f9, 0xfcf5fbf5, 0x7520fd75, 0xff75cce8,
0xf5d6f5cc, 0x33e875d7, 0xf533ff75, 0x22d7f5d6,
0xe482f975, 0xfbf5faf5, 0xfd75fcf5, 0x55e87520,
0xf555ff75, 0x75d7f5d6, 0xff75aae8, 0xf5d6f5aa,
0x80f975d7, 0xfbf5faf5, 0x7520fc75, 0x0d8530fd,
0x80f975e8, 0xfbf5faf5, 0x752dfc75, 0xe85330fd,
0x82f975fb, 0xfbf5faf5, 0xfd75fcf5, 0xcce87520,
0xf5ccff75, 0x75d7f5d6, 0xff7533e8, 0xf5d6f533,
0xf5e422d7, 0x750bf50a, 0xfaf580f9, 0xf5d0fb75,
0x29fd75fc, 0x4054e8e5, 0x088508f5, 0x54e8e509,
0x6508f540, 0x05047009, 0xe403800a, 0x0b050af5,
0x94c30ae5, 0xe5075003, 0x1094c30b, 0xf975dc40,
0xfaf5e480, 0xfc75fbf5, 0x14fd7520, 0x046008e5,
0x2201e875, 0x12e8f5e4, 0xc222bb09, 0x8ef5e400,
0x53fdf453, 0x0812fbf4, 0x02f8754e, 0x7502f443,
0xf44304f8, 0x85a87504, 0x3002b875, 0x01c20b01,
0x43820a12, 0xf44302f4, 0x4487e504, 0x200cf501,
0x0c85e901, 0xefe48087, 0x60edf542, 0xf642ef05,
0xf4ef0480, 0xf88ff652, 0x22f442ef, 0x0000521c
};

File diff suppressed because it is too large Load diff

View file

@ -1,448 +0,0 @@
/*
* cs35l36.h -- CS35L36 ALSA SoC audio driver
*
* Copyright 2016 Cirrus Logic, Inc.
*
* Author: Brian Austin <brian.austin@cirrus.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#ifndef __CS35L36_H__
#define __CS35L36_H__
#include <linux/regmap.h>
#define CS35L36_FIRSTREG 0x00000000
#define CS35L36_LASTREG 0x00E037FC
#define CS35L36_SW_RESET 0x00000000
#define CS35L36_SW_REV 0x00000004
#define CS35L36_HW_REV 0x00000008
#define CS35L36_TESTKEY_CTRL 0x00000020
#define CS35L36_USERKEY_CTL 0x00000024
#define CS35L36_OTP_MEM30 0x00000478
#define CS35L36_OTP_CTRL1 0x00000500
#define CS35L36_OTP_CTRL2 0x00000504
#define CS35L36_OTP_CTRL3 0x00000508
#define CS35L36_OTP_CTRL4 0x0000050C
#define CS35L36_OTP_CTRL5 0x00000510
#define CS35L36_PAC_CTL1 0x00000C00
#define CS35L36_PAC_CTL2 0x00000C04
#define CS35L36_PAC_CTL3 0x00000C08
#define CS35L36_DEVICE_ID 0x00002004
#define CS35L36_FAB_ID 0x00002008
#define CS35L36_REV_ID 0x0000200C
#define CS35L36_PWR_CTRL1 0x00002014
#define CS35L36_PWR_CTRL2 0x00002018
#define CS35L36_PWR_CTRL3 0x0000201C
#define CS35L36_CTRL_OVRRIDE 0x00002020
#define CS35L36_AMP_OUT_MUTE 0x00002024
#define CS35L36_OTP_TRIM_STATUS 0x00002028
#define CS35L36_DISCH_FILT 0x0000202C
#define CS35L36_OSC_TRIM 0x00002030
#define CS35L36_PROTECT_REL_ERR 0x00002034
#define CS35L36_PAD_INTERFACE 0x00002400
#define CS35L36_PLL_CLK_CTRL 0x00002C04
#define CS35L36_GLOBAL_CLK_CTRL 0x00002C0C
#define CS35L36_ADC_CLK_CTRL 0x00002C10
#define CS35L36_SWIRE_CLK_CTRL 0x00002C14
#define CS35L36_SP_SCLK_CLK_CTRL 0x00002D00
#define CS35L36_TST_FS_MON0 0x00002D10
#define CS35L36_PLL_LOOP_PARAMS 0x00003008
#define CS35L36_DCO_CTRL 0x00003010
#define CS35L36_MISC_CTRL 0x00003014
#define CS35L36_MDSYNC_EN 0x00003404
#define CS35L36_MDSYNC_TX_ID 0x00003408
#define CS35L36_MDSYNC_PWR_CTRL 0x0000340C
#define CS35L36_MDSYNC_DATA_TX 0x00003410
#define CS35L36_MDSYNC_TX_STATUS 0x0000341C
#define CS35L36_MDSYNC_RX_STATUS 0x00003420
#define CS35L36_MDSYNC_ERR_STATUS 0x00003424
#define CS35L36_BSTCVRT_VCTRL1 0x00003800
#define CS35L36_BSTCVRT_VCTRL2 0x00003804
#define CS35L36_BSTCVRT_PEAK_CUR 0x00003808
#define CS35L36_BSTCVRT_SFT_RAMP 0x0000380C
#define CS35L36_BSTCVRT_COEFF 0x00003810
#define CS35L36_BSTCVRT_SLOPE_LBST 0x00003814
#define CS35L36_BSTCVRT_SW_FREQ 0x00003818
#define CS35L36_BSTCVRT_DCM_CTRL 0x0000381C
#define CS35L36_BSTCVRT_DCM_MODE_FORCE 0x00003820
#define CS35L36_BSTCVRT_OVERVOLT_CTRL 0x00003830
#define CS35L36_BST_TST_MANUAL 0x0000393C
#define CS35L36_BST_ANA2_TEST 0x0000394C
#define CS35L36_VPI_LIMIT_MODE 0x00003C04
#define CS35L36_VPI_LIMIT_MINMAX 0x00003C08
#define CS35L36_VPI_VP_THLD 0x00003C0C
#define CS35L36_VPI_TRACK_CTRL 0x00003C10
#define CS35L36_VPI_TRIG_MODE_CTRL 0x00003C14
#define CS35L36_VPI_TRIG_STEPS 0x00003C18
#define CS35L36_VI_SPKMON_FILT 0x00004004
#define CS35L36_VI_SPKMON_GAIN 0x00004008
#define CS35L36_VI_SPKMON_IP_SEL 0x00004100
#define CS35L36_DTEMP_WARN_THLD 0x00004220
#define CS35L36_DTEMP_STATUS 0x00004300
#define CS35L36_VPVBST_FS_SEL 0x00004400
#define CS35L36_VPVBST_VP_CTRL 0x00004440
#define CS35L36_VPVBST_VBST_CTRL 0x00004444
#define CS35L36_ASP_TX_PIN_CTRL 0x00004800
#define CS35L36_ASP_RATE_CTRL 0x00004804
#define CS35L36_ASP_FORMAT 0x00004808
#define CS35L36_ASP_FRAME_CTRL 0x00004818
#define CS35L36_ASP_TX1_TX2_SLOT 0x0000481C
#define CS35L36_ASP_TX3_TX4_SLOT 0x00004820
#define CS35L36_ASP_TX5_TX6_SLOT 0x00004824
#define CS35L36_ASP_TX7_TX8_SLOT 0x00004828
#define CS35L36_ASP_RX1_SLOT 0x0000482C
#define CS35L36_ASP_RX_TX_EN 0x0000483C
#define CS35L36_ASP_RX1_SEL 0x00004C00
#define CS35L36_ASP_TX1_SEL 0x00004C20
#define CS35L36_ASP_TX2_SEL 0x00004C24
#define CS35L36_ASP_TX3_SEL 0x00004C28
#define CS35L36_ASP_TX4_SEL 0x00004C2C
#define CS35L36_ASP_TX5_SEL 0x00004C30
#define CS35L36_ASP_TX6_SEL 0x00004C34
#define CS35L36_SWIRE_P1_TX1_SEL 0x00004C40
#define CS35L36_SWIRE_P1_TX2_SEL 0x00004C44
#define CS35L36_SWIRE_P2_TX1_SEL 0x00004C60
#define CS35L36_SWIRE_P2_TX2_SEL 0x00004C64
#define CS35L36_SWIRE_P2_TX3_SEL 0x00004C68
#define CS35L36_SWIRE_DP1_FIFO_CFG 0x00005000
#define CS35L36_SWIRE_DP2_FIFO_CFG 0x00005004
#define CS35L36_SWIRE_DP3_FIFO_CFG 0x00005008
#define CS35L36_SWIRE_PCM_RX_DATA 0x0000500C
#define CS35L36_SWIRE_FS_SEL 0x00005010
#define CS35L36_SPARE_CP_BITS 0x00005C00
#define CS35L36_AMP_DIG_VOL_CTRL 0x00006000
#define CS35L36_VPBR_CFG 0x00006404
#define CS35L36_VBBR_CFG 0x00006408
#define CS35L36_VPBR_STATUS 0x0000640C
#define CS35L36_VBBR_STATUS 0x00006410
#define CS35L36_OVERTEMP_CFG 0x00006414
#define CS35L36_AMP_ERR_VOL 0x00006418
#define CS35L36_CLASSH_CFG 0x00006800
#define CS35L36_CLASSH_FET_DRV_CFG 0x00006804
#define CS35L36_NG_CFG 0x00006808
#define CS35L36_AMP_GAIN_CTRL 0x00006C04
#define CS35L36_PWM_MOD_IO_CTRL 0x0000706C
#define CS35L36_PWM_MOD_STATUS 0x00007070
#define CS35L36_DAC_MSM_CFG 0x00007400
#define CS35L36_AMP_SLOPE_CTRL 0x00007410
#define CS35L36_AMP_PDM_VOLUME 0x00007E04
#define CS35L36_AMP_PDM_RATE_CTRL 0x00007E08
#define CS35L36_PDM_CH_SEL 0x00007E10
#define CS35L36_AMP_NG_CTRL 0x00007E14
#define CS35L36_PDM_HIGHFILT_CTRL 0x00007E3C
#define CS35L36_INT1_STATUS 0x00D00000
#define CS35L36_INT2_STATUS 0x00D00004
#define CS35L36_INT3_STATUS 0x00D00008
#define CS35L36_INT4_STATUS 0x00D0000C
#define CS35L36_INT1_RAW_STATUS 0x00D00020
#define CS35L36_INT2_RAW_STATUS 0x00D00024
#define CS35L36_INT3_RAW_STATUS 0x00D00028
#define CS35L36_INT4_RAW_STATUS 0x00D0002C
#define CS35L36_INT1_MASK 0x00D00040
#define CS35L36_INT2_MASK 0x00D00044
#define CS35L36_INT3_MASK 0x00D00048
#define CS35L36_INT4_MASK 0x00D0004C
#define CS35L36_INT1_EDGE_LVL_CTRL 0x00D00060
#define CS35L36_INT3_EDGE_LVL_CTRL 0x00D00068
#define CS35L36_PAC_INT_STATUS 0x00D00200
#define CS35L36_PAC_INT_RAW_STATUS 0x00D00210
#define CS35L36_PAC_INT_FLUSH_CTRL 0x00D00218
#define CS35L36_PAC_INT0_CTRL 0x00D00220
#define CS35L36_PAC_INT1_CTRL 0x00D00224
#define CS35L36_PAC_INT2_CTRL 0x00D00228
#define CS35L36_PAC_INT3_CTRL 0x00D0022C
#define CS35L36_PAC_INT4_CTRL 0x00D00230
#define CS35L36_PAC_INT5_CTRL 0x00D00234
#define CS35L36_PAC_INT6_CTRL 0x00D00238
#define CS35L36_PAC_INT7_CTRL 0x00D0023C
#define CS35L36_PAC_PMEM_WORD0 0x00E02800
#define CS35L36_PAC_PMEM_WORD1 0x00E02804
#define CS35L36_PAC_PMEM_WORD1023 0x00E037FC
#define CS35L36_MAX_CACHE_REG 0x00007E44
#define CS35L36_INTPAC_REG_COUNT 25
#define CS35L36_CHIP_ID 0x00035A36
#define CS35L36_INT_OUTPUT_EN_MASK 0x01
#define CS35L36_INT_GPIO_SEL_MASK 0x02
#define CS35L36_INT_GPIO_SEL_SHIFT 1
#define CS35L36_INT_POL_SEL_MASK 0x04
#define CS35L36_INT_POL_SEL_SHIFT 2
#define CS35L36_INT_DRV_SEL_MASK 0x10
#define CS35L36_INT_DRV_SEL_SHIFT 5
#define CS35L36_IRQ_SRC_MASK 0x08
#define CS35L36_IRQ_SRC_SHIFT 3
#define CS35L36_SCLK_MSTR_MASK 0x40
#define CS35L36_SCLK_MSTR_SHIFT 6
#define CS35L36_LRCLK_MSTR_MASK 0x01
#define CS35L36_LRCLK_MSTR_SHIFT 0
#define CS35L36_SCLK_INV_MASK 0x100
#define CS35L36_SCLK_INV_SHIFT 8
#define CS35L36_LRCLK_INV_MASK 0x04
#define CS35L36_LRCLK_INV_SHIFT 2
#define CS35L36_SCLK_FRC_MASK 0x80
#define CS35L36_SCLK_FRC_SHIFT 7
#define CS35L36_LRCLK_FRC_MASK 0x02
#define CS35L36_LRCLK_FRC_SHIFT 1
#define CS35L36_PDM_MODE_MASK 0x01
#define CS35L36_PDM_MODE_SHIFT 0
#define CS35L36_ASP_FMT_MASK 0x07
#define CS35L36_ASP_FMT_SHIFT 0
#define CS35L36_ASP_RX_WIDTH_MASK 0xFF0000
#define CS35L36_ASP_RX_WIDTH_SHIFT 16
#define CS35L36_ASP_TX_WIDTH_MASK 0xFF
#define CS35L36_ASP_TX_WIDTH_SHIFT 0
#define CS35L36_ASP_WIDTH_16 0x10
#define CS35L36_ASP_WIDTH_24 0x18
#define CS35L36_ASP_WIDTH_32 0x20
#define CS35L36_ASP_RX1_SLOT_MASK 0x3F
#define CS35L36_ASP_RX1_EN_MASK 0x00010000
#define CS35L36_ASP_RX1_EN_SHIFT 16
#define CS35L36_ASP_TX1_SLOT_MASK 0x3F
#define CS35L36_ASP_TX2_SLOT_MASK 0x3F0000
#define CS35L36_ASP_TX2_SLOT_SHIFT 16
#define CS35L36_ASP_TX3_SLOT_MASK 0x3F
#define CS35L36_ASP_TX4_SLOT_MASK 0x3F0000
#define CS35L36_ASP_TX4_SLOT_SHIFT 16
#define CS35L36_ASP_TX5_SLOT_MASK 0x3F
#define CS35L36_ASP_TX6_SLOT_MASK 0x3F0000
#define CS35L36_ASP_TX6_SLOT_SHIFT 16
#define CS35L36_ASP_TX7_SLOT_MASK 0x3F
#define CS35L36_ASP_TX8_SLOT_MASK 0x3F0000
#define CS35L36_ASP_TX8_SLOT_SHIFT 16
#define CS35L36_ASP_TX_HIZ_MASK 0x200000
#define CS35L36_APS_TX_SEL_MASK 0x7F
#define CS35L36_ASP_TX1_EN_MASK 0x01
#define CS35L36_ASP_TX2_EN_MASK 0x02
#define CS35L36_ASP_TX2_EN_SHIFT 1
#define CS35L36_ASP_TX3_EN_MASK 0x04
#define CS35L36_ASP_TX3_EN_SHIFT 2
#define CS35L36_ASP_TX4_EN_MASK 0x08
#define CS35L36_ASP_TX4_EN_SHIFT 3
#define CS35L36_ASP_TX5_EN_MASK 0x10
#define CS35L36_ASP_TX5_EN_SHIFT 4
#define CS35L36_ASP_TX6_EN_MASK 0x20
#define CS35L36_ASP_TX6_EN_SHIFT 5
#define CS35L36_ASP_TX7_EN_MASK 0x40
#define CS35L36_ASP_TX7_EN_SHIFT 6
#define CS35L36_ASP_TX8_EN_MASK 0x80
#define CS35L36_ASP_TX8_EN_SHIFT 7
#define CS35L36_PLL_CLK_SEL_MASK 0x07
#define CS35L36_PLL_CLK_SEL_SHIFT 0
#define CS35L36_PLLSRC_SCLK 0
#define CS35L36_PLLSRC_LRCLK 1
#define CS35L36_PLLSRC_SELF 3
#define CS35L36_PLLSRC_PDMCLK 4
#define CS35L36_PLLSRC_MCLK 5
#define CS35L36_PLLSRC_SWIRE 7
#define CS35L36_REFCLK_FREQ_MASK 0x7E0
#define CS35L36_REFCLK_FREQ_SHIFT 5
#define CS35L36_PLL_OPENLOOP_MASK 0x800
#define CS35L36_PLL_OPENLOOP_SHIFT 11
#define CS35L36_PLL_REFCLK_EN_MASK 0x10
#define CS35L36_PLL_REFCLK_EN_SHIFT 4
#define CS35L36_GLOBAL_FS_MASK 0x1F
#define CS35L36_GLOBAL_FS_SHIFT 0
#define CS35L36_HPF_PCM_EN_MASK 0x800
#define CS35L36_HPF_PCM_EN_SHIFT 15
#define CS35L36_PCM_RX_SEL_MASK 0x7F
#define CS35L36_PCM_RX_SEL_SHIFT 0
#define CS35L36_PCM_RX_SEL_ZERO 0x00
#define CS35L36_PCM_RX_SEL_PCM 0x08
#define CS35L36_PCM_RX_SEL_SWIRE 0x10
#define CS35L36_PCM_RX_SEL_DIAG 0x04
#define CS35L36_GLOBAL_EN_MASK 0x01
#define CS35L36_GLOBAL_EN_SHIFT 0x00
#define CS35L36_AMP_PCM_INV_MASK 0x4000
#define CS35L36_AMP_PCM_INV_SHIFT 14
#define CS35L36_AMP_VOL_PCM_MASK 0x3FF8
#define CS35L36_AMP_VOL_PCM_SHIFT 3
#define CS35L36_DIGITAL_MUTE 0x04CF
#define CS35L36_AMP_RAMP_MASK 0x0007
#define CS35L36_AMP_RAMP_SHIFT 0
#define CS35L36_AMP_MUTE_MASK 0x0010
#define CS35L36_AMP_MUTE_SHIFT 4
#define CS35L36_GLOBAL_RESYNC_FS1_MASK 0x00000200
#define CS35L36_GLOBAL_RESYNC_FS2_MASK 0x00000400
#define CS35L36_SYNC_GLOBAL_OVR_MASK 0x00000002
#define CS35L36_SYNC_GLOBAL_OVR_SHIFT 1
#define CS35L36_REFCLK_IN_MASK 0x00100000
#define CS35L36_PLL_UNLOCK_MASK 0x00002000
#define CS35L36_ASP_RX_UDF_MASK 0x00000040
#define CS35L36_ASP_RX_OVF_MASK 0x00000080
#define CS35L36_IMON_POL_MASK 0x02
#define CS35L36_IMON_POL_SHIFT 1
#define CS35L36_VMON_POL_MASK 0x01
#define CS35L36_VMON_POL_SHIFT 0
#define CS35L36_PDN_DONE 0x40
#define CS35L36_PDN_DONE_SHIFT 6
#define CS35L36_PUP_DONE 0x80
#define CS35L36_PUP_DONE_SHIFT 7
#define CS35L36_GLOBAL_EN_ASSRT 0x20
#define CS35L36_PUP_DONE_IRQ_UNMASK 0x7F
#define CS35L36_PUP_DONE_IRQ_MASK 0xBF
#define CS35L36_FS1_WINDOW_MASK 0x000007FF
#define CS35L36_FS2_WINDOW_MASK 0x00FFF800
#define CS35L36_FS2_WINDOW_SHIFT 12
#define CS35L36_PLL_FFL_IGAIN_MASK 0x0F
#define CS35L36_PLL_IGAIN_MASK 0x3F0
#define CS35L36_PLL_IGAIN_SHIFT 4
#define CS35L36_PLL_IGAIN 0x04
#define CS35L36_BST_EN_MASK 0x30
#define CS35L36_BST_EN 0x02
#define CS35L36_BST_DIS_VP 0x01
#define CS35L36_BST_DIS_EXTN 0x00
#define CS35L36_BST_EN_SHIFT 4
#define CS35L36_BST_MAN_IPKCOMP_MASK 0x200
#define CS35L36_BST_MAN_IPKCOMP_SHIFT 9
#define CS35L36_VPBR_EN_SHIFT 12
#define CS35L36_VPBR_EN_MASK 0x1000
#define CS35L36_BST_MAN_IPKCOMP_EN_MASK 0x100
#define CS35L36_BST_MAN_IPKCOMP_EN_SHIFT 8
#define CS35L36_VPBR_REL_RATE_SHIFT 21
#define CS35L36_VPBR_REL_RATE_MASK 0xE00000
#define CS35L36_VPBR_THLD_SHIFT 0
#define CS35L36_VPBR_THLD_MASK 0x1F
#define CS35L36_VPBR_ATK_VOL_SHIFT 12
#define CS35L36_VPBR_ATK_VOL_MASK 0xF000
#define CS35L36_VPBR_WAIT_SHIFT 19
#define CS35L36_VPBR_WAIT_MASK 0x180000
#define CS35L36_VPBR_ATK_RATE_SHIFT 16
#define CS35L36_VPBR_ATK_RATE_MASK 0x70000
#define CS35L36_BST_IPK_MASK 0x7F
#define CS35L36_BST_OVP_THLD_MASK 0x3F
#define CS35L36_BST_OVP_THLD_11V 0x10
#define CS35L36_BST_OVP_TRIM_MASK 0x00078000
#define CS35L36_BST_OVP_TRIM_SHIFT 15
#define CS35L36_BST_OVP_TRIM_11V 0x0C
#define CS35L36_BST_CTRL_LIM_MASK 0x04
#define CS35L36_BST_CTRL_LIM_SHIFT 2
#define CS35L36_BST_CTRL_10V_CLAMP 0x96
#define CS35L36_NG_AMP_EN_MASK 0x3F00
#define CS35L36_NG_AMP_EN_SHIFT 8
#define CS35L36_NG_DELAY_MASK 0x70
#define CS35L36_NG_DELAY_SHIFT 4
#define CS35L36_AMP_ZC_MASK 0x400
#define CS35L36_PDM_LDM_ENTER_MASK 0x08
#define CS35L36_PDM_LDM_EXIT_MASK 0x10
#define CS35L36_BSTCVRT_K1_MASK 0xFF
#define CS35L36_BSTCVRT_K2_MASK 0xFF00
#define CS35L36_BSTCVRT_K2_SHIFT 8
#define CS35L36_BSTCVRT_SLOPE_MASK 0xFF00
#define CS35L36_BSTCVRT_SLOPE_SHIFT 8
#define CS35L36_BSTCVRT_CCMFREQ_MASK 0x0F
#define CS35L36_BSTCVRT_LBSTVAL_MASK 0x03
#define CS35L35_BSTCVRT_CTL_MASK 0xFF
#define CS35L35_BSTCVRT_CTL_SEL_MASK 0x03
#define CS35L36_DCM_AUTO_MASK 0x01
#define CS35L36_INT1_MASK_DEFAULT 0xF9BA7FFF
#define CS35L36_INT1_MASK_RESET 0xFFFFFFFF
#define CS35L36_INT3_MASK_DEFAULT 0xFFFFEFFF
#define CS35L36_INT3_MASK_RESET 0xFFFFFFFF
#define CS35L36_AMP_SHORT_ERR 0x1000
#define CS35L36_BST_SHORT_ERR 0x40000
#define CS35L36_TEMP_WARN 0x2000000
#define CS35L36_TEMP_ERR 0x4000000
#define CS35L36_BST_OVP_ERR 0x10000
#define CS35L36_BST_DCM_UVP_ERR 0x20000
#define CS35L36_AMP_SHORT_ERR_RLS 0x02
#define CS35L36_BST_SHORT_ERR_RLS 0x04
#define CS35L36_BST_OVP_ERR_RLS 0x08
#define CS35L36_BST_UVP_ERR_RLS 0x10
#define CS35L36_TEMP_WARN_ERR_RLS 0x20
#define CS35L36_TEMP_ERR_RLS 0x40
#define CS35L36_TEMP_THLD_MASK 0x03
#define CS35L36_REV_B0 0xb0
#define CS35L36_REV_A0 0xa0
#define CS35L36_B0_PAC_PATCH 0x00DD0102
#define CS35L36_OTP_ECC_EN_MASK 0x400
#define CS35L36_OTP_ECC_EN_SHIFT 10
#define CS35L36_OTP_RUN_BOOT_MASK 0x01
#define CS35L36_OTP_BOOT_DONE 0x2000000
#define CS35L36_PAC_RESET_MASK 0x04
#define CS35L36_PAC_RESET_SHIFT 2
#define CS35L36_PAC_STALL_MASK 0x02
#define CS35L36_PAC_STALL_SHIFT 1
#define CS35L36_PAC_ENABLE_MASK 0x00000001
#define CS35L36_PAC_MEM_ACCESS 0x01
#define CS35L36_PAC_MEM_ACCESS_CLR 0
#define CS35L36_SOFT_RESET 0x5AAA
#define CS35L36_MCU_BOOT_COMPLETE 0x02
#define CS35L36_MCU_CONFIG_UNMASK 0x00FEFFFF
#define CS35L36_MCU_CONFIG_CLR 0x00010000
#define CS35L36_MCU_CONFIG_MASK 0x00FFFFFF
#define CS35L36_GPIO_INT_SEL_MASK 0x0000003B
#define CS35L36_GPIO_INT_SEL_UNMASK 0x0000003A
#define CS35L36_PAC_RESET 0x00000000
#define CS35L36_OTP_REV_MASK 0x00FF0000
#define CS35L36_OTP_REV_L37 0x00CC0000
#define CS35L36_12V_L37 37
#define CS35L36_10V_L36 36
#define CS35L36_OSC_FREQ_TRIM_MASK 0x070
#define CS35L36_OSC_TRIM_DONE 0x08
#define CS35L36_TEST_UNLOCK1 0x00005555
#define CS35L36_TEST_UNLOCK2 0x0000AAAA
#define CS35L36_TEST_LOCK1 0x0000CCCC
#define CS35L36_TEST_LOCK2 0x00003333
#define CS35L36_PAC_PROG_MEM 512
#define CS35L36_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
#define CS35L36_TX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE \
| SNDRV_PCM_FMTBIT_S32_LE)
bool cs35l36_readable_reg(struct device *dev, unsigned int reg);
bool cs35l36_volatile_reg(struct device *dev, unsigned int reg);
extern struct reg_default cs35l36_reg[CS35L36_MAX_CACHE_REG];
extern const unsigned int cs35l36_aou_low_power_patch[CS35L36_PAC_PROG_MEM];
#endif

View file

@ -1,153 +0,0 @@
/*
* cs35l41-i2c.c -- CS35l41 I2C driver
*
* Copyright 2017 Cirrus Logic, Inc.
*
* Author: David Rhodes <david.rhodes@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/version.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/gpio/consumer.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/regmap.h>
#include <linux/gpio.h>
#include "wm_adsp.h"
#include "cs35l41.h"
#include <sound/cs35l41.h>
static struct regmap_config cs35l41_regmap_i2c = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.reg_format_endian = REGMAP_ENDIAN_BIG,
.val_format_endian = REGMAP_ENDIAN_BIG,
.max_register = CS35L41_LASTREG,
.reg_defaults = cs35l41_reg,
.num_reg_defaults = ARRAY_SIZE(cs35l41_reg),
.volatile_reg = cs35l41_volatile_reg,
.readable_reg = cs35l41_readable_reg,
.precious_reg = cs35l41_precious_reg,
.cache_type = REGCACHE_RBTREE,
};
static const struct i2c_device_id cs35l41_id_i2c[] = {
{"cs35l40", 0},
{"cs35l41", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, cs35l41_id_i2c);
static ssize_t gpio_status_show(struct device *dev, struct device_attribute *attr, char *buf)
{
u32 int_status = 0;
struct cs35l41_private *cs35l41 = dev_get_drvdata(dev);
if (cs35l41 != NULL)
{
regmap_read(cs35l41->regmap, CS35L41_GPIO_STATUS1, &int_status);
dev_err(cs35l41->dev, "gpio_status_show read regmap:%d\n", int_status);
}
else
{
dev_err(cs35l41->dev, "gpio_status_show cs35l41 not init\n");
}
return snprintf(buf, PAGE_SIZE, "%d\n", int_status);
}
static DEVICE_ATTR(gpio_status, S_IRUGO, gpio_status_show, NULL);
static struct attribute *gpio_status_attrs[] = {
&dev_attr_gpio_status.attr,
NULL,
};
static struct attribute_group gpio_status_attr_group = {
.attrs = gpio_status_attrs,
};
static int cs35l41_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct cs35l41_private *cs35l41;
struct device *dev = &client->dev;
struct cs35l41_platform_data *pdata = dev_get_platdata(dev);
const struct regmap_config *regmap_config = &cs35l41_regmap_i2c;
int ret;
cs35l41 = devm_kzalloc(dev, sizeof(struct cs35l41_private), GFP_KERNEL);
if (cs35l41 == NULL)
return -ENOMEM;
cs35l41->dev = dev;
cs35l41->irq = client->irq;
cs35l41->bus_spi = false;
i2c_set_clientdata(client, cs35l41);
cs35l41->regmap = devm_regmap_init_i2c(client, regmap_config);
if (IS_ERR(cs35l41->regmap)) {
ret = PTR_ERR(cs35l41->regmap);
dev_err(cs35l41->dev, "Failed to allocate register map: %d\n",
ret);
return ret;
}
ret = sysfs_create_group(&cs35l41->dev->kobj, &gpio_status_attr_group);
if (ret < 0)
dev_err(cs35l41->dev, "sysfs group creation failed, ret = %d\n", ret);
return cs35l41_probe(cs35l41, pdata);
}
static int cs35l41_i2c_remove(struct i2c_client *client)
{
struct cs35l41_private *cs35l41 = i2c_get_clientdata(client);
regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1, 0xFFFFFFFF);
wm_adsp2_remove(&cs35l41->dsp);
regulator_bulk_disable(cs35l41->num_supplies, cs35l41->supplies);
snd_soc_unregister_codec(cs35l41->dev);
return 0;
}
static const struct of_device_id cs35l41_of_match[] = {
{.compatible = "cirrus,cs35l40"},
{.compatible = "cirrus,cs35l41"},
{},
};
MODULE_DEVICE_TABLE(of, cs35l41_of_match);
static struct i2c_driver cs35l41_i2c_driver = {
.driver = {
.name = "cs35l41",
.of_match_table = cs35l41_of_match,
},
.id_table = cs35l41_id_i2c,
.probe = cs35l41_i2c_probe,
.remove = cs35l41_i2c_remove,
};
module_i2c_driver(cs35l41_i2c_driver);
MODULE_DESCRIPTION("I2C CS35L41 driver");
MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <david.rhodes@cirrus.com>");
MODULE_LICENSE("GPL");

View file

@ -1,116 +0,0 @@
/*
* cs35l41-spi.c -- CS35l41 SPI driver
*
* Copyright 2017 Cirrus Logic, Inc.
*
* Author: David Rhodes <david.rhodes@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/version.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include "wm_adsp.h"
#include "cs35l41.h"
#include <sound/cs35l41.h>
static struct regmap_config cs35l41_regmap_spi = {
.reg_bits = 32,
.val_bits = 32,
.pad_bits = 16,
.reg_stride = 4,
.reg_format_endian = REGMAP_ENDIAN_BIG,
.val_format_endian = REGMAP_ENDIAN_BIG,
.max_register = CS35L41_LASTREG,
.reg_defaults = cs35l41_reg,
.num_reg_defaults = ARRAY_SIZE(cs35l41_reg),
.volatile_reg = cs35l41_volatile_reg,
.readable_reg = cs35l41_readable_reg,
.precious_reg = cs35l41_precious_reg,
.cache_type = REGCACHE_RBTREE,
};
static const struct spi_device_id cs35l41_id_spi[] = {
{"cs35l40", 0},
{"cs35l41", 0},
{}
};
MODULE_DEVICE_TABLE(spi, cs35l41_id_spi);
static int cs35l41_spi_probe(struct spi_device *spi)
{
const struct regmap_config *regmap_config = &cs35l41_regmap_spi;
struct cs35l41_platform_data *pdata =
dev_get_platdata(&spi->dev);
struct cs35l41_private *cs35l41;
int ret;
cs35l41 = devm_kzalloc(&spi->dev,
sizeof(struct cs35l41_private),
GFP_KERNEL);
if (cs35l41 == NULL)
return -ENOMEM;
spi_set_drvdata(spi, cs35l41);
cs35l41->regmap = devm_regmap_init_spi(spi, regmap_config);
if (IS_ERR(cs35l41->regmap)) {
ret = PTR_ERR(cs35l41->regmap);
dev_err(&spi->dev, "Failed to allocate register map: %d\n",
ret);
return ret;
}
cs35l41->dev = &spi->dev;
cs35l41->irq = spi->irq;
cs35l41->bus_spi = true;
return cs35l41_probe(cs35l41, pdata);
}
static int cs35l41_spi_remove(struct spi_device *spi)
{
struct cs35l41_private *cs35l41 = spi_get_drvdata(spi);
regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1, 0xFFFFFFFF);
wm_adsp2_remove(&cs35l41->dsp);
regulator_bulk_disable(cs35l41->num_supplies, cs35l41->supplies);
snd_soc_unregister_codec(cs35l41->dev);
return 0;
}
static const struct of_device_id cs35l41_of_match[] = {
{.compatible = "cirrus,cs35l40"},
{.compatible = "cirrus,cs35l41"},
{},
};
MODULE_DEVICE_TABLE(of, cs35l41_of_match);
static struct spi_driver cs35l41_spi_driver = {
.driver = {
.name = "cs35l41",
.of_match_table = cs35l41_of_match,
},
.id_table = cs35l41_id_spi,
.probe = cs35l41_spi_probe,
.remove = cs35l41_spi_remove,
};
module_spi_driver(cs35l41_spi_driver);
MODULE_DESCRIPTION("SPI CS35L41 driver");
MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <david.rhodes@cirrus.com>");
MODULE_LICENSE("GPL");

View file

@ -1,953 +0,0 @@
/*
* cs35l41-tables.c -- CS35L41 ALSA SoC audio driver
*
* Copyright 2018 Cirrus Logic, Inc.
*
* Author: Brian Austin <brian.austin@cirrus.com>
* David Rhodes <david.rhodes@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 "cs35l41.h"
const struct reg_default cs35l41_reg[CS35L41_MAX_CACHE_REG] = {
{CS35L41_TEST_KEY_CTL, 0x00000000},
{CS35L41_USER_KEY_CTL, 0x00000000},
{CS35L41_OTP_CTRL0, 0x00006418},
{CS35L41_OTP_CTRL1, 0x00000000},
{CS35L41_OTP_CTRL3, 0x00000000},
{CS35L41_OTP_CTRL4, 0x00000000},
{CS35L41_OTP_CTRL5, 0x00000030},
{CS35L41_OTP_CTRL6, 0x00000000},
{CS35L41_OTP_CTRL7, 0x00000000},
{CS35L41_OTP_CTRL8, 0x00000000},
{CS35L41_PWR_CTRL1, 0x00000000},
{CS35L41_PWR_CTRL3, 0x01000010},
{CS35L41_CTRL_OVRRIDE, 0x00000002},
{CS35L41_AMP_OUT_MUTE, 0x00000000},
{CS35L41_PROTECT_REL_ERR_IGN, 0x00000000},
{CS35L41_GPIO_PAD_CONTROL, 0x00000000},
{CS35L41_JTAG_CONTROL, 0x00000000},
{CS35L41_PLL_CLK_CTRL, 0x00000010},
{CS35L41_DSP_CLK_CTRL, 0x00000003},
{CS35L41_GLOBAL_CLK_CTRL, 0x00000003},
{CS35L41_DATA_FS_SEL, 0x00000000},
{CS35L41_MDSYNC_EN, 0x00000200},
{CS35L41_MDSYNC_TX_ID, 0x00000000},
{CS35L41_MDSYNC_PWR_CTRL, 0x00000002},
{CS35L41_MDSYNC_DATA_TX, 0x00000000},
{CS35L41_MDSYNC_TX_STATUS, 0x00000002},
{CS35L41_MDSYNC_DATA_RX, 0x00000000},
{CS35L41_MDSYNC_RX_STATUS, 0x00000002},
{CS35L41_MDSYNC_ERR_STATUS, 0x00000000},
{CS35L41_MDSYNC_SYNC_PTE2, 0x00000000},
{CS35L41_MDSYNC_SYNC_PTE3, 0x00000000},
{CS35L41_MDSYNC_SYNC_MSM_STATUS, 0x00000000},
{CS35L41_BSTCVRT_VCTRL1, 0x00000000},
{CS35L41_BSTCVRT_VCTRL2, 0x00000001},
{CS35L41_BSTCVRT_PEAK_CUR, 0x0000004A},
{CS35L41_BSTCVRT_SFT_RAMP, 0x00000003},
{CS35L41_BSTCVRT_COEFF, 0x00002424},
{CS35L41_BSTCVRT_SLOPE_LBST, 0x00007500},
{CS35L41_BSTCVRT_SW_FREQ, 0x01008000},
{CS35L41_BSTCVRT_DCM_CTRL, 0x00002001},
{CS35L41_BSTCVRT_DCM_MODE_FORCE, 0x00000000},
{CS35L41_BSTCVRT_OVERVOLT_CTRL, 0x00000130},
{CS35L41_VI_VOL_POL, 0x08000800},
{CS35L41_DTEMP_WARN_THLD, 0x00000002},
{CS35L41_DTEMP_EN, 0x00000000},
{CS35L41_VPVBST_FS_SEL, 0x00000001},
{CS35L41_SP_ENABLES, 0x00000000},
{CS35L41_SP_RATE_CTRL, 0x00000028},
{CS35L41_SP_FORMAT, 0x18180200},
{CS35L41_SP_HIZ_CTRL, 0x00000002},
{CS35L41_SP_FRAME_TX_SLOT, 0x03020100},
{CS35L41_SP_FRAME_RX_SLOT, 0x00000100},
{CS35L41_SP_TX_WL, 0x00000018},
{CS35L41_SP_RX_WL, 0x00000018},
{CS35L41_DAC_PCM1_SRC, 0x00000008},
{CS35L41_ASP_TX1_SRC, 0x00000018},
{CS35L41_ASP_TX2_SRC, 0x00000019},
{CS35L41_ASP_TX3_SRC, 0x00000020},
{CS35L41_ASP_TX4_SRC, 0x00000021},
{CS35L41_DSP1_RX1_SRC, 0x00000008},
{CS35L41_DSP1_RX2_SRC, 0x00000009},
{CS35L41_DSP1_RX3_SRC, 0x00000018},
{CS35L41_DSP1_RX4_SRC, 0x00000019},
{CS35L41_DSP1_RX5_SRC, 0x00000020},
{CS35L41_DSP1_RX6_SRC, 0x00000021},
{CS35L41_DSP1_RX7_SRC, 0x0000003A},
{CS35L41_DSP1_RX8_SRC, 0x00000001},
{CS35L41_NGATE1_SRC, 0x00000008},
{CS35L41_NGATE2_SRC, 0x00000009},
{CS35L41_AMP_DIG_VOL_CTRL, 0x00008000},
{CS35L41_VPBR_CFG, 0x02AA1905},
{CS35L41_VBBR_CFG, 0x02AA1905},
{CS35L41_VPBR_STATUS, 0x00000000},
{CS35L41_VBBR_STATUS, 0x00000000},
{CS35L41_OVERTEMP_CFG, 0x00000001},
{CS35L41_AMP_ERR_VOL, 0x00000000},
{CS35L41_VOL_STATUS_TO_DSP, 0x00000000},
{CS35L41_CLASSH_CFG, 0x000B0405},
{CS35L41_WKFET_CFG, 0x00000111},
{CS35L41_NG_CFG, 0x00000033},
{CS35L41_AMP_GAIN_CTRL, 0x00000273},
{CS35L41_DAC_MSM_CFG, 0x00580000},
{CS35L41_GPIO1_CTRL1, 0xE1000001},
{CS35L41_GPIO2_CTRL1, 0xE1000001},
{CS35L41_MIXER_NGATE_CFG, 0x00000000},
{CS35L41_MIXER_NGATE_CH1_CFG, 0x00000303},
{CS35L41_MIXER_NGATE_CH2_CFG, 0x00000303},
{CS35L41_CLOCK_DETECT_1, 0x00000000},
{CS35L41_TIMER1_CONTROL, 0x00000000},
{CS35L41_TIMER1_COUNT_PRESET, 0x00000000},
{CS35L41_TIMER1_START_STOP, 0x00000000},
{CS35L41_TIMER1_STATUS, 0x00000000},
{CS35L41_TIMER1_COUNT_READBACK, 0x00000000},
{CS35L41_TIMER1_DSP_CLK_CFG, 0x00000000},
{CS35L41_TIMER1_DSP_CLK_STATUS, 0x00000000},
{CS35L41_TIMER2_CONTROL, 0x00000000},
{CS35L41_TIMER2_COUNT_PRESET, 0x00000000},
{CS35L41_TIMER2_START_STOP, 0x00000000},
{CS35L41_TIMER2_STATUS, 0x00000000},
{CS35L41_TIMER2_COUNT_READBACK, 0x00000000},
{CS35L41_TIMER2_DSP_CLK_CFG, 0x00000000},
{CS35L41_TIMER2_DSP_CLK_STATUS, 0x00000000},
{CS35L41_DFT_JTAG_CONTROL, 0x00000000},
{CS35L41_DIE_STS1, 0x00000000},
{CS35L41_DIE_STS2, 0x00000000},
{CS35L41_TEMP_CAL1, 0x00000000},
{CS35L41_TEMP_CAL2, 0x00000000},
};
bool cs35l41_readable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case CS35L41_DEVID:
case CS35L41_REVID:
case CS35L41_FABID:
case CS35L41_RELID:
case CS35L41_OTPID:
case CS35L41_TEST_KEY_CTL:
case CS35L41_USER_KEY_CTL:
case CS35L41_OTP_CTRL0:
case CS35L41_OTP_CTRL3:
case CS35L41_OTP_CTRL4:
case CS35L41_OTP_CTRL5:
case CS35L41_OTP_CTRL6:
case CS35L41_OTP_CTRL7:
case CS35L41_OTP_CTRL8:
case CS35L41_PWR_CTRL1:
case CS35L41_PWR_CTRL2:
case CS35L41_PWR_CTRL3:
case CS35L41_CTRL_OVRRIDE:
case CS35L41_AMP_OUT_MUTE:
case CS35L41_PROTECT_REL_ERR_IGN:
case CS35L41_GPIO_PAD_CONTROL:
case CS35L41_JTAG_CONTROL:
case CS35L41_PLL_CLK_CTRL:
case CS35L41_DSP_CLK_CTRL:
case CS35L41_GLOBAL_CLK_CTRL:
case CS35L41_DATA_FS_SEL:
case CS35L41_MDSYNC_EN:
case CS35L41_MDSYNC_TX_ID:
case CS35L41_MDSYNC_PWR_CTRL:
case CS35L41_MDSYNC_DATA_TX:
case CS35L41_MDSYNC_TX_STATUS:
case CS35L41_MDSYNC_DATA_RX:
case CS35L41_MDSYNC_RX_STATUS:
case CS35L41_MDSYNC_ERR_STATUS:
case CS35L41_MDSYNC_SYNC_PTE2:
case CS35L41_MDSYNC_SYNC_PTE3:
case CS35L41_MDSYNC_SYNC_MSM_STATUS:
case CS35L41_BSTCVRT_VCTRL1:
case CS35L41_BSTCVRT_VCTRL2:
case CS35L41_BSTCVRT_PEAK_CUR:
case CS35L41_BSTCVRT_SFT_RAMP:
case CS35L41_BSTCVRT_COEFF:
case CS35L41_BSTCVRT_SLOPE_LBST:
case CS35L41_BSTCVRT_SW_FREQ:
case CS35L41_BSTCVRT_DCM_CTRL:
case CS35L41_BSTCVRT_DCM_MODE_FORCE:
case CS35L41_BSTCVRT_OVERVOLT_CTRL:
case CS35L41_VI_VOL_POL:
case CS35L41_DTEMP_WARN_THLD:
case CS35L41_DTEMP_CFG:
case CS35L41_DTEMP_EN:
case CS35L41_VPVBST_FS_SEL:
case CS35L41_SP_ENABLES:
case CS35L41_SP_RATE_CTRL:
case CS35L41_SP_FORMAT:
case CS35L41_SP_HIZ_CTRL:
case CS35L41_SP_FRAME_TX_SLOT:
case CS35L41_SP_FRAME_RX_SLOT:
case CS35L41_SP_TX_WL:
case CS35L41_SP_RX_WL:
case CS35L41_DAC_PCM1_SRC:
case CS35L41_ASP_TX1_SRC:
case CS35L41_ASP_TX2_SRC:
case CS35L41_ASP_TX3_SRC:
case CS35L41_ASP_TX4_SRC:
case CS35L41_DSP1_RX1_SRC:
case CS35L41_DSP1_RX2_SRC:
case CS35L41_DSP1_RX3_SRC:
case CS35L41_DSP1_RX4_SRC:
case CS35L41_DSP1_RX5_SRC:
case CS35L41_DSP1_RX6_SRC:
case CS35L41_DSP1_RX7_SRC:
case CS35L41_DSP1_RX8_SRC:
case CS35L41_NGATE1_SRC:
case CS35L41_NGATE2_SRC:
case CS35L41_AMP_DIG_VOL_CTRL:
case CS35L41_VPBR_CFG:
case CS35L41_VBBR_CFG:
case CS35L41_VPBR_STATUS:
case CS35L41_VBBR_STATUS:
case CS35L41_OVERTEMP_CFG:
case CS35L41_AMP_ERR_VOL:
case CS35L41_VOL_STATUS_TO_DSP:
case CS35L41_CLASSH_CFG:
case CS35L41_WKFET_CFG:
case CS35L41_NG_CFG:
case CS35L41_AMP_GAIN_CTRL:
case CS35L41_DAC_MSM_CFG:
case CS35L41_IRQ1_CFG:
case CS35L41_IRQ1_STATUS:
case CS35L41_IRQ1_STATUS1:
case CS35L41_IRQ1_STATUS2:
case CS35L41_IRQ1_STATUS3:
case CS35L41_IRQ1_STATUS4:
case CS35L41_IRQ1_RAW_STATUS1:
case CS35L41_IRQ1_RAW_STATUS2:
case CS35L41_IRQ1_RAW_STATUS3:
case CS35L41_IRQ1_RAW_STATUS4:
case CS35L41_IRQ1_MASK1:
case CS35L41_IRQ1_MASK2:
case CS35L41_IRQ1_MASK3:
case CS35L41_IRQ1_MASK4:
case CS35L41_IRQ1_FRC1:
case CS35L41_IRQ1_FRC2:
case CS35L41_IRQ1_FRC3:
case CS35L41_IRQ1_FRC4:
case CS35L41_IRQ1_EDGE1:
case CS35L41_IRQ1_EDGE4:
case CS35L41_IRQ1_POL1:
case CS35L41_IRQ1_POL2:
case CS35L41_IRQ1_POL3:
case CS35L41_IRQ1_POL4:
case CS35L41_IRQ1_DB3:
case CS35L41_IRQ2_CFG:
case CS35L41_IRQ2_STATUS:
case CS35L41_IRQ2_STATUS1:
case CS35L41_IRQ2_STATUS2:
case CS35L41_IRQ2_STATUS3:
case CS35L41_IRQ2_STATUS4:
case CS35L41_IRQ2_RAW_STATUS1:
case CS35L41_IRQ2_RAW_STATUS2:
case CS35L41_IRQ2_RAW_STATUS3:
case CS35L41_IRQ2_RAW_STATUS4:
case CS35L41_IRQ2_MASK1:
case CS35L41_IRQ2_MASK2:
case CS35L41_IRQ2_MASK3:
case CS35L41_IRQ2_MASK4:
case CS35L41_IRQ2_FRC1:
case CS35L41_IRQ2_FRC2:
case CS35L41_IRQ2_FRC3:
case CS35L41_IRQ2_FRC4:
case CS35L41_IRQ2_EDGE1:
case CS35L41_IRQ2_EDGE4:
case CS35L41_IRQ2_POL1:
case CS35L41_IRQ2_POL2:
case CS35L41_IRQ2_POL3:
case CS35L41_IRQ2_POL4:
case CS35L41_IRQ2_DB3:
case CS35L41_GPIO_STATUS1:
case CS35L41_GPIO1_CTRL1:
case CS35L41_GPIO2_CTRL1:
case CS35L41_MIXER_NGATE_CFG:
case CS35L41_MIXER_NGATE_CH1_CFG:
case CS35L41_MIXER_NGATE_CH2_CFG:
case CS35L41_DSP_MBOX_1 ... CS35L41_DSP_VIRT2_MBOX_8:
case CS35L41_CLOCK_DETECT_1:
case CS35L41_TIMER1_CONTROL:
case CS35L41_TIMER1_COUNT_PRESET:
case CS35L41_TIMER1_STATUS:
case CS35L41_TIMER1_COUNT_READBACK:
case CS35L41_TIMER1_DSP_CLK_CFG:
case CS35L41_TIMER1_DSP_CLK_STATUS:
case CS35L41_TIMER2_CONTROL:
case CS35L41_TIMER2_COUNT_PRESET:
case CS35L41_TIMER2_STATUS:
case CS35L41_TIMER2_COUNT_READBACK:
case CS35L41_TIMER2_DSP_CLK_CFG:
case CS35L41_TIMER2_DSP_CLK_STATUS:
case CS35L41_DFT_JTAG_CONTROL:
case CS35L41_DIE_STS1:
case CS35L41_DIE_STS2:
case CS35L41_TEMP_CAL1:
case CS35L41_TEMP_CAL2:
case CS35L41_DSP1_TIMESTAMP_COUNT:
case CS35L41_DSP1_SYS_ID:
case CS35L41_DSP1_SYS_VERSION:
case CS35L41_DSP1_SYS_CORE_ID:
case CS35L41_DSP1_SYS_AHB_ADDR:
case CS35L41_DSP1_SYS_XSRAM_SIZE:
case CS35L41_DSP1_SYS_YSRAM_SIZE:
case CS35L41_DSP1_SYS_PSRAM_SIZE:
case CS35L41_DSP1_SYS_PM_BOOT_SIZE:
case CS35L41_DSP1_SYS_FEATURES:
case CS35L41_DSP1_SYS_FIR_FILTERS:
case CS35L41_DSP1_SYS_LMS_FILTERS:
case CS35L41_DSP1_SYS_XM_BANK_SIZE:
case CS35L41_DSP1_SYS_YM_BANK_SIZE:
case CS35L41_DSP1_SYS_PM_BANK_SIZE:
case CS35L41_DSP1_AHBM_WIN0_CTRL0:
case CS35L41_DSP1_AHBM_WIN0_CTRL1:
case CS35L41_DSP1_AHBM_WIN1_CTRL0:
case CS35L41_DSP1_AHBM_WIN1_CTRL1:
case CS35L41_DSP1_AHBM_WIN2_CTRL0:
case CS35L41_DSP1_AHBM_WIN2_CTRL1:
case CS35L41_DSP1_AHBM_WIN3_CTRL0:
case CS35L41_DSP1_AHBM_WIN3_CTRL1:
case CS35L41_DSP1_AHBM_WIN4_CTRL0:
case CS35L41_DSP1_AHBM_WIN4_CTRL1:
case CS35L41_DSP1_AHBM_WIN5_CTRL0:
case CS35L41_DSP1_AHBM_WIN5_CTRL1:
case CS35L41_DSP1_AHBM_WIN6_CTRL0:
case CS35L41_DSP1_AHBM_WIN6_CTRL1:
case CS35L41_DSP1_AHBM_WIN7_CTRL0:
case CS35L41_DSP1_AHBM_WIN7_CTRL1:
case CS35L41_DSP1_AHBM_WIN_DBG_CTRL0:
case CS35L41_DSP1_AHBM_WIN_DBG_CTRL1:
case CS35L41_DSP1_DEBUG:
case CS35L41_DSP1_TIMER_CTRL:
case CS35L41_DSP1_RX1_RATE:
case CS35L41_DSP1_RX2_RATE:
case CS35L41_DSP1_RX3_RATE:
case CS35L41_DSP1_RX4_RATE:
case CS35L41_DSP1_RX5_RATE:
case CS35L41_DSP1_RX6_RATE:
case CS35L41_DSP1_RX7_RATE:
case CS35L41_DSP1_RX8_RATE:
case CS35L41_DSP1_TX1_RATE:
case CS35L41_DSP1_TX2_RATE:
case CS35L41_DSP1_TX3_RATE:
case CS35L41_DSP1_TX4_RATE:
case CS35L41_DSP1_TX5_RATE:
case CS35L41_DSP1_TX6_RATE:
case CS35L41_DSP1_TX7_RATE:
case CS35L41_DSP1_TX8_RATE:
case CS35L41_DSP1_NMI_CTRL1:
case CS35L41_DSP1_NMI_CTRL2:
case CS35L41_DSP1_NMI_CTRL3:
case CS35L41_DSP1_NMI_CTRL4:
case CS35L41_DSP1_NMI_CTRL5:
case CS35L41_DSP1_NMI_CTRL6:
case CS35L41_DSP1_NMI_CTRL7:
case CS35L41_DSP1_NMI_CTRL8:
case CS35L41_DSP1_RESUME_CTRL:
case CS35L41_DSP1_IRQ1_CTRL:
case CS35L41_DSP1_IRQ2_CTRL:
case CS35L41_DSP1_IRQ3_CTRL:
case CS35L41_DSP1_IRQ4_CTRL:
case CS35L41_DSP1_IRQ5_CTRL:
case CS35L41_DSP1_IRQ6_CTRL:
case CS35L41_DSP1_IRQ7_CTRL:
case CS35L41_DSP1_IRQ8_CTRL:
case CS35L41_DSP1_IRQ9_CTRL:
case CS35L41_DSP1_IRQ10_CTRL:
case CS35L41_DSP1_IRQ11_CTRL:
case CS35L41_DSP1_IRQ12_CTRL:
case CS35L41_DSP1_IRQ13_CTRL:
case CS35L41_DSP1_IRQ14_CTRL:
case CS35L41_DSP1_IRQ15_CTRL:
case CS35L41_DSP1_IRQ16_CTRL:
case CS35L41_DSP1_IRQ17_CTRL:
case CS35L41_DSP1_IRQ18_CTRL:
case CS35L41_DSP1_IRQ19_CTRL:
case CS35L41_DSP1_IRQ20_CTRL:
case CS35L41_DSP1_IRQ21_CTRL:
case CS35L41_DSP1_IRQ22_CTRL:
case CS35L41_DSP1_IRQ23_CTRL:
case CS35L41_DSP1_SCRATCH1:
case CS35L41_DSP1_SCRATCH2:
case CS35L41_DSP1_SCRATCH3:
case CS35L41_DSP1_SCRATCH4:
case CS35L41_DSP1_CCM_CORE_CTRL:
case CS35L41_DSP1_CCM_CLK_OVERRIDE:
case CS35L41_DSP1_XM_MSTR_EN:
case CS35L41_DSP1_XM_CORE_PRI:
case CS35L41_DSP1_XM_AHB_PACK_PL_PRI:
case CS35L41_DSP1_XM_AHB_UP_PL_PRI:
case CS35L41_DSP1_XM_ACCEL_PL0_PRI:
case CS35L41_DSP1_XM_NPL0_PRI:
case CS35L41_DSP1_YM_MSTR_EN:
case CS35L41_DSP1_YM_CORE_PRI:
case CS35L41_DSP1_YM_AHB_PACK_PL_PRI:
case CS35L41_DSP1_YM_AHB_UP_PL_PRI:
case CS35L41_DSP1_YM_ACCEL_PL0_PRI:
case CS35L41_DSP1_YM_NPL0_PRI:
case CS35L41_DSP1_PM_MSTR_EN:
case CS35L41_DSP1_PM_PATCH0_ADDR:
case CS35L41_DSP1_PM_PATCH0_EN:
case CS35L41_DSP1_PM_PATCH0_DATA_LO:
case CS35L41_DSP1_PM_PATCH0_DATA_HI:
case CS35L41_DSP1_PM_PATCH1_ADDR:
case CS35L41_DSP1_PM_PATCH1_EN:
case CS35L41_DSP1_PM_PATCH1_DATA_LO:
case CS35L41_DSP1_PM_PATCH1_DATA_HI:
case CS35L41_DSP1_PM_PATCH2_ADDR:
case CS35L41_DSP1_PM_PATCH2_EN:
case CS35L41_DSP1_PM_PATCH2_DATA_LO:
case CS35L41_DSP1_PM_PATCH2_DATA_HI:
case CS35L41_DSP1_PM_PATCH3_ADDR:
case CS35L41_DSP1_PM_PATCH3_EN:
case CS35L41_DSP1_PM_PATCH3_DATA_LO:
case CS35L41_DSP1_PM_PATCH3_DATA_HI:
case CS35L41_DSP1_PM_PATCH4_ADDR:
case CS35L41_DSP1_PM_PATCH4_EN:
case CS35L41_DSP1_PM_PATCH4_DATA_LO:
case CS35L41_DSP1_PM_PATCH4_DATA_HI:
case CS35L41_DSP1_PM_PATCH5_ADDR:
case CS35L41_DSP1_PM_PATCH5_EN:
case CS35L41_DSP1_PM_PATCH5_DATA_LO:
case CS35L41_DSP1_PM_PATCH5_DATA_HI:
case CS35L41_DSP1_PM_PATCH6_ADDR:
case CS35L41_DSP1_PM_PATCH6_EN:
case CS35L41_DSP1_PM_PATCH6_DATA_LO:
case CS35L41_DSP1_PM_PATCH6_DATA_HI:
case CS35L41_DSP1_PM_PATCH7_ADDR:
case CS35L41_DSP1_PM_PATCH7_EN:
case CS35L41_DSP1_PM_PATCH7_DATA_LO:
case CS35L41_DSP1_PM_PATCH7_DATA_HI:
case CS35L41_DSP1_MPU_XM_ACCESS0:
case CS35L41_DSP1_MPU_YM_ACCESS0:
case CS35L41_DSP1_MPU_WNDW_ACCESS0:
case CS35L41_DSP1_MPU_XREG_ACCESS0:
case CS35L41_DSP1_MPU_YREG_ACCESS0:
case CS35L41_DSP1_MPU_XM_ACCESS1:
case CS35L41_DSP1_MPU_YM_ACCESS1:
case CS35L41_DSP1_MPU_WNDW_ACCESS1:
case CS35L41_DSP1_MPU_XREG_ACCESS1:
case CS35L41_DSP1_MPU_YREG_ACCESS1:
case CS35L41_DSP1_MPU_XM_ACCESS2:
case CS35L41_DSP1_MPU_YM_ACCESS2:
case CS35L41_DSP1_MPU_WNDW_ACCESS2:
case CS35L41_DSP1_MPU_XREG_ACCESS2:
case CS35L41_DSP1_MPU_YREG_ACCESS2:
case CS35L41_DSP1_MPU_XM_ACCESS3:
case CS35L41_DSP1_MPU_YM_ACCESS3:
case CS35L41_DSP1_MPU_WNDW_ACCESS3:
case CS35L41_DSP1_MPU_XREG_ACCESS3:
case CS35L41_DSP1_MPU_YREG_ACCESS3:
case CS35L41_DSP1_MPU_XM_VIO_ADDR:
case CS35L41_DSP1_MPU_XM_VIO_STATUS:
case CS35L41_DSP1_MPU_YM_VIO_ADDR:
case CS35L41_DSP1_MPU_YM_VIO_STATUS:
case CS35L41_DSP1_MPU_PM_VIO_ADDR:
case CS35L41_DSP1_MPU_PM_VIO_STATUS:
case CS35L41_DSP1_MPU_LOCK_CONFIG:
case CS35L41_DSP1_MPU_WDT_RST_CTRL:
case CS35L41_DSP1_STRMARB_MSTR0_CFG0:
case CS35L41_DSP1_STRMARB_MSTR0_CFG1:
case CS35L41_DSP1_STRMARB_MSTR0_CFG2:
case CS35L41_DSP1_STRMARB_MSTR1_CFG0:
case CS35L41_DSP1_STRMARB_MSTR1_CFG1:
case CS35L41_DSP1_STRMARB_MSTR1_CFG2:
case CS35L41_DSP1_STRMARB_MSTR2_CFG0:
case CS35L41_DSP1_STRMARB_MSTR2_CFG1:
case CS35L41_DSP1_STRMARB_MSTR2_CFG2:
case CS35L41_DSP1_STRMARB_MSTR3_CFG0:
case CS35L41_DSP1_STRMARB_MSTR3_CFG1:
case CS35L41_DSP1_STRMARB_MSTR3_CFG2:
case CS35L41_DSP1_STRMARB_MSTR4_CFG0:
case CS35L41_DSP1_STRMARB_MSTR4_CFG1:
case CS35L41_DSP1_STRMARB_MSTR4_CFG2:
case CS35L41_DSP1_STRMARB_MSTR5_CFG0:
case CS35L41_DSP1_STRMARB_MSTR5_CFG1:
case CS35L41_DSP1_STRMARB_MSTR5_CFG2:
case CS35L41_DSP1_STRMARB_MSTR6_CFG0:
case CS35L41_DSP1_STRMARB_MSTR6_CFG1:
case CS35L41_DSP1_STRMARB_MSTR6_CFG2:
case CS35L41_DSP1_STRMARB_MSTR7_CFG0:
case CS35L41_DSP1_STRMARB_MSTR7_CFG1:
case CS35L41_DSP1_STRMARB_MSTR7_CFG2:
case CS35L41_DSP1_STRMARB_TX0_CFG0:
case CS35L41_DSP1_STRMARB_TX0_CFG1:
case CS35L41_DSP1_STRMARB_TX1_CFG0:
case CS35L41_DSP1_STRMARB_TX1_CFG1:
case CS35L41_DSP1_STRMARB_TX2_CFG0:
case CS35L41_DSP1_STRMARB_TX2_CFG1:
case CS35L41_DSP1_STRMARB_TX3_CFG0:
case CS35L41_DSP1_STRMARB_TX3_CFG1:
case CS35L41_DSP1_STRMARB_TX4_CFG0:
case CS35L41_DSP1_STRMARB_TX4_CFG1:
case CS35L41_DSP1_STRMARB_TX5_CFG0:
case CS35L41_DSP1_STRMARB_TX5_CFG1:
case CS35L41_DSP1_STRMARB_TX6_CFG0:
case CS35L41_DSP1_STRMARB_TX6_CFG1:
case CS35L41_DSP1_STRMARB_TX7_CFG0:
case CS35L41_DSP1_STRMARB_TX7_CFG1:
case CS35L41_DSP1_STRMARB_RX0_CFG0:
case CS35L41_DSP1_STRMARB_RX0_CFG1:
case CS35L41_DSP1_STRMARB_RX1_CFG0:
case CS35L41_DSP1_STRMARB_RX1_CFG1:
case CS35L41_DSP1_STRMARB_RX2_CFG0:
case CS35L41_DSP1_STRMARB_RX2_CFG1:
case CS35L41_DSP1_STRMARB_RX3_CFG0:
case CS35L41_DSP1_STRMARB_RX3_CFG1:
case CS35L41_DSP1_STRMARB_RX4_CFG0:
case CS35L41_DSP1_STRMARB_RX4_CFG1:
case CS35L41_DSP1_STRMARB_RX5_CFG0:
case CS35L41_DSP1_STRMARB_RX5_CFG1:
case CS35L41_DSP1_STRMARB_RX6_CFG0:
case CS35L41_DSP1_STRMARB_RX6_CFG1:
case CS35L41_DSP1_STRMARB_RX7_CFG0:
case CS35L41_DSP1_STRMARB_RX7_CFG1:
case CS35L41_DSP1_STRMARB_IRQ0_CFG0:
case CS35L41_DSP1_STRMARB_IRQ0_CFG1:
case CS35L41_DSP1_STRMARB_IRQ0_CFG2:
case CS35L41_DSP1_STRMARB_IRQ1_CFG0:
case CS35L41_DSP1_STRMARB_IRQ1_CFG1:
case CS35L41_DSP1_STRMARB_IRQ1_CFG2:
case CS35L41_DSP1_STRMARB_IRQ2_CFG0:
case CS35L41_DSP1_STRMARB_IRQ2_CFG1:
case CS35L41_DSP1_STRMARB_IRQ2_CFG2:
case CS35L41_DSP1_STRMARB_IRQ3_CFG0:
case CS35L41_DSP1_STRMARB_IRQ3_CFG1:
case CS35L41_DSP1_STRMARB_IRQ3_CFG2:
case CS35L41_DSP1_STRMARB_IRQ4_CFG0:
case CS35L41_DSP1_STRMARB_IRQ4_CFG1:
case CS35L41_DSP1_STRMARB_IRQ4_CFG2:
case CS35L41_DSP1_STRMARB_IRQ5_CFG0:
case CS35L41_DSP1_STRMARB_IRQ5_CFG1:
case CS35L41_DSP1_STRMARB_IRQ5_CFG2:
case CS35L41_DSP1_STRMARB_IRQ6_CFG0:
case CS35L41_DSP1_STRMARB_IRQ6_CFG1:
case CS35L41_DSP1_STRMARB_IRQ6_CFG2:
case CS35L41_DSP1_STRMARB_IRQ7_CFG0:
case CS35L41_DSP1_STRMARB_IRQ7_CFG1:
case CS35L41_DSP1_STRMARB_IRQ7_CFG2:
case CS35L41_DSP1_STRMARB_RESYNC_MSK:
case CS35L41_DSP1_STRMARB_ERR_STATUS:
case CS35L41_DSP1_INTPCTL_RES_STATIC:
case CS35L41_DSP1_INTPCTL_RES_DYN:
case CS35L41_DSP1_INTPCTL_NMI_CTRL:
case CS35L41_DSP1_INTPCTL_IRQ_INV:
case CS35L41_DSP1_INTPCTL_IRQ_MODE:
case CS35L41_DSP1_INTPCTL_IRQ_EN:
case CS35L41_DSP1_INTPCTL_IRQ_MSK:
case CS35L41_DSP1_INTPCTL_IRQ_ERR:
case CS35L41_DSP1_INTPCTL_IRQ_PEND:
case CS35L41_DSP1_INTPCTL_TESTBITS:
case CS35L41_DSP1_WDT_CONTROL:
case CS35L41_DSP1_WDT_STATUS:
case CS35L41_OTP_TRIM_1:
case CS35L41_OTP_TRIM_2:
case CS35L41_OTP_TRIM_3:
case CS35L41_OTP_TRIM_4:
case CS35L41_OTP_TRIM_5:
case CS35L41_OTP_TRIM_6:
case CS35L41_OTP_TRIM_7:
case CS35L41_OTP_TRIM_8:
case CS35L41_OTP_TRIM_9:
case CS35L41_OTP_TRIM_10:
case CS35L41_OTP_TRIM_11:
case CS35L41_OTP_TRIM_12:
case CS35L41_OTP_TRIM_13:
case CS35L41_OTP_TRIM_14:
case CS35L41_OTP_TRIM_15:
case CS35L41_OTP_TRIM_16:
case CS35L41_OTP_TRIM_17:
case CS35L41_OTP_TRIM_18:
case CS35L41_OTP_TRIM_19:
case CS35L41_OTP_TRIM_20:
case CS35L41_OTP_TRIM_21:
case CS35L41_OTP_TRIM_22:
case CS35L41_OTP_TRIM_23:
case CS35L41_OTP_TRIM_24:
case CS35L41_OTP_TRIM_25:
case CS35L41_OTP_TRIM_26:
case CS35L41_OTP_TRIM_27:
case CS35L41_OTP_TRIM_28:
case CS35L41_OTP_TRIM_29:
case CS35L41_OTP_TRIM_30:
case CS35L41_OTP_TRIM_31:
case CS35L41_OTP_TRIM_32:
case CS35L41_OTP_TRIM_33:
case CS35L41_OTP_TRIM_34:
case CS35L41_OTP_TRIM_35:
case CS35L41_OTP_TRIM_36:
case CS35L41_OTP_MEM0 ... CS35L41_OTP_MEM31:
case CS35L41_DSP1_XMEM_PACK_0 ... CS35L41_DSP1_XMEM_PACK_3068:
case CS35L41_DSP1_XMEM_UNPACK32_0 ... CS35L41_DSP1_XMEM_UNPACK32_2046:
case CS35L41_DSP1_XMEM_UNPACK24_0 ... CS35L41_DSP1_XMEM_UNPACK24_4093:
case CS35L41_DSP1_YMEM_PACK_0 ... CS35L41_DSP1_YMEM_PACK_1532:
case CS35L41_DSP1_YMEM_UNPACK32_0 ... CS35L41_DSP1_YMEM_UNPACK32_1022:
case CS35L41_DSP1_YMEM_UNPACK24_0 ... CS35L41_DSP1_YMEM_UNPACK24_2045:
case CS35L41_DSP1_PMEM_0 ... CS35L41_DSP1_PMEM_5114:
/*test regs*/
case CS35L41_PLL_OVR:
case CS35L41_BST_TEST_DUTY:
case CS35L41_DIGPWM_IOCTRL:
return true;
default:
return false;
}
}
bool cs35l41_precious_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case CS35L41_OTP_MEM0 ... CS35L41_OTP_MEM31:
return true;
default:
return false;
}
}
bool cs35l41_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case CS35L41_DEVID:
case CS35L41_SFT_RESET:
case CS35L41_FABID:
case CS35L41_REVID:
case CS35L41_PWR_CTRL1:
case CS35L41_DTEMP_EN:
case CS35L41_IRQ1_STATUS:
case CS35L41_IRQ1_STATUS1:
case CS35L41_IRQ1_STATUS2:
case CS35L41_IRQ1_STATUS3:
case CS35L41_IRQ1_STATUS4:
case CS35L41_IRQ1_RAW_STATUS1:
case CS35L41_IRQ1_RAW_STATUS2:
case CS35L41_IRQ1_RAW_STATUS3:
case CS35L41_IRQ1_RAW_STATUS4:
case CS35L41_IRQ1_FRC1:
case CS35L41_IRQ1_FRC2:
case CS35L41_IRQ1_FRC3:
case CS35L41_IRQ1_FRC4:
case CS35L41_IRQ1_EDGE1:
case CS35L41_IRQ1_EDGE4:
case CS35L41_IRQ1_POL1:
case CS35L41_IRQ1_POL2:
case CS35L41_IRQ1_POL3:
case CS35L41_IRQ1_POL4:
case CS35L41_IRQ1_DB3:
case CS35L41_IRQ2_STATUS:
case CS35L41_IRQ2_STATUS1:
case CS35L41_IRQ2_STATUS2:
case CS35L41_IRQ2_STATUS3:
case CS35L41_IRQ2_STATUS4:
case CS35L41_IRQ2_RAW_STATUS1:
case CS35L41_IRQ2_RAW_STATUS2:
case CS35L41_IRQ2_RAW_STATUS3:
case CS35L41_IRQ2_RAW_STATUS4:
case CS35L41_IRQ2_FRC1:
case CS35L41_IRQ2_FRC2:
case CS35L41_IRQ2_FRC3:
case CS35L41_IRQ2_FRC4:
case CS35L41_IRQ2_EDGE1:
case CS35L41_IRQ2_EDGE4:
case CS35L41_IRQ2_POL1:
case CS35L41_IRQ2_POL2:
case CS35L41_IRQ2_POL3:
case CS35L41_IRQ2_POL4:
case CS35L41_IRQ2_DB3:
case CS35L41_GPIO_STATUS1:
case CS35L41_OTP_TRIM_1:
case CS35L41_OTP_TRIM_2:
case CS35L41_OTP_TRIM_3:
case CS35L41_OTP_TRIM_4:
case CS35L41_OTP_TRIM_5:
case CS35L41_OTP_TRIM_6:
case CS35L41_OTP_TRIM_7:
case CS35L41_OTP_TRIM_8:
case CS35L41_OTP_TRIM_9:
case CS35L41_OTP_TRIM_10:
case CS35L41_OTP_TRIM_11:
case CS35L41_OTP_TRIM_12:
case CS35L41_OTP_TRIM_13:
case CS35L41_OTP_TRIM_14:
case CS35L41_OTP_TRIM_15:
case CS35L41_OTP_TRIM_16:
case CS35L41_OTP_TRIM_17:
case CS35L41_OTP_TRIM_18:
case CS35L41_OTP_TRIM_19:
case CS35L41_OTP_TRIM_20:
case CS35L41_OTP_TRIM_21:
case CS35L41_OTP_TRIM_22:
case CS35L41_OTP_TRIM_23:
case CS35L41_OTP_TRIM_24:
case CS35L41_OTP_TRIM_25:
case CS35L41_OTP_TRIM_26:
case CS35L41_OTP_TRIM_27:
case CS35L41_OTP_TRIM_28:
case CS35L41_OTP_TRIM_29:
case CS35L41_OTP_TRIM_30:
case CS35L41_OTP_TRIM_31:
case CS35L41_OTP_TRIM_32:
case CS35L41_OTP_TRIM_33:
case CS35L41_OTP_TRIM_34:
case CS35L41_OTP_TRIM_35:
case CS35L41_OTP_TRIM_36:
case CS35L41_DSP_MBOX_1 ... CS35L41_DSP_VIRT2_MBOX_8:
case CS35L41_DSP1_XMEM_PACK_0 ... CS35L41_DSP1_XMEM_PACK_3068:
case CS35L41_DSP1_XMEM_UNPACK32_0 ... CS35L41_DSP1_XMEM_UNPACK32_2046:
case CS35L41_DSP1_XMEM_UNPACK24_0 ... CS35L41_DSP1_XMEM_UNPACK24_4093:
case CS35L41_DSP1_YMEM_PACK_0 ... CS35L41_DSP1_YMEM_PACK_1532:
case CS35L41_DSP1_YMEM_UNPACK32_0 ... CS35L41_DSP1_YMEM_UNPACK32_1022:
case CS35L41_DSP1_YMEM_UNPACK24_0 ... CS35L41_DSP1_YMEM_UNPACK24_2045:
case CS35L41_DSP1_PMEM_0 ... CS35L41_DSP1_PMEM_5114:
case CS35L41_DSP1_CCM_CORE_CTRL ... CS35L41_DSP1_WDT_STATUS:
case CS35L41_OTP_MEM0 ... CS35L41_OTP_MEM31:
return true;
default:
return false;
}
}
static const struct cs35l41_otp_packed_element_t
otp_map_1[CS35L41_NUM_OTP_ELEM] = {
/* addr shift size */
{0x00002030, 0, 4}, /*TRIM_OSC_FREQ_TRIM*/
{0x00002030, 7, 1}, /*TRIM_OSC_TRIM_DONE*/
{0x0000208c, 24, 6}, /*TST_DIGREG_VREF_TRIM*/
{0x00002090, 14, 4}, /*TST_REF_TRIM*/
{0x00002090, 10, 4}, /*TST_REF_TEMPCO_TRIM*/
{0x0000300C, 11, 4}, /*PLL_LDOA_TST_VREF_TRIM*/
{0x0000394C, 23, 2}, /*BST_ATEST_CM_VOFF*/
{0x00003950, 0, 7}, /*BST_ATRIM_IADC_OFFSET*/
{0x00003950, 8, 7}, /*BST_ATRIM_IADC_GAIN1*/
{0x00003950, 16, 8}, /*BST_ATRIM_IPKCOMP_OFFSET1*/
{0x00003950, 24, 8}, /*BST_ATRIM_IPKCOMP_GAIN1*/
{0x00003954, 0, 7}, /*BST_ATRIM_IADC_OFFSET2*/
{0x00003954, 8, 7}, /*BST_ATRIM_IADC_GAIN2*/
{0x00003954, 16, 8}, /*BST_ATRIM_IPKCOMP_OFFSET2*/
{0x00003954, 24, 8}, /*BST_ATRIM_IPKCOMP_GAIN2*/
{0x00003958, 0, 7}, /*BST_ATRIM_IADC_OFFSET3*/
{0x00003958, 8, 7}, /*BST_ATRIM_IADC_GAIN3*/
{0x00003958, 16, 8}, /*BST_ATRIM_IPKCOMP_OFFSET3*/
{0x00003958, 24, 8}, /*BST_ATRIM_IPKCOMP_GAIN3*/
{0x0000395C, 0, 7}, /*BST_ATRIM_IADC_OFFSET4*/
{0x0000395C, 8, 7}, /*BST_ATRIM_IADC_GAIN4*/
{0x0000395C, 16, 8}, /*BST_ATRIM_IPKCOMP_OFFSET4*/
{0x0000395C, 24, 8}, /*BST_ATRIM_IPKCOMP_GAIN4*/
{0x0000416C, 0, 8}, /*VMON_GAIN_OTP_VAL*/
{0x00004160, 0, 7}, /*VMON_OFFSET_OTP_VAL*/
{0x0000416C, 8, 8}, /*IMON_GAIN_OTP_VAL*/
{0x00004160, 16, 10}, /*IMON_OFFSET_OTP_VAL*/
{0x0000416C, 16, 12}, /*VMON_CM_GAIN_OTP_VAL*/
{0x0000416C, 28, 1}, /*VMON_CM_GAIN_SIGN_OTP_VAL*/
{0x00004170, 0, 6}, /*IMON_CAL_TEMPCO_OTP_VAL*/
{0x00004170, 6, 1}, /*IMON_CAL_TEMPCO_SIGN_OTP*/
{0x00004170, 8, 6}, /*IMON_CAL_TEMPCO2_OTP_VAL*/
{0x00004170, 14, 1}, /*IMON_CAL_TEMPCO2_DN_UPB_OTP_VAL*/
{0x00004170, 16, 9}, /*IMON_CAL_TEMPCO_TBASE_OTP_VAL*/
{0x00004360, 0, 5}, /*TEMP_GAIN_OTP_VAL*/
{0x00004360, 6, 9}, /*TEMP_OFFSET_OTP_VAL*/
{0x00004448, 0, 8}, /*VP_SARADC_OFFSET*/
{0x00004448, 8, 8}, /*VP_GAIN_INDEX*/
{0x00004448, 16, 8}, /*VBST_SARADC_OFFSET*/
{0x00004448, 24, 8}, /*VBST_GAIN_INDEX*/
{0x0000444C, 0, 3}, /*ANA_SELINVREF*/
{0x00006E30, 0, 5}, /*GAIN_ERR_COEFF_0*/
{0x00006E30, 8, 5}, /*GAIN_ERR_COEFF_1*/
{0x00006E30, 16, 5}, /*GAIN_ERR_COEFF_2*/
{0x00006E30, 24, 5}, /*GAIN_ERR_COEFF_3*/
{0x00006E34, 0, 5}, /*GAIN_ERR_COEFF_4*/
{0x00006E34, 8, 5}, /*GAIN_ERR_COEFF_5*/
{0x00006E34, 16, 5}, /*GAIN_ERR_COEFF_6*/
{0x00006E34, 24, 5}, /*GAIN_ERR_COEFF_7*/
{0x00006E38, 0, 5}, /*GAIN_ERR_COEFF_8*/
{0x00006E38, 8, 5}, /*GAIN_ERR_COEFF_9*/
{0x00006E38, 16, 5}, /*GAIN_ERR_COEFF_10*/
{0x00006E38, 24, 5}, /*GAIN_ERR_COEFF_11*/
{0x00006E3C, 0, 5}, /*GAIN_ERR_COEFF_12*/
{0x00006E3C, 8, 5}, /*GAIN_ERR_COEFF_13*/
{0x00006E3C, 16, 5}, /*GAIN_ERR_COEFF_14*/
{0x00006E3C, 24, 5}, /*GAIN_ERR_COEFF_15*/
{0x00006E40, 0, 5}, /*GAIN_ERR_COEFF_16*/
{0x00006E40, 8, 5}, /*GAIN_ERR_COEFF_17*/
{0x00006E40, 16, 5}, /*GAIN_ERR_COEFF_18*/
{0x00006E40, 24, 5}, /*GAIN_ERR_COEFF_19*/
{0x00006E44, 0, 5}, /*GAIN_ERR_COEFF_20*/
{0x00006E48, 0, 10}, /*VOFF_GAIN_0*/
{0x00006E48, 10, 10}, /*VOFF_GAIN_1*/
{0x00006E48, 20, 10}, /*VOFF_GAIN_2*/
{0x00006E4C, 0, 10}, /*VOFF_GAIN_3*/
{0x00006E4C, 10, 10}, /*VOFF_GAIN_4*/
{0x00006E4C, 20, 10}, /*VOFF_GAIN_5*/
{0x00006E50, 0, 10}, /*VOFF_GAIN_6*/
{0x00006E50, 10, 10}, /*VOFF_GAIN_7*/
{0x00006E50, 20, 10}, /*VOFF_GAIN_8*/
{0x00006E54, 0, 10}, /*VOFF_GAIN_9*/
{0x00006E54, 10, 10}, /*VOFF_GAIN_10*/
{0x00006E54, 20, 10}, /*VOFF_GAIN_11*/
{0x00006E58, 0, 10}, /*VOFF_GAIN_12*/
{0x00006E58, 10, 10}, /*VOFF_GAIN_13*/
{0x00006E58, 20, 10}, /*VOFF_GAIN_14*/
{0x00006E5C, 0, 10}, /*VOFF_GAIN_15*/
{0x00006E5C, 10, 10}, /*VOFF_GAIN_16*/
{0x00006E5C, 20, 10}, /*VOFF_GAIN_17*/
{0x00006E60, 0, 10}, /*VOFF_GAIN_18*/
{0x00006E60, 10, 10}, /*VOFF_GAIN_19*/
{0x00006E60, 20, 10}, /*VOFF_GAIN_20*/
{0x00006E64, 0, 10}, /*VOFF_INT1*/
{0x00007418, 7, 5}, /*DS_SPK_INT1_CAP_TRIM*/
{0x0000741C, 0, 5}, /*DS_SPK_INT2_CAP_TRIM*/
{0x0000741C, 11, 4}, /*DS_SPK_LPF_CAP_TRIM*/
{0x0000741C, 19, 4}, /*DS_SPK_QUAN_CAP_TRIM*/
{0x00007434, 17, 1}, /*FORCE_CAL*/
{0x00007434, 18, 7}, /*CAL_OVERRIDE*/
{0x00007068, 0, 9}, /*MODIX*/
{0x0000410C, 7, 1}, /*VIMON_DLY_NOT_COMB*/
{0x0000400C, 0, 7}, /*VIMON_DLY*/
{0x00000000, 0, 1}, /*extra bit*/
{0x00017040, 0, 8}, /*X_COORDINATE*/
{0x00017040, 8, 8}, /*Y_COORDINATE*/
{0x00017040, 16, 8}, /*WAFER_ID*/
{0x00017040, 24, 8}, /*DVS*/
{0x00017044, 0, 24}, /*LOT_NUMBER*/
};
static const struct cs35l41_otp_packed_element_t
otp_map_2[CS35L41_NUM_OTP_ELEM] = {
/* addr shift size */
{0x00002030, 0, 4}, /*TRIM_OSC_FREQ_TRIM*/
{0x00002030, 7, 1}, /*TRIM_OSC_TRIM_DONE*/
{0x0000208c, 24, 6}, /*TST_DIGREG_VREF_TRIM*/
{0x00002090, 14, 4}, /*TST_REF_TRIM*/
{0x00002090, 10, 4}, /*TST_REF_TEMPCO_TRIM*/
{0x0000300C, 11, 4}, /*PLL_LDOA_TST_VREF_TRIM*/
{0x0000394C, 23, 2}, /*BST_ATEST_CM_VOFF*/
{0x00003950, 0, 7}, /*BST_ATRIM_IADC_OFFSET*/
{0x00003950, 8, 7}, /*BST_ATRIM_IADC_GAIN1*/
{0x00003950, 16, 8}, /*BST_ATRIM_IPKCOMP_OFFSET1*/
{0x00003950, 24, 8}, /*BST_ATRIM_IPKCOMP_GAIN1*/
{0x00003954, 0, 7}, /*BST_ATRIM_IADC_OFFSET2*/
{0x00003954, 8, 7}, /*BST_ATRIM_IADC_GAIN2*/
{0x00003954, 16, 8}, /*BST_ATRIM_IPKCOMP_OFFSET2*/
{0x00003954, 24, 8}, /*BST_ATRIM_IPKCOMP_GAIN2*/
{0x00003958, 0, 7}, /*BST_ATRIM_IADC_OFFSET3*/
{0x00003958, 8, 7}, /*BST_ATRIM_IADC_GAIN3*/
{0x00003958, 16, 8}, /*BST_ATRIM_IPKCOMP_OFFSET3*/
{0x00003958, 24, 8}, /*BST_ATRIM_IPKCOMP_GAIN3*/
{0x0000395C, 0, 7}, /*BST_ATRIM_IADC_OFFSET4*/
{0x0000395C, 8, 7}, /*BST_ATRIM_IADC_GAIN4*/
{0x0000395C, 16, 8}, /*BST_ATRIM_IPKCOMP_OFFSET4*/
{0x0000395C, 24, 8}, /*BST_ATRIM_IPKCOMP_GAIN4*/
{0x0000416C, 0, 8}, /*VMON_GAIN_OTP_VAL*/
{0x00004160, 0, 7}, /*VMON_OFFSET_OTP_VAL*/
{0x0000416C, 8, 8}, /*IMON_GAIN_OTP_VAL*/
{0x00004160, 16, 10}, /*IMON_OFFSET_OTP_VAL*/
{0x0000416C, 16, 12}, /*VMON_CM_GAIN_OTP_VAL*/
{0x0000416C, 28, 1}, /*VMON_CM_GAIN_SIGN_OTP_VAL*/
{0x00004170, 0, 6}, /*IMON_CAL_TEMPCO_OTP_VAL*/
{0x00004170, 6, 1}, /*IMON_CAL_TEMPCO_SIGN_OTP*/
{0x00004170, 8, 6}, /*IMON_CAL_TEMPCO2_OTP_VAL*/
{0x00004170, 14, 1}, /*IMON_CAL_TEMPCO2_DN_UPB_OTP_VAL*/
{0x00004170, 16, 9}, /*IMON_CAL_TEMPCO_TBASE_OTP_VAL*/
{0x00004360, 0, 5}, /*TEMP_GAIN_OTP_VAL*/
{0x00004360, 6, 9}, /*TEMP_OFFSET_OTP_VAL*/
{0x00004448, 0, 8}, /*VP_SARADC_OFFSET*/
{0x00004448, 8, 8}, /*VP_GAIN_INDEX*/
{0x00004448, 16, 8}, /*VBST_SARADC_OFFSET*/
{0x00004448, 24, 8}, /*VBST_GAIN_INDEX*/
{0x0000444C, 0, 3}, /*ANA_SELINVREF*/
{0x00006E30, 0, 5}, /*GAIN_ERR_COEFF_0*/
{0x00006E30, 8, 5}, /*GAIN_ERR_COEFF_1*/
{0x00006E30, 16, 5}, /*GAIN_ERR_COEFF_2*/
{0x00006E30, 24, 5}, /*GAIN_ERR_COEFF_3*/
{0x00006E34, 0, 5}, /*GAIN_ERR_COEFF_4*/
{0x00006E34, 8, 5}, /*GAIN_ERR_COEFF_5*/
{0x00006E34, 16, 5}, /*GAIN_ERR_COEFF_6*/
{0x00006E34, 24, 5}, /*GAIN_ERR_COEFF_7*/
{0x00006E38, 0, 5}, /*GAIN_ERR_COEFF_8*/
{0x00006E38, 8, 5}, /*GAIN_ERR_COEFF_9*/
{0x00006E38, 16, 5}, /*GAIN_ERR_COEFF_10*/
{0x00006E38, 24, 5}, /*GAIN_ERR_COEFF_11*/
{0x00006E3C, 0, 5}, /*GAIN_ERR_COEFF_12*/
{0x00006E3C, 8, 5}, /*GAIN_ERR_COEFF_13*/
{0x00006E3C, 16, 5}, /*GAIN_ERR_COEFF_14*/
{0x00006E3C, 24, 5}, /*GAIN_ERR_COEFF_15*/
{0x00006E40, 0, 5}, /*GAIN_ERR_COEFF_16*/
{0x00006E40, 8, 5}, /*GAIN_ERR_COEFF_17*/
{0x00006E40, 16, 5}, /*GAIN_ERR_COEFF_18*/
{0x00006E40, 24, 5}, /*GAIN_ERR_COEFF_19*/
{0x00006E44, 0, 5}, /*GAIN_ERR_COEFF_20*/
{0x00006E48, 0, 10}, /*VOFF_GAIN_0*/
{0x00006E48, 10, 10}, /*VOFF_GAIN_1*/
{0x00006E48, 20, 10}, /*VOFF_GAIN_2*/
{0x00006E4C, 0, 10}, /*VOFF_GAIN_3*/
{0x00006E4C, 10, 10}, /*VOFF_GAIN_4*/
{0x00006E4C, 20, 10}, /*VOFF_GAIN_5*/
{0x00006E50, 0, 10}, /*VOFF_GAIN_6*/
{0x00006E50, 10, 10}, /*VOFF_GAIN_7*/
{0x00006E50, 20, 10}, /*VOFF_GAIN_8*/
{0x00006E54, 0, 10}, /*VOFF_GAIN_9*/
{0x00006E54, 10, 10}, /*VOFF_GAIN_10*/
{0x00006E54, 20, 10}, /*VOFF_GAIN_11*/
{0x00006E58, 0, 10}, /*VOFF_GAIN_12*/
{0x00006E58, 10, 10}, /*VOFF_GAIN_13*/
{0x00006E58, 20, 10}, /*VOFF_GAIN_14*/
{0x00006E5C, 0, 10}, /*VOFF_GAIN_15*/
{0x00006E5C, 10, 10}, /*VOFF_GAIN_16*/
{0x00006E5C, 20, 10}, /*VOFF_GAIN_17*/
{0x00006E60, 0, 10}, /*VOFF_GAIN_18*/
{0x00006E60, 10, 10}, /*VOFF_GAIN_19*/
{0x00006E60, 20, 10}, /*VOFF_GAIN_20*/
{0x00006E64, 0, 10}, /*VOFF_INT1*/
{0x00007418, 7, 5}, /*DS_SPK_INT1_CAP_TRIM*/
{0x0000741C, 0, 5}, /*DS_SPK_INT2_CAP_TRIM*/
{0x0000741C, 11, 4}, /*DS_SPK_LPF_CAP_TRIM*/
{0x0000741C, 19, 4}, /*DS_SPK_QUAN_CAP_TRIM*/
{0x00007434, 17, 1}, /*FORCE_CAL*/
{0x00007434, 18, 7}, /*CAL_OVERRIDE*/
{0x00007068, 0, 9}, /*MODIX*/
{0x0000410C, 7, 1}, /*VIMON_DLY_NOT_COMB*/
{0x0000400C, 0, 7}, /*VIMON_DLY*/
{0x00004000, 11, 1}, /*VMON_POL*/
{0x00017040, 0, 8}, /*X_COORDINATE*/
{0x00017040, 8, 8}, /*Y_COORDINATE*/
{0x00017040, 16, 8}, /*WAFER_ID*/
{0x00017040, 24, 8}, /*DVS*/
{0x00017044, 0, 24}, /*LOT_NUMBER*/
};
const struct cs35l41_otp_map_element_t
cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS] = {
{
.id = 0x01,
.map = otp_map_1,
.num_elements = CS35L41_NUM_OTP_ELEM,
.bit_offset = 16,
.word_offset = 2,
},
{
.id = 0x02,
.map = otp_map_2,
.num_elements = CS35L41_NUM_OTP_ELEM,
.bit_offset = 16,
.word_offset = 2,
},
{
.id = 0x03,
.map = otp_map_2,
.num_elements = CS35L41_NUM_OTP_ELEM,
.bit_offset = 16,
.word_offset = 2,
},
{
.id = 0x06,
.map = otp_map_2,
.num_elements = CS35L41_NUM_OTP_ELEM,
.bit_offset = 16,
.word_offset = 2,
},
};

File diff suppressed because it is too large Load diff

View file

@ -1,766 +0,0 @@
/*
* cs35l41.h -- CS35L41 ALSA SoC audio driver
*
* Copyright 2018 Cirrus Logic, Inc.
*
* Author: Brian Austin <brian.austin@cirrus.com>
* David Rhodes <david.rhodes@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 __CS35L41_H__
#define __CS35L41_H__
#include <linux/regmap.h>
#define CS35L41_FIRSTREG 0x00000000
#define CS35L41_LASTREG 0x03804FE8
#define CS35L41_DEVID 0x00000000
#define CS35L41_REVID 0x00000004
#define CS35L41_FABID 0x00000008
#define CS35L41_RELID 0x0000000C
#define CS35L41_OTPID 0x00000010
#define CS35L41_SFT_RESET 0x00000020
#define CS35L41_TEST_KEY_CTL 0x00000040
#define CS35L41_USER_KEY_CTL 0x00000044
#define CS35L41_OTP_MEM0 0x00000400
#define CS35L41_OTP_MEM31 0x0000047C
#define CS35L41_OTP_CTRL0 0x00000500
#define CS35L41_OTP_CTRL1 0x00000504
#define CS35L41_OTP_CTRL3 0x00000508
#define CS35L41_OTP_CTRL4 0x0000050C
#define CS35L41_OTP_CTRL5 0x00000510
#define CS35L41_OTP_CTRL6 0x00000514
#define CS35L41_OTP_CTRL7 0x00000518
#define CS35L41_OTP_CTRL8 0x0000051C
#define CS35L41_PWR_CTRL1 0x00002014
#define CS35L41_PWR_CTRL2 0x00002018
#define CS35L41_PWR_CTRL3 0x0000201C
#define CS35L41_CTRL_OVRRIDE 0x00002020
#define CS35L41_AMP_OUT_MUTE 0x00002024
#define CS35L41_PROTECT_REL_ERR_IGN 0x00002034
#define CS35L41_GPIO_PAD_CONTROL 0x0000242C
#define CS35L41_JTAG_CONTROL 0x00002438
#define CS35L41_PLL_CLK_CTRL 0x00002C04
#define CS35L41_DSP_CLK_CTRL 0x00002C08
#define CS35L41_GLOBAL_CLK_CTRL 0x00002C0C
#define CS35L41_DATA_FS_SEL 0x00002C10
#define CS35L41_MDSYNC_EN 0x00003400
#define CS35L41_MDSYNC_TX_ID 0x00003408
#define CS35L41_MDSYNC_PWR_CTRL 0x0000340C
#define CS35L41_MDSYNC_DATA_TX 0x00003410
#define CS35L41_MDSYNC_TX_STATUS 0x00003414
#define CS35L41_MDSYNC_DATA_RX 0x0000341C
#define CS35L41_MDSYNC_RX_STATUS 0x00003420
#define CS35L41_MDSYNC_ERR_STATUS 0x00003424
#define CS35L41_MDSYNC_SYNC_PTE2 0x00003528
#define CS35L41_MDSYNC_SYNC_PTE3 0x0000352C
#define CS35L41_MDSYNC_SYNC_MSM_STATUS 0x0000353C
#define CS35L41_BSTCVRT_VCTRL1 0x00003800
#define CS35L41_BSTCVRT_VCTRL2 0x00003804
#define CS35L41_BSTCVRT_PEAK_CUR 0x00003808
#define CS35L41_BSTCVRT_SFT_RAMP 0x0000380C
#define CS35L41_BSTCVRT_COEFF 0x00003810
#define CS35L41_BSTCVRT_SLOPE_LBST 0x00003814
#define CS35L41_BSTCVRT_SW_FREQ 0x00003818
#define CS35L41_BSTCVRT_DCM_CTRL 0x0000381C
#define CS35L41_BSTCVRT_DCM_MODE_FORCE 0x00003820
#define CS35L41_BSTCVRT_OVERVOLT_CTRL 0x00003830
#define CS35L41_VI_VOL_POL 0x00004000
#define CS35L41_VIMON_SPKMON_RESYNC 0x00004100
#define CS35L41_DTEMP_WARN_THLD 0x00004220
#define CS35L41_DTEMP_CFG 0x00004224
#define CS35L41_DTEMP_EN 0x00004308
#define CS35L41_VPVBST_FS_SEL 0x00004400
#define CS35L41_SP_ENABLES 0x00004800
#define CS35L41_SP_RATE_CTRL 0x00004804
#define CS35L41_SP_FORMAT 0x00004808
#define CS35L41_SP_HIZ_CTRL 0x0000480C
#define CS35L41_SP_FRAME_TX_SLOT 0x00004810
#define CS35L41_SP_FRAME_RX_SLOT 0x00004820
#define CS35L41_SP_TX_WL 0x00004830
#define CS35L41_SP_RX_WL 0x00004840
#define CS35L41_ASP_CONTROL4 0x00004854
#define CS35L41_DAC_PCM1_SRC 0x00004C00
#define CS35L41_ASP_TX1_SRC 0x00004C20
#define CS35L41_ASP_TX2_SRC 0x00004C24
#define CS35L41_ASP_TX3_SRC 0x00004C28
#define CS35L41_ASP_TX4_SRC 0x00004C2C
#define CS35L41_DSP1_RX1_SRC 0x00004C40
#define CS35L41_DSP1_RX2_SRC 0x00004C44
#define CS35L41_DSP1_RX3_SRC 0x00004C48
#define CS35L41_DSP1_RX4_SRC 0x00004C4C
#define CS35L41_DSP1_RX5_SRC 0x00004C50
#define CS35L41_DSP1_RX6_SRC 0x00004C54
#define CS35L41_DSP1_RX7_SRC 0x00004C58
#define CS35L41_DSP1_RX8_SRC 0x00004C5C
#define CS35L41_NGATE1_SRC 0x00004C60
#define CS35L41_NGATE2_SRC 0x00004C64
#define CS35L41_AMP_DIG_VOL_CTRL 0x00006000
#define CS35L41_VPBR_CFG 0x00006404
#define CS35L41_VBBR_CFG 0x00006408
#define CS35L41_VPBR_STATUS 0x0000640C
#define CS35L41_VBBR_STATUS 0x00006410
#define CS35L41_OVERTEMP_CFG 0x00006414
#define CS35L41_AMP_ERR_VOL 0x00006418
#define CS35L41_VOL_STATUS_TO_DSP 0x00006450
#define CS35L41_CLASSH_CFG 0x00006800
#define CS35L41_WKFET_CFG 0x00006804
#define CS35L41_NG_CFG 0x00006808
#define CS35L41_AMP_GAIN_CTRL 0x00006C04
#define CS35L41_DAC_MSM_CFG 0x00007400
#define CS35L41_IRQ1_CFG 0x00010000
#define CS35L41_IRQ1_STATUS 0x00010004
#define CS35L41_IRQ1_STATUS1 0x00010010
#define CS35L41_IRQ1_STATUS2 0x00010014
#define CS35L41_IRQ1_STATUS3 0x00010018
#define CS35L41_IRQ1_STATUS4 0x0001001C
#define CS35L41_IRQ1_RAW_STATUS1 0x00010090
#define CS35L41_IRQ1_RAW_STATUS2 0x00010094
#define CS35L41_IRQ1_RAW_STATUS3 0x00010098
#define CS35L41_IRQ1_RAW_STATUS4 0x0001009C
#define CS35L41_IRQ1_MASK1 0x00010110
#define CS35L41_IRQ1_MASK2 0x00010114
#define CS35L41_IRQ1_MASK3 0x00010118
#define CS35L41_IRQ1_MASK4 0x0001011C
#define CS35L41_IRQ1_FRC1 0x00010190
#define CS35L41_IRQ1_FRC2 0x00010194
#define CS35L41_IRQ1_FRC3 0x00010198
#define CS35L41_IRQ1_FRC4 0x0001019C
#define CS35L41_IRQ1_EDGE1 0x00010210
#define CS35L41_IRQ1_EDGE4 0x0001021C
#define CS35L41_IRQ1_POL1 0x00010290
#define CS35L41_IRQ1_POL2 0x00010294
#define CS35L41_IRQ1_POL3 0x00010298
#define CS35L41_IRQ1_POL4 0x0001029C
#define CS35L41_IRQ1_DB3 0x00010318
#define CS35L41_IRQ2_CFG 0x00010800
#define CS35L41_IRQ2_STATUS 0x00010804
#define CS35L41_IRQ2_STATUS1 0x00010810
#define CS35L41_IRQ2_STATUS2 0x00010814
#define CS35L41_IRQ2_STATUS3 0x00010818
#define CS35L41_IRQ2_STATUS4 0x0001081C
#define CS35L41_IRQ2_RAW_STATUS1 0x00010890
#define CS35L41_IRQ2_RAW_STATUS2 0x00010894
#define CS35L41_IRQ2_RAW_STATUS3 0x00010898
#define CS35L41_IRQ2_RAW_STATUS4 0x0001089C
#define CS35L41_IRQ2_MASK1 0x00010910
#define CS35L41_IRQ2_MASK2 0x00010914
#define CS35L41_IRQ2_MASK3 0x00010918
#define CS35L41_IRQ2_MASK4 0x0001091C
#define CS35L41_IRQ2_FRC1 0x00010990
#define CS35L41_IRQ2_FRC2 0x00010994
#define CS35L41_IRQ2_FRC3 0x00010998
#define CS35L41_IRQ2_FRC4 0x0001099C
#define CS35L41_IRQ2_EDGE1 0x00010A10
#define CS35L41_IRQ2_EDGE4 0x00010A1C
#define CS35L41_IRQ2_POL1 0x00010A90
#define CS35L41_IRQ2_POL2 0x00010A94
#define CS35L41_IRQ2_POL3 0x00010A98
#define CS35L41_IRQ2_POL4 0x00010A9C
#define CS35L41_IRQ2_DB3 0x00010B18
#define CS35L41_GPIO_STATUS1 0x00011000
#define CS35L41_GPIO1_CTRL1 0x00011008
#define CS35L41_GPIO2_CTRL1 0x0001100C
#define CS35L41_MIXER_NGATE_CFG 0x00012000
#define CS35L41_MIXER_NGATE_CH1_CFG 0x00012004
#define CS35L41_MIXER_NGATE_CH2_CFG 0x00012008
#define CS35L41_DSP_MBOX_1 0x00013000
#define CS35L41_DSP_MBOX_2 0x00013004
#define CS35L41_DSP_MBOX_3 0x00013008
#define CS35L41_DSP_MBOX_4 0x0001300C
#define CS35L41_DSP_MBOX_5 0x00013010
#define CS35L41_DSP_MBOX_6 0x00013014
#define CS35L41_DSP_MBOX_7 0x00013018
#define CS35L41_DSP_MBOX_8 0x0001301C
#define CS35L41_DSP_VIRT1_MBOX_1 0x00013020
#define CS35L41_DSP_VIRT1_MBOX_2 0x00013024
#define CS35L41_DSP_VIRT1_MBOX_3 0x00013028
#define CS35L41_DSP_VIRT1_MBOX_4 0x0001302C
#define CS35L41_DSP_VIRT1_MBOX_5 0x00013030
#define CS35L41_DSP_VIRT1_MBOX_6 0x00013034
#define CS35L41_DSP_VIRT1_MBOX_7 0x00013038
#define CS35L41_DSP_VIRT1_MBOX_8 0x0001303C
#define CS35L41_DSP_VIRT2_MBOX_1 0x00013040
#define CS35L41_DSP_VIRT2_MBOX_2 0x00013044
#define CS35L41_DSP_VIRT2_MBOX_3 0x00013048
#define CS35L41_DSP_VIRT2_MBOX_4 0x0001304C
#define CS35L41_DSP_VIRT2_MBOX_5 0x00013050
#define CS35L41_DSP_VIRT2_MBOX_6 0x00013054
#define CS35L41_DSP_VIRT2_MBOX_7 0x00013058
#define CS35L41_DSP_VIRT2_MBOX_8 0x0001305C
#define CS35L41_CLOCK_DETECT_1 0x00014000
#define CS35L41_TIMER1_CONTROL 0x00015000
#define CS35L41_TIMER1_COUNT_PRESET 0x00015004
#define CS35L41_TIMER1_START_STOP 0x0001500C
#define CS35L41_TIMER1_STATUS 0x00015010
#define CS35L41_TIMER1_COUNT_READBACK 0x00015014
#define CS35L41_TIMER1_DSP_CLK_CFG 0x00015018
#define CS35L41_TIMER1_DSP_CLK_STATUS 0x0001501C
#define CS35L41_TIMER2_CONTROL 0x00015100
#define CS35L41_TIMER2_COUNT_PRESET 0x00015104
#define CS35L41_TIMER2_START_STOP 0x0001510C
#define CS35L41_TIMER2_STATUS 0x00015110
#define CS35L41_TIMER2_COUNT_READBACK 0x00015114
#define CS35L41_TIMER2_DSP_CLK_CFG 0x00015118
#define CS35L41_TIMER2_DSP_CLK_STATUS 0x0001511C
#define CS35L41_DFT_JTAG_CONTROL 0x00016000
#define CS35L41_DIE_STS1 0x00017040
#define CS35L41_DIE_STS2 0x00017044
#define CS35L41_TEMP_CAL1 0x00017048
#define CS35L41_TEMP_CAL2 0x0001704C
#define CS35L41_DSP1_XMEM_PACK_0 0x02000000
#define CS35L41_DSP1_XMEM_PACK_3068 0x02002FF0
#define CS35L41_DSP1_XMEM_UNPACK32_0 0x02400000
#define CS35L41_DSP1_XMEM_UNPACK32_2046 0x02401FF8
#define CS35L41_DSP1_TIMESTAMP_COUNT 0x025C0800
#define CS35L41_DSP1_SYS_ID 0x025E0000
#define CS35L41_DSP1_SYS_VERSION 0x025E0004
#define CS35L41_DSP1_SYS_CORE_ID 0x025E0008
#define CS35L41_DSP1_SYS_AHB_ADDR 0x025E000C
#define CS35L41_DSP1_SYS_XSRAM_SIZE 0x025E0010
#define CS35L41_DSP1_SYS_YSRAM_SIZE 0x025E0018
#define CS35L41_DSP1_SYS_PSRAM_SIZE 0x025E0020
#define CS35L41_DSP1_SYS_PM_BOOT_SIZE 0x025E0028
#define CS35L41_DSP1_SYS_FEATURES 0x025E002C
#define CS35L41_DSP1_SYS_FIR_FILTERS 0x025E0030
#define CS35L41_DSP1_SYS_LMS_FILTERS 0x025E0034
#define CS35L41_DSP1_SYS_XM_BANK_SIZE 0x025E0038
#define CS35L41_DSP1_SYS_YM_BANK_SIZE 0x025E003C
#define CS35L41_DSP1_SYS_PM_BANK_SIZE 0x025E0040
#define CS35L41_DSP1_AHBM_WIN0_CTRL0 0x025E2000
#define CS35L41_DSP1_AHBM_WIN0_CTRL1 0x025E2004
#define CS35L41_DSP1_AHBM_WIN1_CTRL0 0x025E2008
#define CS35L41_DSP1_AHBM_WIN1_CTRL1 0x025E200C
#define CS35L41_DSP1_AHBM_WIN2_CTRL0 0x025E2010
#define CS35L41_DSP1_AHBM_WIN2_CTRL1 0x025E2014
#define CS35L41_DSP1_AHBM_WIN3_CTRL0 0x025E2018
#define CS35L41_DSP1_AHBM_WIN3_CTRL1 0x025E201C
#define CS35L41_DSP1_AHBM_WIN4_CTRL0 0x025E2020
#define CS35L41_DSP1_AHBM_WIN4_CTRL1 0x025E2024
#define CS35L41_DSP1_AHBM_WIN5_CTRL0 0x025E2028
#define CS35L41_DSP1_AHBM_WIN5_CTRL1 0x025E202C
#define CS35L41_DSP1_AHBM_WIN6_CTRL0 0x025E2030
#define CS35L41_DSP1_AHBM_WIN6_CTRL1 0x025E2034
#define CS35L41_DSP1_AHBM_WIN7_CTRL0 0x025E2038
#define CS35L41_DSP1_AHBM_WIN7_CTRL1 0x025E203C
#define CS35L41_DSP1_AHBM_WIN_DBG_CTRL0 0x025E2040
#define CS35L41_DSP1_AHBM_WIN_DBG_CTRL1 0x025E2044
#define CS35L41_DSP1_XMEM_UNPACK24_0 0x02800000
#define CS35L41_DSP1_XMEM_UNPACK24_4093 0x02803FF4
#define CS35L41_DSP1_CTRL_BASE 0x02B80000
#define CS35L41_DSP1_CORE_SOFT_RESET 0x02B80010
#define CS35L41_DSP1_DEBUG 0x02B80040
#define CS35L41_DSP1_TIMER_CTRL 0x02B80048
#define CS35L41_DSP1_STREAM_ARB_CTRL 0x02B80050
#define CS35L41_DSP1_RX1_RATE 0x02B80080
#define CS35L41_DSP1_RX2_RATE 0x02B80088
#define CS35L41_DSP1_RX3_RATE 0x02B80090
#define CS35L41_DSP1_RX4_RATE 0x02B80098
#define CS35L41_DSP1_RX5_RATE 0x02B800A0
#define CS35L41_DSP1_RX6_RATE 0x02B800A8
#define CS35L41_DSP1_RX7_RATE 0x02B800B0
#define CS35L41_DSP1_RX8_RATE 0x02B800B8
#define CS35L41_DSP1_TX1_RATE 0x02B80280
#define CS35L41_DSP1_TX2_RATE 0x02B80288
#define CS35L41_DSP1_TX3_RATE 0x02B80290
#define CS35L41_DSP1_TX4_RATE 0x02B80298
#define CS35L41_DSP1_TX5_RATE 0x02B802A0
#define CS35L41_DSP1_TX6_RATE 0x02B802A8
#define CS35L41_DSP1_TX7_RATE 0x02B802B0
#define CS35L41_DSP1_TX8_RATE 0x02B802B8
#define CS35L41_DSP1_NMI_CTRL1 0x02B80480
#define CS35L41_DSP1_NMI_CTRL2 0x02B80488
#define CS35L41_DSP1_NMI_CTRL3 0x02B80490
#define CS35L41_DSP1_NMI_CTRL4 0x02B80498
#define CS35L41_DSP1_NMI_CTRL5 0x02B804A0
#define CS35L41_DSP1_NMI_CTRL6 0x02B804A8
#define CS35L41_DSP1_NMI_CTRL7 0x02B804B0
#define CS35L41_DSP1_NMI_CTRL8 0x02B804B8
#define CS35L41_DSP1_RESUME_CTRL 0x02B80500
#define CS35L41_DSP1_IRQ1_CTRL 0x02B80508
#define CS35L41_DSP1_IRQ2_CTRL 0x02B80510
#define CS35L41_DSP1_IRQ3_CTRL 0x02B80518
#define CS35L41_DSP1_IRQ4_CTRL 0x02B80520
#define CS35L41_DSP1_IRQ5_CTRL 0x02B80528
#define CS35L41_DSP1_IRQ6_CTRL 0x02B80530
#define CS35L41_DSP1_IRQ7_CTRL 0x02B80538
#define CS35L41_DSP1_IRQ8_CTRL 0x02B80540
#define CS35L41_DSP1_IRQ9_CTRL 0x02B80548
#define CS35L41_DSP1_IRQ10_CTRL 0x02B80550
#define CS35L41_DSP1_IRQ11_CTRL 0x02B80558
#define CS35L41_DSP1_IRQ12_CTRL 0x02B80560
#define CS35L41_DSP1_IRQ13_CTRL 0x02B80568
#define CS35L41_DSP1_IRQ14_CTRL 0x02B80570
#define CS35L41_DSP1_IRQ15_CTRL 0x02B80578
#define CS35L41_DSP1_IRQ16_CTRL 0x02B80580
#define CS35L41_DSP1_IRQ17_CTRL 0x02B80588
#define CS35L41_DSP1_IRQ18_CTRL 0x02B80590
#define CS35L41_DSP1_IRQ19_CTRL 0x02B80598
#define CS35L41_DSP1_IRQ20_CTRL 0x02B805A0
#define CS35L41_DSP1_IRQ21_CTRL 0x02B805A8
#define CS35L41_DSP1_IRQ22_CTRL 0x02B805B0
#define CS35L41_DSP1_IRQ23_CTRL 0x02B805B8
#define CS35L41_DSP1_SCRATCH1 0x02B805C0
#define CS35L41_DSP1_SCRATCH2 0x02B805C8
#define CS35L41_DSP1_SCRATCH3 0x02B805D0
#define CS35L41_DSP1_SCRATCH4 0x02B805D8
#define CS35L41_DSP1_CCM_CORE_CTRL 0x02BC1000
#define CS35L41_DSP1_CCM_CLK_OVERRIDE 0x02BC1008
#define CS35L41_DSP1_XM_MSTR_EN 0x02BC2000
#define CS35L41_DSP1_XM_CORE_PRI 0x02BC2008
#define CS35L41_DSP1_XM_AHB_PACK_PL_PRI 0x02BC2010
#define CS35L41_DSP1_XM_AHB_UP_PL_PRI 0x02BC2018
#define CS35L41_DSP1_XM_ACCEL_PL0_PRI 0x02BC2020
#define CS35L41_DSP1_XM_NPL0_PRI 0x02BC2078
#define CS35L41_DSP1_YM_MSTR_EN 0x02BC20C0
#define CS35L41_DSP1_YM_CORE_PRI 0x02BC20C8
#define CS35L41_DSP1_YM_AHB_PACK_PL_PRI 0x02BC20D0
#define CS35L41_DSP1_YM_AHB_UP_PL_PRI 0x02BC20D8
#define CS35L41_DSP1_YM_ACCEL_PL0_PRI 0x02BC20E0
#define CS35L41_DSP1_YM_NPL0_PRI 0x02BC2138
#define CS35L41_DSP1_PM_MSTR_EN 0x02BC2180
#define CS35L41_DSP1_PM_PATCH0_ADDR 0x02BC2188
#define CS35L41_DSP1_PM_PATCH0_EN 0x02BC218C
#define CS35L41_DSP1_PM_PATCH0_DATA_LO 0x02BC2190
#define CS35L41_DSP1_PM_PATCH0_DATA_HI 0x02BC2194
#define CS35L41_DSP1_PM_PATCH1_ADDR 0x02BC2198
#define CS35L41_DSP1_PM_PATCH1_EN 0x02BC219C
#define CS35L41_DSP1_PM_PATCH1_DATA_LO 0x02BC21A0
#define CS35L41_DSP1_PM_PATCH1_DATA_HI 0x02BC21A4
#define CS35L41_DSP1_PM_PATCH2_ADDR 0x02BC21A8
#define CS35L41_DSP1_PM_PATCH2_EN 0x02BC21AC
#define CS35L41_DSP1_PM_PATCH2_DATA_LO 0x02BC21B0
#define CS35L41_DSP1_PM_PATCH2_DATA_HI 0x02BC21B4
#define CS35L41_DSP1_PM_PATCH3_ADDR 0x02BC21B8
#define CS35L41_DSP1_PM_PATCH3_EN 0x02BC21BC
#define CS35L41_DSP1_PM_PATCH3_DATA_LO 0x02BC21C0
#define CS35L41_DSP1_PM_PATCH3_DATA_HI 0x02BC21C4
#define CS35L41_DSP1_PM_PATCH4_ADDR 0x02BC21C8
#define CS35L41_DSP1_PM_PATCH4_EN 0x02BC21CC
#define CS35L41_DSP1_PM_PATCH4_DATA_LO 0x02BC21D0
#define CS35L41_DSP1_PM_PATCH4_DATA_HI 0x02BC21D4
#define CS35L41_DSP1_PM_PATCH5_ADDR 0x02BC21D8
#define CS35L41_DSP1_PM_PATCH5_EN 0x02BC21DC
#define CS35L41_DSP1_PM_PATCH5_DATA_LO 0x02BC21E0
#define CS35L41_DSP1_PM_PATCH5_DATA_HI 0x02BC21E4
#define CS35L41_DSP1_PM_PATCH6_ADDR 0x02BC21E8
#define CS35L41_DSP1_PM_PATCH6_EN 0x02BC21EC
#define CS35L41_DSP1_PM_PATCH6_DATA_LO 0x02BC21F0
#define CS35L41_DSP1_PM_PATCH6_DATA_HI 0x02BC21F4
#define CS35L41_DSP1_PM_PATCH7_ADDR 0x02BC21F8
#define CS35L41_DSP1_PM_PATCH7_EN 0x02BC21FC
#define CS35L41_DSP1_PM_PATCH7_DATA_LO 0x02BC2200
#define CS35L41_DSP1_PM_PATCH7_DATA_HI 0x02BC2204
#define CS35L41_DSP1_MPU_XM_ACCESS0 0x02BC3000
#define CS35L41_DSP1_MPU_YM_ACCESS0 0x02BC3004
#define CS35L41_DSP1_MPU_WNDW_ACCESS0 0x02BC3008
#define CS35L41_DSP1_MPU_XREG_ACCESS0 0x02BC300C
#define CS35L41_DSP1_MPU_YREG_ACCESS0 0x02BC3014
#define CS35L41_DSP1_MPU_XM_ACCESS1 0x02BC3018
#define CS35L41_DSP1_MPU_YM_ACCESS1 0x02BC301C
#define CS35L41_DSP1_MPU_WNDW_ACCESS1 0x02BC3020
#define CS35L41_DSP1_MPU_XREG_ACCESS1 0x02BC3024
#define CS35L41_DSP1_MPU_YREG_ACCESS1 0x02BC302C
#define CS35L41_DSP1_MPU_XM_ACCESS2 0x02BC3030
#define CS35L41_DSP1_MPU_YM_ACCESS2 0x02BC3034
#define CS35L41_DSP1_MPU_WNDW_ACCESS2 0x02BC3038
#define CS35L41_DSP1_MPU_XREG_ACCESS2 0x02BC303C
#define CS35L41_DSP1_MPU_YREG_ACCESS2 0x02BC3044
#define CS35L41_DSP1_MPU_XM_ACCESS3 0x02BC3048
#define CS35L41_DSP1_MPU_YM_ACCESS3 0x02BC304C
#define CS35L41_DSP1_MPU_WNDW_ACCESS3 0x02BC3050
#define CS35L41_DSP1_MPU_XREG_ACCESS3 0x02BC3054
#define CS35L41_DSP1_MPU_YREG_ACCESS3 0x02BC305C
#define CS35L41_DSP1_MPU_XM_VIO_ADDR 0x02BC3100
#define CS35L41_DSP1_MPU_XM_VIO_STATUS 0x02BC3104
#define CS35L41_DSP1_MPU_YM_VIO_ADDR 0x02BC3108
#define CS35L41_DSP1_MPU_YM_VIO_STATUS 0x02BC310C
#define CS35L41_DSP1_MPU_PM_VIO_ADDR 0x02BC3110
#define CS35L41_DSP1_MPU_PM_VIO_STATUS 0x02BC3114
#define CS35L41_DSP1_MPU_LOCK_CONFIG 0x02BC3140
#define CS35L41_DSP1_MPU_WDT_RST_CTRL 0x02BC3180
#define CS35L41_DSP1_STRMARB_MSTR0_CFG0 0x02BC5000
#define CS35L41_DSP1_STRMARB_MSTR0_CFG1 0x02BC5004
#define CS35L41_DSP1_STRMARB_MSTR0_CFG2 0x02BC5008
#define CS35L41_DSP1_STRMARB_MSTR1_CFG0 0x02BC5010
#define CS35L41_DSP1_STRMARB_MSTR1_CFG1 0x02BC5014
#define CS35L41_DSP1_STRMARB_MSTR1_CFG2 0x02BC5018
#define CS35L41_DSP1_STRMARB_MSTR2_CFG0 0x02BC5020
#define CS35L41_DSP1_STRMARB_MSTR2_CFG1 0x02BC5024
#define CS35L41_DSP1_STRMARB_MSTR2_CFG2 0x02BC5028
#define CS35L41_DSP1_STRMARB_MSTR3_CFG0 0x02BC5030
#define CS35L41_DSP1_STRMARB_MSTR3_CFG1 0x02BC5034
#define CS35L41_DSP1_STRMARB_MSTR3_CFG2 0x02BC5038
#define CS35L41_DSP1_STRMARB_MSTR4_CFG0 0x02BC5040
#define CS35L41_DSP1_STRMARB_MSTR4_CFG1 0x02BC5044
#define CS35L41_DSP1_STRMARB_MSTR4_CFG2 0x02BC5048
#define CS35L41_DSP1_STRMARB_MSTR5_CFG0 0x02BC5050
#define CS35L41_DSP1_STRMARB_MSTR5_CFG1 0x02BC5054
#define CS35L41_DSP1_STRMARB_MSTR5_CFG2 0x02BC5058
#define CS35L41_DSP1_STRMARB_MSTR6_CFG0 0x02BC5060
#define CS35L41_DSP1_STRMARB_MSTR6_CFG1 0x02BC5064
#define CS35L41_DSP1_STRMARB_MSTR6_CFG2 0x02BC5068
#define CS35L41_DSP1_STRMARB_MSTR7_CFG0 0x02BC5070
#define CS35L41_DSP1_STRMARB_MSTR7_CFG1 0x02BC5074
#define CS35L41_DSP1_STRMARB_MSTR7_CFG2 0x02BC5078
#define CS35L41_DSP1_STRMARB_TX0_CFG0 0x02BC5200
#define CS35L41_DSP1_STRMARB_TX0_CFG1 0x02BC5204
#define CS35L41_DSP1_STRMARB_TX1_CFG0 0x02BC5208
#define CS35L41_DSP1_STRMARB_TX1_CFG1 0x02BC520C
#define CS35L41_DSP1_STRMARB_TX2_CFG0 0x02BC5210
#define CS35L41_DSP1_STRMARB_TX2_CFG1 0x02BC5214
#define CS35L41_DSP1_STRMARB_TX3_CFG0 0x02BC5218
#define CS35L41_DSP1_STRMARB_TX3_CFG1 0x02BC521C
#define CS35L41_DSP1_STRMARB_TX4_CFG0 0x02BC5220
#define CS35L41_DSP1_STRMARB_TX4_CFG1 0x02BC5224
#define CS35L41_DSP1_STRMARB_TX5_CFG0 0x02BC5228
#define CS35L41_DSP1_STRMARB_TX5_CFG1 0x02BC522C
#define CS35L41_DSP1_STRMARB_TX6_CFG0 0x02BC5230
#define CS35L41_DSP1_STRMARB_TX6_CFG1 0x02BC5234
#define CS35L41_DSP1_STRMARB_TX7_CFG0 0x02BC5238
#define CS35L41_DSP1_STRMARB_TX7_CFG1 0x02BC523C
#define CS35L41_DSP1_STRMARB_RX0_CFG0 0x02BC5400
#define CS35L41_DSP1_STRMARB_RX0_CFG1 0x02BC5404
#define CS35L41_DSP1_STRMARB_RX1_CFG0 0x02BC5408
#define CS35L41_DSP1_STRMARB_RX1_CFG1 0x02BC540C
#define CS35L41_DSP1_STRMARB_RX2_CFG0 0x02BC5410
#define CS35L41_DSP1_STRMARB_RX2_CFG1 0x02BC5414
#define CS35L41_DSP1_STRMARB_RX3_CFG0 0x02BC5418
#define CS35L41_DSP1_STRMARB_RX3_CFG1 0x02BC541C
#define CS35L41_DSP1_STRMARB_RX4_CFG0 0x02BC5420
#define CS35L41_DSP1_STRMARB_RX4_CFG1 0x02BC5424
#define CS35L41_DSP1_STRMARB_RX5_CFG0 0x02BC5428
#define CS35L41_DSP1_STRMARB_RX5_CFG1 0x02BC542C
#define CS35L41_DSP1_STRMARB_RX6_CFG0 0x02BC5430
#define CS35L41_DSP1_STRMARB_RX6_CFG1 0x02BC5434
#define CS35L41_DSP1_STRMARB_RX7_CFG0 0x02BC5438
#define CS35L41_DSP1_STRMARB_RX7_CFG1 0x02BC543C
#define CS35L41_DSP1_STRMARB_IRQ0_CFG0 0x02BC5600
#define CS35L41_DSP1_STRMARB_IRQ0_CFG1 0x02BC5604
#define CS35L41_DSP1_STRMARB_IRQ0_CFG2 0x02BC5608
#define CS35L41_DSP1_STRMARB_IRQ1_CFG0 0x02BC5610
#define CS35L41_DSP1_STRMARB_IRQ1_CFG1 0x02BC5614
#define CS35L41_DSP1_STRMARB_IRQ1_CFG2 0x02BC5618
#define CS35L41_DSP1_STRMARB_IRQ2_CFG0 0x02BC5620
#define CS35L41_DSP1_STRMARB_IRQ2_CFG1 0x02BC5624
#define CS35L41_DSP1_STRMARB_IRQ2_CFG2 0x02BC5628
#define CS35L41_DSP1_STRMARB_IRQ3_CFG0 0x02BC5630
#define CS35L41_DSP1_STRMARB_IRQ3_CFG1 0x02BC5634
#define CS35L41_DSP1_STRMARB_IRQ3_CFG2 0x02BC5638
#define CS35L41_DSP1_STRMARB_IRQ4_CFG0 0x02BC5640
#define CS35L41_DSP1_STRMARB_IRQ4_CFG1 0x02BC5644
#define CS35L41_DSP1_STRMARB_IRQ4_CFG2 0x02BC5648
#define CS35L41_DSP1_STRMARB_IRQ5_CFG0 0x02BC5650
#define CS35L41_DSP1_STRMARB_IRQ5_CFG1 0x02BC5654
#define CS35L41_DSP1_STRMARB_IRQ5_CFG2 0x02BC5658
#define CS35L41_DSP1_STRMARB_IRQ6_CFG0 0x02BC5660
#define CS35L41_DSP1_STRMARB_IRQ6_CFG1 0x02BC5664
#define CS35L41_DSP1_STRMARB_IRQ6_CFG2 0x02BC5668
#define CS35L41_DSP1_STRMARB_IRQ7_CFG0 0x02BC5670
#define CS35L41_DSP1_STRMARB_IRQ7_CFG1 0x02BC5674
#define CS35L41_DSP1_STRMARB_IRQ7_CFG2 0x02BC5678
#define CS35L41_DSP1_STRMARB_RESYNC_MSK 0x02BC5A00
#define CS35L41_DSP1_STRMARB_ERR_STATUS 0x02BC5A08
#define CS35L41_DSP1_INTPCTL_RES_STATIC 0x02BC6000
#define CS35L41_DSP1_INTPCTL_RES_DYN 0x02BC6004
#define CS35L41_DSP1_INTPCTL_NMI_CTRL 0x02BC6008
#define CS35L41_DSP1_INTPCTL_IRQ_INV 0x02BC6010
#define CS35L41_DSP1_INTPCTL_IRQ_MODE 0x02BC6014
#define CS35L41_DSP1_INTPCTL_IRQ_EN 0x02BC6018
#define CS35L41_DSP1_INTPCTL_IRQ_MSK 0x02BC601C
#define CS35L41_DSP1_INTPCTL_IRQ_FLUSH 0x02BC6020
#define CS35L41_DSP1_INTPCTL_IRQ_MSKCLR 0x02BC6024
#define CS35L41_DSP1_INTPCTL_IRQ_FRC 0x02BC6028
#define CS35L41_DSP1_INTPCTL_IRQ_MSKSET 0x02BC602C
#define CS35L41_DSP1_INTPCTL_IRQ_ERR 0x02BC6030
#define CS35L41_DSP1_INTPCTL_IRQ_PEND 0x02BC6034
#define CS35L41_DSP1_INTPCTL_IRQ_GEN 0x02BC6038
#define CS35L41_DSP1_INTPCTL_TESTBITS 0x02BC6040
#define CS35L41_DSP1_WDT_CONTROL 0x02BC7000
#define CS35L41_DSP1_WDT_STATUS 0x02BC7008
#define CS35L41_DSP1_YMEM_PACK_0 0x02C00000
#define CS35L41_DSP1_YMEM_PACK_1532 0x02C017F0
#define CS35L41_DSP1_YMEM_UNPACK32_0 0x03000000
#define CS35L41_DSP1_YMEM_UNPACK32_1022 0x03000FF8
#define CS35L41_DSP1_YMEM_UNPACK24_0 0x03400000
#define CS35L41_DSP1_YMEM_UNPACK24_2045 0x03401FF4
#define CS35L41_DSP1_PMEM_0 0x03800000
#define CS35L41_DSP1_PMEM_5114 0x03804FE8
/*test regs for emulation bringup*/
#define CS35L41_PLL_OVR 0x00003018
#define CS35L41_BST_TEST_DUTY 0x00003900
#define CS35L41_DIGPWM_IOCTRL 0x0000706C
/*registers populated by OTP*/
#define CS35L41_OTP_TRIM_1 0x0000208c
#define CS35L41_OTP_TRIM_2 0x00002090
#define CS35L41_OTP_TRIM_3 0x00003010
#define CS35L41_OTP_TRIM_4 0x0000300C
#define CS35L41_OTP_TRIM_5 0x0000394C
#define CS35L41_OTP_TRIM_6 0x00003950
#define CS35L41_OTP_TRIM_7 0x00003954
#define CS35L41_OTP_TRIM_8 0x00003958
#define CS35L41_OTP_TRIM_9 0x0000395C
#define CS35L41_OTP_TRIM_10 0x0000416C
#define CS35L41_OTP_TRIM_11 0x00004160
#define CS35L41_OTP_TRIM_12 0x00004170
#define CS35L41_OTP_TRIM_13 0x00004360
#define CS35L41_OTP_TRIM_14 0x00004448
#define CS35L41_OTP_TRIM_15 0x0000444C
#define CS35L41_OTP_TRIM_16 0x00006E30
#define CS35L41_OTP_TRIM_17 0x00006E34
#define CS35L41_OTP_TRIM_18 0x00006E38
#define CS35L41_OTP_TRIM_19 0x00006E3C
#define CS35L41_OTP_TRIM_20 0x00006E40
#define CS35L41_OTP_TRIM_21 0x00006E44
#define CS35L41_OTP_TRIM_22 0x00006E48
#define CS35L41_OTP_TRIM_23 0x00006E4C
#define CS35L41_OTP_TRIM_24 0x00006E50
#define CS35L41_OTP_TRIM_25 0x00006E54
#define CS35L41_OTP_TRIM_26 0x00006E58
#define CS35L41_OTP_TRIM_27 0x00006E5C
#define CS35L41_OTP_TRIM_28 0x00006E60
#define CS35L41_OTP_TRIM_29 0x00006E64
#define CS35L41_OTP_TRIM_30 0x00007418
#define CS35L41_OTP_TRIM_31 0x0000741C
#define CS35L41_OTP_TRIM_32 0x00007434
#define CS35L41_OTP_TRIM_33 0x00007068
#define CS35L41_OTP_TRIM_34 0x0000410C
#define CS35L41_OTP_TRIM_35 0x0000400C
#define CS35L41_OTP_TRIM_36 0x00002030
#define CS35L41_MAX_CACHE_REG 0x0000006B
#define CS35L41_OTP_SIZE_WORDS 32
#define CS35L41_NUM_OTP_ELEM 100
#define CS35L41_NUM_OTP_MAPS 4
#define CS35L41_VALID_PDATA 0x80000000
#define CS35L41_SCLK_MSTR_MASK 0x10
#define CS35L41_SCLK_MSTR_SHIFT 4
#define CS35L41_LRCLK_MSTR_MASK 0x01
#define CS35L41_LRCLK_MSTR_SHIFT 0
#define CS35L41_SCLK_INV_MASK 0x40
#define CS35L41_SCLK_INV_SHIFT 6
#define CS35L41_LRCLK_INV_MASK 0x04
#define CS35L41_LRCLK_INV_SHIFT 2
#define CS35L41_SCLK_FRC_MASK 0x20
#define CS35L41_SCLK_FRC_SHIFT 5
#define CS35L41_LRCLK_FRC_MASK 0x02
#define CS35L41_LRCLK_FRC_SHIFT 1
#define CS35L41_AMP_GAIN_ZC_MASK 0x0400
#define CS35L41_AMP_GAIN_ZC_SHIFT 10
#define CS35L41_BST_CTL_MASK 0xFF
#define CS35L41_BST_CTL_SEL_MASK 0x03
#define CS35L41_BST_CTL_SEL_REG 0x00
#define CS35L41_BST_CTL_SEL_CLASSH 0x01
#define CS35L41_BST_IPK_MASK 0x7F
#define CS35L41_BST_IPK_SHIFT 0
#define CS35L41_BST_LIM_MASK 0x4
#define CS35L41_BST_LIM_SHIFT 2
#define CS35L41_BST_K1_MASK 0x000000FF
#define CS35L41_BST_K1_SHIFT 0
#define CS35L41_BST_K2_MASK 0x0000FF00
#define CS35L41_BST_K2_SHIFT 8
#define CS35L41_BST_SLOPE_MASK 0x0000FF00
#define CS35L41_BST_SLOPE_SHIFT 8
#define CS35L41_BST_LBST_VAL_MASK 0x00000003
#define CS35L41_BST_LBST_VAL_SHIFT 0
#define CS35L41_TEMP_THLD_MASK 0x03
#define CS35L41_VMON_IMON_VOL_MASK 0x07FF07FF
#define CS35L41_PDM_MODE_MASK 0x01
#define CS35L41_PDM_MODE_SHIFT 0
#define CS35L41_CH_MEM_DEPTH_MASK 0x07
#define CS35L41_CH_MEM_DEPTH_SHIFT 0
#define CS35L41_CH_HDRM_CTL_MASK 0x007F0000
#define CS35L41_CH_HDRM_CTL_SHIFT 16
#define CS35L41_CH_REL_RATE_MASK 0xFF00
#define CS35L41_CH_REL_RATE_SHIFT 8
#define CS35L41_CH_WKFET_DLY_MASK 0x001C
#define CS35L41_CH_WKFET_DLY_SHIFT 2
#define CS35L41_CH_WKFET_THLD_MASK 0x0F00
#define CS35L41_CH_WKFET_THLD_SHIFT 8
#define CS35L41_NG_ENABLE_MASK 0x00010000
#define CS35L41_NG_ENABLE_SHIFT 16
#define CS35L41_NG_THLD_MASK 0x7
#define CS35L41_NG_THLD_SHIFT 0
#define CS35L41_NG_DELAY_MASK 0x0F00
#define CS35L41_NG_DELAY_SHIFT 8
#define CS35L41_ASP_FMT_MASK 0x0700
#define CS35L41_ASP_FMT_SHIFT 8
#define CS35L41_ASP_DOUT_HIZ_MASK 0x03
#define CS35L41_ASP_DOUT_HIZ_SHIFT 0
#define CS35L41_ASP_WIDTH_16 0x10
#define CS35L41_ASP_WIDTH_24 0x18
#define CS35L41_ASP_WIDTH_32 0x20
#define CS35L41_ASP_WIDTH_TX_MASK 0xFF0000
#define CS35L41_ASP_WIDTH_TX_SHIFT 16
#define CS35L41_ASP_WIDTH_RX_MASK 0xFF000000
#define CS35L41_ASP_WIDTH_RX_SHIFT 24
#define CS35L41_ASP_RX1_SLOT_MASK 0x3F
#define CS35L41_ASP_RX1_SLOT_SHIFT 0
#define CS35L41_ASP_RX2_SLOT_MASK 0x3F00
#define CS35L41_ASP_RX2_SLOT_SHIFT 8
#define CS35L41_ASP_RX_WL_MASK 0x3F
#define CS35L41_ASP_TX_WL_MASK 0x3F
#define CS35L41_ASP_RX_WL_SHIFT 0
#define CS35L41_ASP_TX_WL_SHIFT 0
#define CS35L41_ASP_SOURCE_MASK 0x7F
#define CS35L41_INPUT_SRC_ASPRX1 0x08
#define CS35L41_INPUT_SRC_ASPRX2 0x09
#define CS35L41_INPUT_SRC_VMON 0x18
#define CS35L41_INPUT_SRC_IMON 0x19
#define CS35L41_INPUT_SRC_CLASSH 0x21
#define CS35L41_INPUT_SRC_VPMON 0x28
#define CS35L41_INPUT_SRC_VBSTMON 0x29
#define CS35L41_INPUT_SRC_TEMPMON 0x3A
#define CS35L41_INPUT_SRC_RSVD 0x3B
#define CS35L41_INPUT_DSP_TX1 0x32
#define CS35L41_INPUT_DSP_TX2 0x33
#define CS35L41_PLL_CLK_SEL_MASK 0x07
#define CS35L41_PLL_CLK_SEL_SHIFT 0
#define CS35L41_PLL_CLK_EN_MASK 0x10
#define CS35L41_PLL_CLK_EN_SHIFT 4
#define CS35L41_PLL_OPENLOOP_MASK 0x0800
#define CS35L41_PLL_OPENLOOP_SHIFT 11
#define CS35L41_PLLSRC_SCLK 0
#define CS35L41_PLLSRC_LRCLK 1
#define CS35L41_PLLSRC_SELF 3
#define CS35L41_PLLSRC_PDMCLK 4
#define CS35L41_PLLSRC_MCLK 5
#define CS35L41_PLLSRC_SWIRE 7
#define CS35L41_REFCLK_FREQ_MASK 0x7E0
#define CS35L41_REFCLK_FREQ_SHIFT 5
#define CS35L41_GLOBAL_FS_MASK 0x1F
#define CS35L41_GLOBAL_FS_SHIFT 0
#define CS35L41_GLOBAL_EN_MASK 0x01
#define CS35L41_GLOBAL_EN_SHIFT 0
#define CS35L41_BST_EN_MASK 0x0030
#define CS35L41_BST_EN_SHIFT 4
#define CS35L41_BST_EN_DEFAULT 0x2
#define CS35L41_BST_EN_BYPASS 1
#define CS35L41_AMP_MUTE_MASK 0x10
#define CS35L41_PDN_DONE_MASK 0x00800000
#define CS35L41_PDN_DONE_SHIFT 23
#define CS35L41_PUP_DONE_MASK 0x01000000
#define CS35L41_PUP_DONE_SHIFT 24
#define CS35L36_PUP_DONE_IRQ_UNMASK 0x5F
#define CS35L36_PUP_DONE_IRQ_MASK 0xBF
#define CS35L41_AMP_SHORT_ERR 0x80000000
#define CS35L41_BST_SHORT_ERR 0x0100
#define CS35L41_TEMP_WARN 0x8000
#define CS35L41_TEMP_ERR 0x00020000
#define CS35L41_BST_OVP_ERR 0x40
#define CS35L41_BST_DCM_UVP_ERR 0x80
#define CS35L41_OTP_BOOT_DONE 0x02
#define CS35L41_PLL_UNLOCK 0x10
#define CS35L41_OTP_BOOT_ERR 0x80000000
#define CS35L41_AMP_SHORT_ERR_RLS 0x02
#define CS35L41_BST_SHORT_ERR_RLS 0x04
#define CS35L41_BST_OVP_ERR_RLS 0x08
#define CS35L41_BST_UVP_ERR_RLS 0x10
#define CS35L41_TEMP_WARN_ERR_RLS 0x20
#define CS35L41_TEMP_ERR_RLS 0x40
#define CS35L41_INT1_MASK_DEFAULT 0x7FFCFE3F
#define CS35L41_INT1_UNMASK_PUP 0xFEFFFFFF
#define CS35L41_INT1_UNMASK_PDN 0xFF7FFFFF
#define CS35L41_GPIO_DIR_MASK 0x80000000
#define CS35L41_GPIO1_CTRL_MASK 0x00030000
#define CS35L41_GPIO1_CTRL_SHIFT 16
#define CS35L41_GPIO2_CTRL_MASK 0x07000000
#define CS35L41_GPIO2_CTRL_SHIFT 24
#define CS35L41_GPIO_CTRL_ACTV_LO 4
#define CS35L41_GPIO_CTRL_ACTV_HI 5
#define CS35L41_GPIO_POL_MASK 0x1000
#define CS35L41_GPIO_POL_SHIFT 12
#define CS35L41_CHIP_ID 0x35a40
#define CS35L41R_CHIP_ID 0x35b40
#define CS35L41_MTLREVID_MASK 0x0F
#define CS35L41_REVID_A0 0xA0
#define CS35L41_REVID_B0 0xB0
#define CS35L41_DSP_N_RX_RATES 8
#define CS35L41_DSP_N_TX_RATES 8
#define CS35L41_HALO_CORE_RESET 0x00000200
#define CS35L41_SPI_MAX_FREQ_OTP 4000000
#define CS35L41_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
#define CS35L41_TX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE \
| SNDRV_PCM_FMTBIT_S32_LE)
bool cs35l41_readable_reg(struct device *dev, unsigned int reg);
bool cs35l41_precious_reg(struct device *dev, unsigned int reg);
bool cs35l41_volatile_reg(struct device *dev, unsigned int reg);
struct cs35l41_otp_packed_element_t {
u32 reg;
u8 shift;
u8 size;
};
struct cs35l41_otp_map_element_t {
u32 id;
u32 num_elements;
const struct cs35l41_otp_packed_element_t *map;
u32 bit_offset;
u32 word_offset;
};
extern const struct reg_default cs35l41_reg[CS35L41_MAX_CACHE_REG];
extern const struct cs35l41_otp_map_element_t
cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS];
#define CS35L41_REGSTRIDE 4
#define CS35L41_DSP_VIRT1_MBOX_SHIFT 20
#define CS35L41_DSP_VIRT2_MBOX_SHIFT 21
#define CS35L41_CSPL_MBOX_STS CS35L41_DSP_MBOX_2
/* Firmware update following reg */
#define CS35L41_CSPL_MBOX_CMD_FW CS35L41_DSP_VIRT2_MBOX_1
#define CS35L41_CSPL_MBOX_CMD_FW_SHIFT CS35L41_DSP_VIRT2_MBOX_SHIFT
/* Driver update following reg */
#define CS35L41_CSPL_MBOX_CMD_DRV CS35L41_DSP_VIRT1_MBOX_1
#define CS35L41_CSPL_MBOX_CMD_DRV_SHIFT CS35L41_DSP_VIRT1_MBOX_SHIFT
enum cs35l41_cspl_mboxstate {
CSPL_MBOX_STS_RUNNING = 0,
CSPL_MBOX_STS_PAUSED = 1,
CSPL_MBOX_STS_RDY_FOR_REINIT = 2,
};
enum cs35l41_cspl_mboxcmd {
CSPL_MBOX_CMD_NONE = 0,
CSPL_MBOX_CMD_PAUSE = 1,
CSPL_MBOX_CMD_RESUME = 2,
CSPL_MBOX_CMD_REINIT = 3,
CSPL_MBOX_CMD_STOP_PRE_REINIT = 4,
CSPL_MBOX_CMD_UNKNOWN_CMD = -1,
CSPL_MBOX_CMD_INVALID_SEQUENCE = -2,
};
#endif /*__CS35L41_H__*/

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,534 +0,0 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/mfd/madera/core.h>
#include <linux/mfd/madera/registers.h>
#include <linux/mfd/madera/pdata.h>
#include "madera-slimbus.h"
#include "madera.h"
/* As there is no sane way to recover an entry point to the slimbus core
* from anything other than a slim_device probe, simply use this as a bridge
* between ASoC and the slimbus core to get our slimbus generic device
* associated with our ASoC specific slimbus code
*/
static struct slim_device *stashed_slim_dev;
static struct mutex slim_tx_lock;
static struct mutex slim_rx_lock;
static int madera_slim_get_la(struct slim_device *slim, u8 *la)
{
int ret;
const unsigned long timeout = jiffies + msecs_to_jiffies(100);
if (slim == NULL)
return -EINVAL;
do {
ret = slim_get_logical_addr(slim, slim->e_addr, 6, la);
if (!ret)
break;
/* Give SLIMBUS time to report present and be ready. */
usleep_range(1000, 1100);
dev_info(&slim->dev, "retrying get logical addr\n");
} while time_before(jiffies, timeout);
dev_info(&slim->dev, "LA %d\n", *la);
return 0;
}
static void madera_slim_fixup_prop(struct slim_ch *prop,
u32 samplerate, u32 sampleszbits)
{
prop->prot = SLIM_AUTO_ISO;
prop->baser = SLIM_RATE_4000HZ;
prop->dataf = SLIM_CH_DATAF_NOT_DEFINED;
prop->auxf = SLIM_CH_AUXF_NOT_APPLICABLE;
prop->ratem = samplerate / 4000;
prop->sampleszbits = sampleszbits;
}
#define TX_STREAM_1 128
#define TX_STREAM_2 132
#define TX_STREAM_3 134
#define RX_STREAM_1 144
#define RX_STREAM_2 146
#define RX_STREAM_3 148
static u32 rx_porth1[2], rx_porth2[2], rx_porth3[2];
static u32 tx_porth1[4], tx_porth2[2], tx_porth3[1];
static u16 rx_handles1[] = { RX_STREAM_1, RX_STREAM_1 + 1 };
static u16 rx_handles2[] = { RX_STREAM_2, RX_STREAM_2 + 1 };
static u16 rx_handles3[] = { RX_STREAM_3, RX_STREAM_3 + 1 };
static u16 tx_handles1[] = { TX_STREAM_1, TX_STREAM_1 + 1,
TX_STREAM_1 + 2, TX_STREAM_1 + 3 };
static u16 tx_handles2[] = { TX_STREAM_2, TX_STREAM_2 + 1 };
static u16 tx_handles3[] = { TX_STREAM_3 };
static u16 rx_group1, rx_group2, rx_group3;
static u16 tx_group1, tx_group2, tx_group3;
int madera_slim_tx_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct madera_priv *priv = snd_soc_codec_get_drvdata(codec);
struct madera *madera = priv->madera;
struct slim_ch prop;
int ret = 0, i;
u32 *porth;
u16 *handles, *group;
int chcnt;
if (stashed_slim_dev == NULL) {
dev_err(madera->dev, "slim device undefined.\n");
return -EINVAL;
}
mutex_lock(&slim_tx_lock);
switch (w->shift) {
case MADERA_SLIMTX1_ENA_SHIFT:
dev_dbg(madera->dev, "TX1\n");
chcnt = priv->tx_chan_map_num[0];
if (chcnt > ARRAY_SIZE(tx_porth1)) {
dev_err(madera->dev, "ERROR: Too many TX channels\n");
ret = -EINVAL;
goto exit;
}
porth = tx_porth1;
handles = tx_handles1;
group = &tx_group1;
break;
case MADERA_SLIMTX5_ENA_SHIFT:
dev_dbg(madera->dev, "TX2\n");
chcnt = priv->tx_chan_map_num[1];
if (chcnt > ARRAY_SIZE(tx_porth2)) {
dev_err(madera->dev, "ERROR: Too many TX channels\n");
ret = -EINVAL;
goto exit;
}
porth = tx_porth2;
handles = tx_handles2;
group = &tx_group2;
break;
case MADERA_SLIMTX4_ENA_SHIFT:
dev_dbg(codec->dev, "TX3\n");
chcnt = priv->tx_chan_map_num[2];
if (chcnt > ARRAY_SIZE(tx_porth3)) {
dev_err(madera->dev, "ERROR: Too many TX channels\n");
ret = -EINVAL;
goto exit;
}
porth = tx_porth3;
handles = tx_handles3;
group = &tx_group3;
break;
default:
goto exit;
}
madera_slim_fixup_prop(&prop, 48000, 16);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
case SND_SOC_DAPM_POST_PMU:
dev_dbg(madera->dev, "Start slimbus TX\n");
ret = slim_define_ch(stashed_slim_dev, &prop,
handles, chcnt, true, group);
if (ret != 0) {
dev_err(madera->dev, "slim_define_ch() failed: %d\n",
ret);
goto exit;
}
for (i = 0; i < chcnt; i++) {
ret = slim_connect_src(stashed_slim_dev,
porth[i], handles[i]);
if (ret != 0) {
dev_err(madera->dev, "src connect fail %d:%d\n",
i, ret);
goto exit;
}
}
ret = slim_control_ch(stashed_slim_dev, *group,
SLIM_CH_ACTIVATE, true);
if (ret != 0) {
dev_err(madera->dev, "Failed to activate: %d\n", ret);
goto exit;
}
break;
case SND_SOC_DAPM_POST_PMD:
case SND_SOC_DAPM_PRE_PMD:
dev_dbg(madera->dev, "Stop slimbus Tx\n");
ret = slim_control_ch(stashed_slim_dev, *group,
SLIM_CH_REMOVE, true);
if (ret != 0)
dev_err(madera->dev, "Failed to remove tx: %d\n", ret);
break;
default:
break;
}
exit:
mutex_unlock(&slim_tx_lock);
return ret;
}
EXPORT_SYMBOL_GPL(madera_slim_tx_ev);
int madera_slim_rx_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct madera_priv *priv = snd_soc_codec_get_drvdata(codec);
struct madera *madera = priv->madera;
struct slim_ch prop;
int ret = 0, i;
u32 *porth;
u16 *handles, *group;
int chcnt;
u32 rx_sampleszbits = 16, rx_samplerate = 48000;
if (stashed_slim_dev == NULL) {
dev_err(madera->dev, "slim device undefined.\n");
return -EINVAL;
}
mutex_lock(&slim_rx_lock);
switch (w->shift) {
case MADERA_SLIMRX1_ENA_SHIFT:
dev_dbg(madera->dev, "RX1\n");
chcnt = priv->rx_chan_map_num[0];
if (chcnt > ARRAY_SIZE(rx_porth1)) {
dev_err(madera->dev, "ERROR: Too many RX channels\n");
ret = -EINVAL;
goto exit;
}
porth = rx_porth1;
handles = rx_handles1;
group = &rx_group1;
rx_sampleszbits = priv->rx1_sampleszbits;
rx_samplerate = priv->rx1_samplerate;
break;
case MADERA_SLIMRX5_ENA_SHIFT:
dev_dbg(madera->dev, "RX2\n");
chcnt = priv->rx_chan_map_num[1];
if (chcnt > ARRAY_SIZE(rx_porth2)) {
dev_err(madera->dev, "ERROR: Too many RX channels\n");
ret = -EINVAL;
goto exit;
}
porth = rx_porth2;
handles = rx_handles2;
group = &rx_group2;
rx_sampleszbits = priv->rx2_sampleszbits;
rx_samplerate = priv->rx2_samplerate;
break;
case MADERA_SLIMRX3_ENA_SHIFT:
dev_dbg(codec->dev, "RX3\n");
chcnt = priv->rx_chan_map_num[2];
if (chcnt > ARRAY_SIZE(rx_porth3)) {
dev_err(madera->dev, "ERROR: Too many RX channels\n");
ret = -EINVAL;
goto exit;
}
porth = rx_porth3;
handles = rx_handles3;
group = &rx_group3;
break;
default:
goto exit;
}
madera_slim_fixup_prop(&prop, rx_samplerate, rx_sampleszbits);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
case SND_SOC_DAPM_POST_PMU:
dev_dbg(madera->dev, "Start slimbus RX, rate=%d, bit=%d\n",
rx_samplerate, rx_sampleszbits);
ret = slim_define_ch(stashed_slim_dev, &prop,
handles, chcnt, true, group);
if (ret != 0) {
dev_err(madera->dev, "slim_define_ch() failed: %d\n",
ret);
return ret;
}
for (i = 0; i < chcnt; i++) {
ret = slim_connect_sink(stashed_slim_dev, &porth[i], 1,
handles[i]);
if (ret != 0) {
dev_err(madera->dev, "snk connect fail %d:%d\n",
i, ret);
goto exit;
}
}
ret = slim_control_ch(stashed_slim_dev, *group,
SLIM_CH_ACTIVATE, true);
if (ret != 0) {
dev_err(madera->dev, "Failed to activate: %d\n", ret);
goto exit;
}
break;
case SND_SOC_DAPM_POST_PMD:
case SND_SOC_DAPM_PRE_PMD:
dev_dbg(madera->dev, "Stop slimbus Rx\n");
ret = slim_control_ch(stashed_slim_dev, *group,
SLIM_CH_REMOVE, true);
if (ret != 0)
dev_err(madera->dev, "Failed to remove rx: %d\n", ret);
break;
default:
break;
}
exit:
mutex_unlock(&slim_rx_lock);
return ret;
}
EXPORT_SYMBOL_GPL(madera_slim_rx_ev);
int madera_set_channel_map(struct snd_soc_dai *dai,
unsigned int tx_num, unsigned int *tx_slot,
unsigned int rx_num, unsigned int *rx_slot)
{
struct madera_priv *priv = snd_soc_codec_get_drvdata(dai->codec);
struct madera *madera = priv->madera;
u8 laddr;
int i, ret;
u32 *tx_porth, *rx_porth;
u16 *tx_handles, *rx_handles;
int tx_chcnt, rx_chcnt, tx_idx_step, rx_idx_step;
int tx_stream_idx, rx_stream_idx;
int *tx_priv_counter, *rx_priv_counter;
u16 *tx_chan_map_slot, *rx_chan_map_slot;
if (stashed_slim_dev == NULL) {
dev_err(madera->dev, "%s No slim device available\n",
__func__);
return -EINVAL;
}
/*
* same reason with stashed_slim_dev, there is no clever way to link
* codec and slimbus driver on madera based platform. whenever codec
* calls slimbus driver, it will keep its client codec pointer and use
* it as a bridge to call codec related functions.
*/
if (dai->codec != NULL)
slim_set_clientdata(stashed_slim_dev, dai->codec);
if (!priv->slim_logic_addr) {
madera_slim_get_la(stashed_slim_dev, &laddr);
priv->slim_logic_addr = laddr;
} else {
laddr = priv->slim_logic_addr;
}
switch (dai->id) {
case 4: /* cs47l35-slim1 */
tx_porth = tx_porth1;
tx_handles = tx_handles1;
tx_chcnt = ARRAY_SIZE(tx_porth1);
tx_idx_step = 8;
tx_stream_idx = TX_STREAM_1;
tx_priv_counter = &priv->tx_chan_map_num[0];
tx_chan_map_slot = priv->tx_chan_map_slot[0];
rx_porth = rx_porth1;
rx_handles = rx_handles1;
rx_chcnt = ARRAY_SIZE(rx_porth1);
rx_idx_step = 0;
rx_stream_idx = RX_STREAM_1;
rx_priv_counter = &priv->rx_chan_map_num[0];
rx_chan_map_slot = priv->rx_chan_map_slot[0];
break;
case 5: /* cs47l35-slim2 */
tx_porth = tx_porth2;
tx_handles = tx_handles2;
tx_chcnt = ARRAY_SIZE(tx_porth2);
tx_idx_step = 12;
tx_stream_idx = TX_STREAM_2;
tx_priv_counter = &priv->tx_chan_map_num[1];
tx_chan_map_slot = priv->tx_chan_map_slot[1];
rx_porth = rx_porth2;
rx_handles = rx_handles2;
rx_chcnt = ARRAY_SIZE(rx_porth2);
rx_idx_step = 4;
rx_stream_idx = RX_STREAM_2;
rx_priv_counter = &priv->rx_chan_map_num[1];
rx_chan_map_slot = priv->rx_chan_map_slot[1];
break;
default:
dev_err(madera->dev, "set_channel_map unknown dai->id %d\n",
dai->id);
return -EINVAL;
}
if (rx_num > rx_chcnt)
rx_num = rx_chcnt;
if (rx_num > 0)
*rx_priv_counter = rx_num;
if (tx_num > tx_chcnt)
tx_num = tx_chcnt;
if (tx_num > 0)
*tx_priv_counter = tx_num;
/* This actually allocates the channel or refcounts it if there... */
for (i = 0; i < rx_num; i++) {
slim_get_slaveport(laddr, i + rx_idx_step, &rx_porth[i],
SLIM_SINK);
ret = slim_query_ch(stashed_slim_dev, rx_stream_idx + i,
&rx_handles[i]);
if (ret != 0) {
dev_err(madera->dev, "slim_alloc_ch() failed: %d\n",
ret);
return ret;
}
rx_chan_map_slot[i] = rx_slot[i] = rx_stream_idx + i;
}
for (i = 0; i < tx_num; i++) {
slim_get_slaveport(laddr, i + tx_idx_step, &tx_porth[i],
SLIM_SRC);
ret = slim_query_ch(stashed_slim_dev, tx_stream_idx + i,
&tx_handles[i]);
if (ret != 0) {
dev_err(madera->dev, "slim_alloc_ch() failed: %d\n",
ret);
return ret;
}
tx_chan_map_slot[i] = tx_slot[i] = tx_stream_idx + i;
}
return 0;
}
EXPORT_SYMBOL_GPL(madera_set_channel_map);
int madera_get_channel_map(struct snd_soc_dai *dai,
unsigned int *tx_num, unsigned int *tx_slot,
unsigned int *rx_num, unsigned int *rx_slot)
{
struct madera_priv *priv = snd_soc_codec_get_drvdata(dai->codec);
struct madera *madera = priv->madera;
int i;
int tx_chan_map_num, rx_chan_map_num;
u16 *tx_chan_map_slot, *rx_chan_map_slot;
switch (dai->id) {
case 4: /* cs47l35-slim1 */
tx_chan_map_num = priv->tx_chan_map_num[0];
rx_chan_map_num = priv->rx_chan_map_num[0];
tx_chan_map_slot = priv->tx_chan_map_slot[0];
rx_chan_map_slot = priv->rx_chan_map_slot[0];
break;
case 5: /* cs47l35-slim2 */
tx_chan_map_num = priv->tx_chan_map_num[1];
rx_chan_map_num = priv->rx_chan_map_num[1];
tx_chan_map_slot = priv->tx_chan_map_slot[1];
rx_chan_map_slot = priv->rx_chan_map_slot[1];
break;
default:
dev_err(madera->dev, "get_channel_map unknown dai->id %d\n",
dai->id);
return -EINVAL;
}
if (!rx_chan_map_num || !tx_chan_map_num)
return -EINVAL;
*rx_num = rx_chan_map_num;
*tx_num = tx_chan_map_num;
for (i = 0; i < rx_chan_map_num; i++)
rx_slot[i] = rx_chan_map_slot[i];
for (i = 0; i < tx_chan_map_num; i++)
tx_slot[i] = tx_chan_map_slot[i];
return 0;
}
EXPORT_SYMBOL_GPL(madera_get_channel_map);
static const struct slim_device_id madera_slim_id[] = {
{ "madera-slim-audio", 0 },
{ },
};
static int madera_slim_audio_probe(struct slim_device *slim)
{
stashed_slim_dev = slim;
dev_info(&slim->dev, "%s SLIM PROBE\n", __func__);
mutex_init(&slim_tx_lock);
mutex_init(&slim_rx_lock);
return 0;
}
static int madera_slim_device_reset(struct slim_device *slim)
{
struct snd_soc_codec *codec;
if (slim == NULL)
return -EINVAL;
codec = slim_get_devicedata(slim);
if (codec != NULL) {
dev_info(&slim->dev, "%s handle SLIM RESET\n", __func__);
snd_soc_card_change_online_state(codec->component.card, 1);
}
return 0;
}
static int madera_slim_device_down(struct slim_device *slim)
{
struct snd_soc_codec *codec;
if (slim == NULL)
return -EINVAL;
codec = slim_get_devicedata(slim);
if (codec != NULL) {
dev_info(&slim->dev, "%s handle SLIM DOWN\n", __func__);
snd_soc_card_change_online_state(codec->component.card, 0);
}
return 0;
}
static struct slim_driver madera_slim_audio = {
.driver = {
.name = "madera-slim-audio",
.owner = THIS_MODULE,
},
.probe = madera_slim_audio_probe,
.id_table = madera_slim_id,
.reset_device = madera_slim_device_reset,
.device_down = madera_slim_device_down,
};
static int __init madera_slim_audio_init(void)
{
return slim_driver_register(&madera_slim_audio);
}
module_init(madera_slim_audio_init);
static void __exit madera_slim_audio_exit(void)
{
slim_driver_unregister(&madera_slim_audio);
}
module_exit(madera_slim_audio_exit);

View file

@ -1,57 +0,0 @@
#ifndef MADERA_SLIMBUS_H
#define MADERA_SLIMBUS_H
#include <sound/soc.h>
#define MADERA_SLIMBUS_MAX_CHANNELS 8
#define CONFIG_SND_SOC_MADERA_SLIMBUS 1
#ifdef CONFIG_SND_SOC_MADERA_SLIMBUS
#include <linux/slimbus/slimbus.h>
int madera_slim_tx_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event);
int madera_slim_rx_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event);
int madera_set_channel_map(struct snd_soc_dai *dai,
unsigned int tx_num, unsigned int *tx_slot,
unsigned int rx_num, unsigned int *rx_slot);
int madera_get_channel_map(struct snd_soc_dai *dai,
unsigned int *tx_num, unsigned int *tx_slot,
unsigned int *rx_num, unsigned int *rx_slot);
#else
static inline int madera_slim_tx_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event, int dai_id)
{
return 0;
}
static inline int madera_slim_rx_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event, int dai_id)
{
return 0;
}
static inline int madera_set_channel_map(struct snd_soc_dai *dai,
unsigned int tx_num,
unsigned int *tx_slot,
unsigned int rx_num,
unsigned int *rx_slot)
{
return 0;
}
static inline int madera_get_channel_map(struct snd_soc_dai *dai,
unsigned int *tx_num,
unsigned int *tx_slot,
unsigned int *rx_num,
unsigned int *rx_slot)
{
return 0;
}
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,544 +0,0 @@
/*
* madera.h - Cirrus Logic Madera class codecs common support
*
* Copyright 2015-2016 Cirrus Logic
*
* 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 _ASOC_MADERA_H
#define _ASOC_MADERA_H
#include <linux/completion.h>
#include <sound/soc.h>
#include <sound/madera-pdata.h>
#include "wm_adsp.h"
#include "madera-slimbus.h"
#define MADERA_FLL1_REFCLK 1
#define MADERA_FLL2_REFCLK 2
#define MADERA_FLL3_REFCLK 3
#define MADERA_FLLAO_REFCLK 4
#define MADERA_FLL1_SYNCCLK 5
#define MADERA_FLL2_SYNCCLK 6
#define MADERA_FLL3_SYNCCLK 7
#define MADERA_FLLAO_SYNCCLK 8
#define MADERA_FLL_SRC_NONE -1
#define MADERA_FLL_SRC_MCLK1 0
#define MADERA_FLL_SRC_MCLK2 1
#define MADERA_FLL_SRC_SLIMCLK 3
#define MADERA_FLL_SRC_FLL1 4
#define MADERA_FLL_SRC_FLL2 5
#define MADERA_FLL_SRC_AIF1BCLK 8
#define MADERA_FLL_SRC_AIF2BCLK 9
#define MADERA_FLL_SRC_AIF3BCLK 10
#define MADERA_FLL_SRC_AIF4BCLK 11
#define MADERA_FLL_SRC_AIF1LRCLK 12
#define MADERA_FLL_SRC_AIF2LRCLK 13
#define MADERA_FLL_SRC_AIF3LRCLK 14
#define MADERA_FLL_SRC_AIF4LRCLK 15
#define MADERA_CLK_SYSCLK 1
#define MADERA_CLK_ASYNCCLK 2
#define MADERA_CLK_OPCLK 3
#define MADERA_CLK_ASYNC_OPCLK 4
#define MADERA_CLK_SYSCLK_2 5
#define MADERA_CLK_SYSCLK_3 6
#define MADERA_CLK_ASYNCCLK_2 7
#define MADERA_CLK_DSPCLK 8
#define MADERA_CLK_SRC_MCLK1 0x0
#define MADERA_CLK_SRC_MCLK2 0x1
#define MADERA_CLK_SRC_FLL1 0x4
#define MADERA_CLK_SRC_FLL2 0x5
#define MADERA_CLK_SRC_FLL3 0x6
#define MADERA_CLK_SRC_FLLAO_HI 0x7
#define MADERA_CLK_SRC_FLL1_DIV6 0x7
#define MADERA_CLK_SRC_AIF1BCLK 0x8
#define MADERA_CLK_SRC_AIF2BCLK 0x9
#define MADERA_CLK_SRC_AIF3BCLK 0xA
#define MADERA_CLK_SRC_AIF4BCLK 0xB
#define MADERA_CLK_SRC_FLLAO 0xF
#define MADERA_MIXER_VOL_MASK 0x00FE
#define MADERA_MIXER_VOL_SHIFT 1
#define MADERA_MIXER_VOL_WIDTH 7
#define MADERA_CLK_6MHZ 0
#define MADERA_CLK_12MHZ 1
#define MADERA_CLK_24MHZ 2
#define MADERA_CLK_49MHZ 3
#define MADERA_CLK_98MHZ 4
#define MADERA_DSP_CLK_9MHZ 0
#define MADERA_DSP_CLK_18MHZ 1
#define MADERA_DSP_CLK_36MHZ 2
#define MADERA_DSP_CLK_73MHZ 3
#define MADERA_DSP_CLK_147MHZ 4
#define MADERA_MAX_DAI 17
#define MADERA_MAX_ADSP 7
#define MADERA_MAX_AIF_SOURCES 32
#define MADERA_MAX_MIXER_SOURCES 48
#define MADERA_NUM_MIXER_INPUTS 146
#define MADERA_FRF_COEFFICIENT_LEN 4
struct madera;
struct wm_adsp;
struct madera_jd_state;
/* Voice trigger event codes */
enum {
MADERA_TRIGGER_VOICE,
MADERA_TRIGGER_TEXT,
MADERA_TRIGGER_PANIC
};
struct madera_voice_trigger_info {
/** Which core triggered, 1-based (1 = DSP1, ...) */
int core_num;
int code;
u16 err_msg[4];
};
struct madera_dai_priv {
int clk;
struct snd_pcm_hw_constraint_list constraint;
int sample_rate;
int bit_width;
};
struct madera_priv {
struct wm_adsp adsp[MADERA_MAX_ADSP];
struct madera *madera;
int sysclk;
int asyncclk;
int dspclk;
struct madera_dai_priv dai[MADERA_MAX_DAI];
int num_inputs;
unsigned int in_pending;
unsigned int out_up_pending;
unsigned int out_up_delay;
unsigned int out_down_pending;
unsigned int out_down_delay;
unsigned int adsp_rate_cache[MADERA_MAX_ADSP];
struct mutex adsp_rate_lock;
struct mutex rate_lock;
struct mutex adsp_fw_lock;
int tdm_width[MADERA_MAX_AIF];
int tdm_slots[MADERA_MAX_AIF];
unsigned int aif_sources_cache[MADERA_MAX_AIF_SOURCES];
unsigned int mixer_sources_cache[MADERA_MAX_MIXER_SOURCES];
int (*get_sources)(unsigned int reg, const unsigned int **cur_sources,
int *lim);
u32 rx_port_handle[MADERA_SLIMBUS_MAX_CHANNELS];
u32 tx_port_handle[MADERA_SLIMBUS_MAX_CHANNELS];
u16 rx_channel_handle[MADERA_SLIMBUS_MAX_CHANNELS];
u16 tx_channel_handle[MADERA_SLIMBUS_MAX_CHANNELS];
u16 rx_chan_map_slot[3][MADERA_SLIMBUS_MAX_CHANNELS];
u16 tx_chan_map_slot[3][MADERA_SLIMBUS_MAX_CHANNELS];
int rx_chan_map_num[3];
int tx_chan_map_num[3];
u32 rx1_samplerate;
u32 rx1_sampleszbits;
u32 rx2_samplerate;
u32 rx2_sampleszbits;
u8 slim_logic_addr;
};
struct madera_fll_cfg {
int n;
int theta;
int lambda;
int refdiv;
int fratio;
int gain;
int alt_gain;
};
struct madera_fll {
struct madera *madera;
int id;
unsigned int base;
struct completion ok;
unsigned int fout;
int sync_src;
unsigned int sync_freq;
int ref_src;
unsigned int ref_freq;
struct madera_fll_cfg ref_cfg;
};
struct madera_enum {
struct soc_enum mixer_enum;
int val;
};
struct cs47l35 {
struct madera_priv core;
struct madera_fll fll;
};
extern const unsigned int madera_ana_tlv[];
extern const unsigned int madera_eq_tlv[];
extern const unsigned int madera_digital_tlv[];
extern const unsigned int madera_noise_tlv[];
extern const unsigned int madera_ng_tlv[];
extern const unsigned int madera_mixer_tlv[];
extern const char * const madera_mixer_texts[MADERA_NUM_MIXER_INPUTS];
extern unsigned int madera_mixer_values[MADERA_NUM_MIXER_INPUTS];
#define MADERA_GAINMUX_CONTROLS(name, base) \
SOC_SINGLE_RANGE_TLV(name " Input Volume", base + 1, \
MADERA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \
madera_mixer_tlv)
#define MADERA_MIXER_CONTROLS(name, base) \
SOC_SINGLE_RANGE_TLV(name " Input 1 Volume", base + 1, \
MADERA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \
madera_mixer_tlv), \
SOC_SINGLE_RANGE_TLV(name " Input 2 Volume", base + 3, \
MADERA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \
madera_mixer_tlv), \
SOC_SINGLE_RANGE_TLV(name " Input 3 Volume", base + 5, \
MADERA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \
madera_mixer_tlv), \
SOC_SINGLE_RANGE_TLV(name " Input 4 Volume", base + 7, \
MADERA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \
madera_mixer_tlv)
#define MADERA_MUX_ENUM_DECL(name, reg) \
SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL( \
name, reg, 0, 0xff, madera_mixer_texts, madera_mixer_values)
#define MADERA_MUX_CTL_DECL(name) \
const struct snd_kcontrol_new name##_mux = \
SOC_DAPM_ENUM("Route", name##_enum)
#define MADERA_MUX_ENUMS(name, base_reg) \
static MADERA_MUX_ENUM_DECL(name##_enum, base_reg); \
static MADERA_MUX_CTL_DECL(name)
#define MADERA_MIXER_ENUMS(name, base_reg) \
MADERA_MUX_ENUMS(name##_in1, base_reg); \
MADERA_MUX_ENUMS(name##_in2, base_reg + 2); \
MADERA_MUX_ENUMS(name##_in3, base_reg + 4); \
MADERA_MUX_ENUMS(name##_in4, base_reg + 6)
#define MADERA_DSP_AUX_ENUMS(name, base_reg) \
MADERA_MUX_ENUMS(name##_aux1, base_reg); \
MADERA_MUX_ENUMS(name##_aux2, base_reg + 8); \
MADERA_MUX_ENUMS(name##_aux3, base_reg + 16); \
MADERA_MUX_ENUMS(name##_aux4, base_reg + 24); \
MADERA_MUX_ENUMS(name##_aux5, base_reg + 32); \
MADERA_MUX_ENUMS(name##_aux6, base_reg + 40)
#define MADERA_MUX(name, ctrl) \
SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
#define MADERA_MUX_WIDGETS(name, name_str) \
MADERA_MUX(name_str " Input 1", &name##_mux)
#define MADERA_MIXER_WIDGETS(name, name_str) \
MADERA_MUX(name_str " Input 1", &name##_in1_mux), \
MADERA_MUX(name_str " Input 2", &name##_in2_mux), \
MADERA_MUX(name_str " Input 3", &name##_in3_mux), \
MADERA_MUX(name_str " Input 4", &name##_in4_mux), \
SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
#define MADERA_DSP_WIDGETS(name, name_str) \
MADERA_MIXER_WIDGETS(name##L, name_str "L"), \
MADERA_MIXER_WIDGETS(name##R, name_str "R"), \
MADERA_MUX(name_str " Aux 1", &name##_aux1_mux), \
MADERA_MUX(name_str " Aux 2", &name##_aux2_mux), \
MADERA_MUX(name_str " Aux 3", &name##_aux3_mux), \
MADERA_MUX(name_str " Aux 4", &name##_aux4_mux), \
MADERA_MUX(name_str " Aux 5", &name##_aux5_mux), \
MADERA_MUX(name_str " Aux 6", &name##_aux6_mux)
#define MADERA_MUX_ROUTES(widget, name) \
{ widget, NULL, name " Input 1" }, \
MADERA_MIXER_INPUT_ROUTES(name " Input 1")
#define MADERA_MIXER_ROUTES(widget, name) \
{ widget, NULL, name " Mixer" }, \
{ name " Mixer", NULL, name " Input 1" }, \
{ name " Mixer", NULL, name " Input 2" }, \
{ name " Mixer", NULL, name " Input 3" }, \
{ name " Mixer", NULL, name " Input 4" }, \
MADERA_MIXER_INPUT_ROUTES(name " Input 1"), \
MADERA_MIXER_INPUT_ROUTES(name " Input 2"), \
MADERA_MIXER_INPUT_ROUTES(name " Input 3"), \
MADERA_MIXER_INPUT_ROUTES(name " Input 4")
#define MADERA_DSP_ROUTES(name) \
{ name, NULL, name " Preloader"}, \
{ name " Preload", NULL, name " Preloader"}, \
{ name, NULL, "SYSCLK"}, \
{ name, NULL, "DSPCLK"}, \
{ name, NULL, name " Aux 1" }, \
{ name, NULL, name " Aux 2" }, \
{ name, NULL, name " Aux 3" }, \
{ name, NULL, name " Aux 4" }, \
{ name, NULL, name " Aux 5" }, \
{ name, NULL, name " Aux 6" }, \
MADERA_MIXER_INPUT_ROUTES(name " Aux 1"), \
MADERA_MIXER_INPUT_ROUTES(name " Aux 2"), \
MADERA_MIXER_INPUT_ROUTES(name " Aux 3"), \
MADERA_MIXER_INPUT_ROUTES(name " Aux 4"), \
MADERA_MIXER_INPUT_ROUTES(name " Aux 5"), \
MADERA_MIXER_INPUT_ROUTES(name " Aux 6"), \
MADERA_MIXER_ROUTES(name, name "L"), \
MADERA_MIXER_ROUTES(name, name "R")
#define MADERA_SAMPLE_RATE_CONTROL(name, domain) \
SOC_ENUM(name, madera_sample_rate[(domain) - 2])
#define MADERA_RATE_ENUM(xname, xenum) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\
.info = snd_soc_info_enum_double, \
.get = snd_soc_get_enum_double, .put = madera_rate_put, \
.private_value = (unsigned long)&xenum }
#define MADERA_EQ_CONTROL(xname, xbase) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \
.put = madera_eq_coeff_put, .private_value = \
((unsigned long)&(struct soc_bytes) { .base = xbase, \
.num_regs = 20, .mask = ~MADERA_EQ1_B1_MODE }) }
#define MADERA_LHPF_CONTROL(xname, xbase) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \
.put = madera_lhpf_coeff_put, .private_value = \
((unsigned long)&(struct soc_bytes) { .base = xbase, \
.num_regs = 1 }) }
#define MADERA_FRF_BYTES(xname, xbase, xregs) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \
.put = madera_frf_bytes_put, .private_value = \
((unsigned long)&(struct soc_bytes) {.base = xbase, \
.num_regs = xregs }) }
/* 2 mixer inputs with a stride of n in the register address */
#define MADERA_MIXER_INPUTS_2_N(_reg, n) \
(_reg), \
(_reg) + (1 * (n))
/* 4 mixer inputs with a stride of n in the register address */
#define MADERA_MIXER_INPUTS_4_N(_reg, n) \
MADERA_MIXER_INPUTS_2_N(_reg, n), \
MADERA_MIXER_INPUTS_2_N(_reg + (2 * n), n)
#define MADERA_DSP_MIXER_INPUTS(_reg) \
MADERA_MIXER_INPUTS_4_N(_reg, 2), \
MADERA_MIXER_INPUTS_4_N(_reg + 8, 2), \
MADERA_MIXER_INPUTS_4_N(_reg + 16, 8), \
MADERA_MIXER_INPUTS_2_N(_reg + 48, 8)
#define MADERA_RATES SNDRV_PCM_RATE_KNOT
#define MADERA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
#define MADERA_OSR_ENUM_SIZE 5
#define MADERA_SYNC_RATE_ENUM_SIZE 3
#define MADERA_ASYNC_RATE_ENUM_SIZE 2
#define MADERA_RATE_ENUM_SIZE \
(MADERA_SYNC_RATE_ENUM_SIZE + MADERA_ASYNC_RATE_ENUM_SIZE)
#define MADERA_SAMPLE_RATE_ENUM_SIZE 16
#define MADERA_DFC_TYPE_ENUM_SIZE 5
#define MADERA_DFC_WIDTH_ENUM_SIZE 5
extern const struct snd_kcontrol_new madera_inmux[];
extern const char * const madera_rate_text[MADERA_RATE_ENUM_SIZE];
extern const unsigned int madera_rate_val[MADERA_RATE_ENUM_SIZE];
extern const char * const madera_sample_rate_text[MADERA_SAMPLE_RATE_ENUM_SIZE];
extern const unsigned int madera_sample_rate_val[MADERA_SAMPLE_RATE_ENUM_SIZE];
extern const char * const madera_dfc_width_text[MADERA_DFC_WIDTH_ENUM_SIZE];
extern const unsigned int madera_dfc_width_val[MADERA_DFC_WIDTH_ENUM_SIZE];
extern const char * const madera_dfc_type_text[MADERA_DFC_TYPE_ENUM_SIZE];
extern const unsigned int madera_dfc_type_val[MADERA_DFC_TYPE_ENUM_SIZE];
extern const struct soc_enum madera_sample_rate[];
extern const struct soc_enum madera_isrc_fsl[];
extern const struct soc_enum madera_isrc_fsh[];
extern const struct soc_enum madera_asrc1_rate[];
extern const struct soc_enum madera_asrc2_rate[];
extern const struct soc_enum madera_output_rate;
extern const struct soc_enum madera_input_rate[];
extern const struct soc_enum madera_dfc_width[];
extern const struct soc_enum madera_dfc_type[];
extern const struct soc_enum madera_fx_rate;
extern const struct soc_enum madera_noise_gen_rate;
extern const struct soc_enum madera_spdif_rate;
extern const struct soc_enum madera_in_vi_ramp;
extern const struct soc_enum madera_in_vd_ramp;
extern const struct soc_enum madera_out_vi_ramp;
extern const struct soc_enum madera_out_vd_ramp;
extern const struct soc_enum madera_lhpf1_mode;
extern const struct soc_enum madera_lhpf2_mode;
extern const struct soc_enum madera_lhpf3_mode;
extern const struct soc_enum madera_lhpf4_mode;
extern const struct soc_enum madera_ng_hold;
extern const struct soc_enum madera_in_hpf_cut_enum;
extern const struct soc_enum madera_in_dmic_osr[];
extern const struct soc_enum madera_output_anc_src[];
extern const struct soc_enum madera_anc_input_src[];
extern const struct soc_enum madera_anc_ng_enum;
extern const struct soc_enum madera_ip_mode[];
extern const struct snd_kcontrol_new madera_dsp_trigger_output_mux[];
extern const struct snd_kcontrol_new madera_drc_activity_output_mux[];
extern const struct snd_kcontrol_new madera_adsp_rate_controls[];
extern const char *madera_sample_rate_val_to_name(unsigned int rate_val);
extern int madera_ip_mode_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
extern int madera_in_rate_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
extern int madera_dfc_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
extern int madera_lp_mode_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
extern int madera_sysclk_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
extern int madera_in_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event);
extern int madera_out_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event);
extern int madera_hp_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event);
extern int madera_anc_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event);
extern int madera_out1_demux_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
extern int madera_put_dre(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
extern int madera_adsp_rate_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
extern int madera_adsp_rate_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
extern int madera_adsp_rate_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
extern int madera_set_adsp_clk(struct wm_adsp *dsp, unsigned int freq);
extern int madera_rate_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
extern int madera_frf_bytes_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
extern int madera_eq_coeff_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
extern int madera_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
extern int madera_set_sysclk(struct snd_soc_codec *codec, int clk_id,
int source, unsigned int freq, int dir);
extern int madera_get_legacy_dspclk_setting(struct madera *madera,
unsigned int freq);
extern int madera_cache_and_clear_sources(struct madera_priv *priv,
const unsigned int *sources,
unsigned int *cache,
int lim);
extern int madera_restore_sources(struct madera_priv *priv,
const unsigned int *sources,
unsigned int *cache,
int lim);
extern void madera_spin_sysclk(struct madera_priv *priv);
extern const struct snd_soc_dai_ops madera_dai_ops;
extern const struct snd_soc_dai_ops madera_simple_dai_ops;
extern const struct snd_soc_dai_ops madera_slim_dai_ops;
extern int madera_init_fll(struct madera *madera, int id, int base,
struct madera_fll *fll);
extern int madera_set_fll_refclk(struct madera_fll *fll, int source,
unsigned int Fref, unsigned int Fout);
extern int madera_set_fll_syncclk(struct madera_fll *fll, int source,
unsigned int Fref, unsigned int Fout);
extern int madera_set_fll_ao_refclk(struct madera_fll *fll, int source,
unsigned int fin, unsigned int fout);
extern int madera_core_init(struct madera_priv *priv);
extern int madera_core_destroy(struct madera_priv *priv);
extern int madera_init_spk(struct snd_soc_codec *codec, int n_channels);
extern int madera_free_spk(struct snd_soc_codec *codec);
extern int madera_init_drc(struct snd_soc_codec *codec);
extern int madera_init_inputs(struct snd_soc_codec *codec,
const char * const *dmic_inputs,
int n_dmic_inputs,
const char * const *dmic_refs,
int n_dmic_refs);
extern int madera_init_outputs(struct snd_soc_codec *codec);
extern int madera_init_bus_error_irq(struct snd_soc_codec *codec, int dsp_num,
irq_handler_t handler);
extern void madera_destroy_bus_error_irq(struct snd_soc_codec *codec,
int dsp_num);
extern int madera_init_dai(struct madera_priv *priv, int dai);
extern int madera_set_output_mode(struct snd_soc_codec *codec, int output,
bool diff);
/* Following functions are for use by machine drivers */
extern int madera_set_custom_jd(struct snd_soc_codec *codec,
const struct madera_jd_state *custom_jd,
unsigned int index);
extern int madera_enable_force_bypass(struct snd_soc_codec *codec);
extern int madera_disable_force_bypass(struct snd_soc_codec *codec);
extern int madera_register_notifier(struct snd_soc_codec *codec,
struct notifier_block *nb);
extern int madera_unregister_notifier(struct snd_soc_codec *codec,
struct notifier_block *nb);
extern const struct snd_soc_dai_ops madera_slim_dai_ops;
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,240 +0,0 @@
/*
* wm_adsp.h -- Wolfson ADSP support
*
* Copyright 2012 Wolfson Microelectronics plc
*
* Author: Mark Brown <broonie@opensource.wolfsonmicro.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 __WM_ADSP_H
#define __WM_ADSP_H
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/compress_driver.h>
#include "wmfw.h"
/* Return values for wm_adsp_compr_handle_irq */
#define WM_ADSP_COMPR_OK 0
#define WM_ADSP_COMPR_VOICE_TRIGGER 1
#define WM_ADSP_MAX_CHANNEL_PER_DSP 2
#define WM_ADSP2_REGION_0 BIT(0)
#define WM_ADSP2_REGION_1 BIT(1)
#define WM_ADSP2_REGION_2 BIT(2)
#define WM_ADSP2_REGION_3 BIT(3)
#define WM_ADSP2_REGION_4 BIT(4)
#define WM_ADSP2_REGION_5 BIT(5)
#define WM_ADSP2_REGION_6 BIT(6)
#define WM_ADSP2_REGION_7 BIT(7)
#define WM_ADSP2_REGION_8 BIT(8)
#define WM_ADSP2_REGION_9 BIT(9)
#define WM_ADSP2_REGION_1_9 (WM_ADSP2_REGION_1 | \
WM_ADSP2_REGION_2 | WM_ADSP2_REGION_3 | \
WM_ADSP2_REGION_4 | WM_ADSP2_REGION_5 | \
WM_ADSP2_REGION_6 | WM_ADSP2_REGION_7 | \
WM_ADSP2_REGION_8 | WM_ADSP2_REGION_9)
#define WM_ADSP2_REGION_ALL (WM_ADSP2_REGION_0 | WM_ADSP2_REGION_1_9)
struct wm_adsp_region {
int type;
unsigned int base;
};
struct wm_adsp_alg_region {
struct list_head list;
unsigned int alg;
int type;
unsigned int base;
};
struct wm_adsp_compr;
struct wm_adsp_compr_buf;
struct wm_adsp_buffer_region_def {
unsigned int mem_type;
unsigned int base_offset;
unsigned int size_offset;
};
struct wm_adsp_fw_caps {
u32 id;
struct snd_codec_desc desc;
int num_regions;
struct wm_adsp_buffer_region_def *region_defs;
};
struct wm_adsp_fw_defs {
const char *file;
const char *binfile;
bool fullname;
int compr_direction;
int num_caps;
struct wm_adsp_fw_caps *caps;
bool voice_trigger;
};
struct wm_adsp {
const char *part;
int rev;
int num;
int type;
bool ao_dsp;
const char *suffix;
struct device *dev;
struct regmap *regmap;
struct snd_soc_codec *codec;
int base;
int base_sysinfo;
int sysclk_reg;
int sysclk_mask;
int sysclk_shift;
struct list_head alg_regions;
unsigned int fw_id;
unsigned int fw_id_version;
unsigned int fw_vendor_id;
const struct wm_adsp_region *mem;
int num_mems;
int fw;
int fw_ver;
bool preloaded;
bool booted;
bool running;
int num_firmwares;
struct wm_adsp_fw_defs *firmwares;
struct snd_kcontrol_new fw_ctrl;
struct soc_enum fw_enum;
struct list_head ctl_list;
struct work_struct boot_work;
int buf_num;
struct wm_adsp_compr *compr[WM_ADSP_MAX_CHANNEL_PER_DSP];
struct wm_adsp_compr_buf *buffer[WM_ADSP_MAX_CHANNEL_PER_DSP];
struct mutex pwr_lock;
unsigned int lock_regions;
bool unlock_all;
unsigned int n_rx_channels;
unsigned int n_tx_channels;
struct mutex *rate_lock;
u8 *rx_rate_cache;
u8 *tx_rate_cache;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_root;
char *wmfw_file_name;
char *bin_file_name;
#endif
void (*fwevent_cb)(struct wm_adsp *dsp, int eventid);
};
struct wm_adsp_compr {
struct wm_adsp *dsp;
struct wm_adsp_compr_buf *buf;
struct snd_compr_stream *stream;
struct snd_compressed_buffer size;
u32 *raw_buf;
unsigned int copied_total;
unsigned int sample_rate;
bool freed;
};
#define WM_ADSP1(wname, num) \
SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \
wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
#define WM_ADSP2_PRELOAD_SWITCH(wname, num) \
SOC_SINGLE_EXT(wname " Preload Switch", SND_SOC_NOPM, num, 1, 0, \
wm_adsp2_preloader_get, wm_adsp2_preloader_put)
#define WM_ADSP2(wname, num, event_fn) \
SND_SOC_DAPM_SPK(wname " Preload", NULL), \
{ .id = snd_soc_dapm_supply, .name = wname " Preloader", \
.reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD, \
.subseq = 100, /* Ensure we run after SYSCLK supply widget */ }, \
{ .id = snd_soc_dapm_out_drv, .name = wname, \
.reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
#define WM_HALO(wname, num, event_fn) \
SND_SOC_DAPM_SPK(wname " Preload", NULL), \
{ .id = snd_soc_dapm_supply, .name = wname " Preloader", \
.reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD, \
.subseq = 100, /* Ensure we run after SYSCLK supply widget */ }, \
{ .id = snd_soc_dapm_out_drv, .name = wname, \
.reg = SND_SOC_NOPM, .shift = num, .event = wm_halo_event, \
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
extern const struct snd_kcontrol_new wm_adsp_fw_controls[];
int wm_adsp1_init(struct wm_adsp *dsp);
int wm_adsp2_init(struct wm_adsp *dsp);
void wm_adsp2_remove(struct wm_adsp *dsp);
int wm_adsp2_codec_probe(struct wm_adsp *dsp, struct snd_soc_codec *codec);
int wm_adsp2_codec_remove(struct wm_adsp *dsp, struct snd_soc_codec *codec);
int wm_halo_init(struct wm_adsp *dsp, struct mutex *rate_lock);
int wm_adsp1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event,
unsigned int freq);
int wm_adsp2_lock(struct wm_adsp *adsp, unsigned int regions);
irqreturn_t wm_adsp2_bus_error(struct wm_adsp *adsp);
irqreturn_t wm_halo_bus_error(struct wm_adsp *dsp);
int wm_adsp2_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
int wm_halo_early_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
int wm_halo_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int wm_adsp_compr_open(struct wm_adsp *dsp,
struct snd_compr_stream *stream,
int channel);
int wm_adsp_compr_free(struct snd_compr_stream *stream);
int wm_adsp_compr_set_params(struct snd_compr_stream *stream,
struct snd_compr_params *params);
int wm_adsp_compr_get_caps(struct snd_compr_stream *stream,
struct snd_compr_caps *caps);
int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd);
int wm_adsp_compr_handle_irq(struct wm_adsp *dsp, int channel);
int wm_adsp_compr_pointer(struct snd_compr_stream *stream,
struct snd_compr_tstamp *tstamp);
int wm_adsp_compr_copy(struct snd_compr_stream *stream,
char __user *buf, size_t count);
extern int wm_adsp_handle_fw_event(struct wm_adsp *dsp);
#endif

View file

@ -1,202 +0,0 @@
/*
* wmfw.h - Wolfson firmware format information
*
* Copyright 2012 Wolfson Microelectronics plc
*
* Author: Mark Brown <broonie@opensource.wolfsonmicro.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 __WMFW_H
#define __WMFW_H
#include <linux/types.h>
#define WMFW_MAX_ALG_NAME 256
#define WMFW_MAX_ALG_DESCR_NAME 256
#define WMFW_MAX_COEFF_NAME 256
#define WMFW_MAX_COEFF_DESCR_NAME 256
#define WMFW_CTL_FLAG_SYS 0x8000
#define WMFW_CTL_FLAG_VOLATILE 0x0004
#define WMFW_CTL_FLAG_WRITEABLE 0x0002
#define WMFW_CTL_FLAG_READABLE 0x0001
/* Non-ALSA coefficient types start at 0x1000 */
#define WMFW_CTL_TYPE_ACKED 0x1000 /* acked control */
#define WMFW_CTL_TYPE_HOSTEVENT 0x1001 /* event control */
#define WMFW_CTL_TYPE_FWEVENT 0x1004 /* firmware event control */
struct wmfw_header {
char magic[4];
__le32 len;
__le16 rev;
u8 core;
u8 ver;
} __packed;
struct wmfw_footer {
__le64 timestamp;
__le32 checksum;
} __packed;
struct wmfw_adsp1_sizes {
__le32 dm;
__le32 pm;
__le32 zm;
} __packed;
struct wmfw_adsp2_sizes {
__le32 xm;
__le32 ym;
__le32 pm;
__le32 zm;
} __packed;
struct wmfw_region {
union {
__be32 type;
__le32 offset;
};
__le32 len;
u8 data[];
} __packed;
struct wmfw_id_hdr {
__be32 core_id;
__be32 core_rev;
__be32 id;
__be32 ver;
} __packed;
struct wmfw_adsp1_id_hdr {
struct wmfw_id_hdr fw;
__be32 zm;
__be32 dm;
__be32 n_algs;
} __packed;
struct wmfw_adsp2_id_hdr {
struct wmfw_id_hdr fw;
__be32 zm;
__be32 xm;
__be32 ym;
__be32 n_algs;
} __packed;
struct wmfw_halo_fwid_hdr {
__be32 core_id;
__be32 block_rev;
__be32 vendor_id;
__be32 id;
__be32 ver;
} __packed;
struct wmfw_halo_id_hdr {
struct wmfw_halo_fwid_hdr fw;
__be32 xm_base;
__be32 xm_size;
__be32 ym_base;
__be32 ym_size;
__be32 n_algs;
} __packed;
struct wmfw_alg_hdr {
__be32 id;
__be32 ver;
} __packed;
struct wmfw_adsp1_alg_hdr {
struct wmfw_alg_hdr alg;
__be32 zm;
__be32 dm;
} __packed;
struct wmfw_adsp2_alg_hdr {
struct wmfw_alg_hdr alg;
__be32 zm;
__be32 xm;
__be32 ym;
} __packed;
struct wmfw_halo_alg_hdr {
struct wmfw_alg_hdr alg;
__be32 xm_base;
__be32 xm_size;
__be32 ym_base;
__be32 ym_size;
} __packed;
struct wmfw_adsp_alg_data {
__le32 id;
u8 name[WMFW_MAX_ALG_NAME];
u8 descr[WMFW_MAX_ALG_DESCR_NAME];
__le32 ncoeff;
u8 data[];
} __packed;
struct wmfw_adsp_coeff_data {
struct {
__le16 offset;
__le16 type;
__le32 size;
} hdr;
u8 name[WMFW_MAX_COEFF_NAME];
u8 descr[WMFW_MAX_COEFF_DESCR_NAME];
__le16 ctl_type;
__le16 flags;
__le32 len;
u8 data[];
} __packed;
struct wmfw_coeff_hdr {
u8 magic[4];
__le32 len;
union {
__be32 rev;
__le32 ver;
};
union {
__be32 core;
__le32 core_ver;
};
u8 data[];
} __packed;
struct wmfw_coeff_item {
__le16 offset;
__le16 type;
__le32 id;
__le32 ver;
__le32 sr;
__le32 len;
u8 data[];
} __packed;
#define WMFW_ADSP1 1
#define WMFW_ADSP2 2
#define WMFW_HALO 4
#define WMFW_ABSOLUTE 0xf0
#define WMFW_ALGORITHM_DATA 0xf2
#define WMFW_NAME_TEXT 0xfe
#define WMFW_INFO_TEXT 0xff
#define WMFW_ADSP1_PM 2
#define WMFW_ADSP1_DM 3
#define WMFW_ADSP1_ZM 4
#define WMFW_ADSP2_PM 2
#define WMFW_ADSP2_ZM 4
#define WMFW_ADSP2_XM 5
#define WMFW_ADSP2_YM 6
#define WMFW_HALO_PM_PACKED 0x10
#define WMFW_HALO_XM_PACKED 0x11
#define WMFW_HALO_YM_PACKED 0x12
#endif