ASoC: cs35l41: Change from MFD to codec driver.

Remove MFD driver support from cs35l41 codec.

Change-Id: Iffcb54eac647a4aa7e47b37ffda8ded1e06af8cf
Signed-off-by: Vlad Karpovich <Vlad.Karpovich@cirrus.com>
Mot-CRs-fixed: (CR)
Reviewed-on: https://gerrit.mot.com/1177445
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Rav(CR) Vembu <raviv@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
Vlad Karpovich 2018-05-18 15:06:00 -05:00 • committed by Ravikumar Vembu
commit 8ae1c8cd2b
14 changed files with 624 additions and 741 deletions

View file

@ -3,6 +3,7 @@ CS35L41 Speaker Amplifier
Required properties:
- compatible : "cirrus,cs35l41"
"cirrus,cs35l40"
- reg : the SPI chip select line for the device
@ -10,6 +11,28 @@ Required properties:
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
@ -30,12 +53,6 @@ Optional properties:
11000 mV with increments of 50 mV.
(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 1600 mA and goes to a maximum of 4500 mA with increments
of 50 mA.
(Default) 4.50 Amps
- 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.
@ -49,7 +66,6 @@ Optional properties:
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
@ -61,46 +77,10 @@ Optional properties:
2 = 125C (Default)
3 = 135C
- cirrus,hw-noise-gate-select : Hardware Noise Gate feature. Each bit selects
a different block for detection.
000000 - All noise gating functionality disbled
xxxxx1 - Amplifier noise gating detection enabled
xxxx1x - Boost converter DCM detection enabled
xxx1xx - VMON low power mode detection enabled
xx1xxx - IMON low power mode detection enabled
x1xxxx - VP brownout prevention detection enabled
1xxxxx - VBST brownout prevention detection enabled
- cirrus,hw-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
- cirrus,hw-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 = 0.654 mVpk
1 = 0.328 mVpk
2 = 0.164 mVpk
3 = 0.082 mVpk (default)
4 = 0.041 mVpk
5 = 0.021 mVpk
6 = 0.010 mVpk
7 = True zero data (no LSB dither)
- cirrus,dsp-noise-gate-enable : DSP Noise Gate feature. If present, noise
- cirrus,noise-gate-enable : DSP Noise Gate feature. If present, noise
gate feature will be enabled.
- cirrus,dsp-noise-gate-threshold : Threshold of audio signal input which the
- 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.
@ -113,7 +93,7 @@ Optional properties:
6 = -102 dBFS
7 = -108 dBFS
- cirrus,dsp-noise-gate-delay : Time that the incoming audio signal must be
- 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
@ -211,17 +191,8 @@ cs35l41: cs35l41@2 {
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>;
};
Optional Fixed HW Params sub-node:
The cs35l41 node can have a single "cirrus,fixed-hw-params" sub-node for
setting the HW params to a fixed rate, width, and word-length.
Example:
cirrus,fixed-hw-params {
cirrus,fixed-rate = <48000>;
cirrus,fixed-width = <16>;
cirrus,fixed-wl = <16>;
};

View file

@ -7,8 +7,3 @@ LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk
include $(CLEAR_VARS)
LOCAL_MODULE := cirrus_cs35l41-mfd.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk

View file

@ -10,7 +10,3 @@ cirrus_madera-core-objs = madera-core.o madera-spi.o madera-core.o madera-spi.o
endif
obj-m += cirrus_madera-core.o
EXTRA_CFLAGS += -DCONFIG_MFD_CS35L41_I2C
cirrus_cs35l41-mfd-objs = cs35l41-core.o cs35l41-i2c.o cs35l41-tables.o
obj-m += cirrus_cs35l41-mfd.o

View file

@ -1,120 +0,0 @@
/*
* Core MFD support for Cirrus Logic CS35L41 codec
*
* Copyright 2017 Cirrus Logic
*
* 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/kernel.h>
#include <linux/gpio.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/regulator/consumer.h>
#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <sound/cs35l41.h>
#include <linux/mfd/cs35l41/core.h>
#define CS35L41_MFD_SYSFS_CLASS_NAME "cirrus"
static const struct mfd_cell cs35l41_devs[] = {
{ .name = "cs35l41-codec", },
};
static const char * const cs35l41_supplies[] = {
"VA",
"VP",
};
int cs35l41_dev_init(struct cs35l41_data *cs35l41)
{
int ret, i;
dev_set_drvdata(cs35l41->dev, cs35l41);
dev_info(cs35l41->dev, "Prince MFD core probe\n");
if (dev_get_platdata(cs35l41->dev))
memcpy(&cs35l41->pdata, dev_get_platdata(cs35l41->dev),
sizeof(cs35l41->pdata));
cs35l41->mfd_class = class_create(THIS_MODULE,
dev_name(cs35l41->dev));
if (IS_ERR(cs35l41->mfd_class)) {
ret = PTR_ERR(cs35l41->mfd_class);
dev_err(cs35l41->dev, "err class create\n");
return -EINVAL;
}
for (i = 0; i < ARRAY_SIZE(cs35l41_supplies); i++)
cs35l41->supplies[i].supply = cs35l41_supplies[i];
cs35l41->num_supplies = ARRAY_SIZE(cs35l41_supplies);
ret = devm_regulator_bulk_get(cs35l41->dev, cs35l41->num_supplies,
cs35l41->supplies);
if (ret != 0) {
dev_err(cs35l41->dev,
"Failed to request core supplies: %d\n",
ret);
return ret;
}
ret = regulator_bulk_enable(cs35l41->num_supplies, cs35l41->supplies);
if (ret != 0) {
dev_err(cs35l41->dev,
"Failed to enable core supplies: %d\n", ret);
return ret;
}
/* returning NULL can be an option if in stereo mode */
cs35l41->reset_gpio = devm_gpiod_get_optional(cs35l41->dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(cs35l41->reset_gpio)) {
ret = PTR_ERR(cs35l41->reset_gpio);
cs35l41->reset_gpio = NULL;
if (ret == -EBUSY) {
dev_info(cs35l41->dev,
"Reset line busy, assuming shared reset\n");
} else {
dev_err(cs35l41->dev,
"Failed to get reset GPIO: %d\n", ret);
goto err;
}
}
if (cs35l41->reset_gpio) {
usleep_range(1000, 1100);
gpiod_set_value_cansleep(cs35l41->reset_gpio, 1);
}
usleep_range(2000, 2100);
ret = mfd_add_devices(cs35l41->dev, PLATFORM_DEVID_AUTO, cs35l41_devs,
ARRAY_SIZE(cs35l41_devs),
NULL, 0, NULL);
if (ret) {
dev_err(cs35l41->dev, "Failed to add subdevices: %d\n", ret);
ret = -EINVAL;
goto err;
}
return 0;
err:
regulator_bulk_disable(cs35l41->num_supplies, cs35l41->supplies);
return ret;
}
int cs35l41_dev_exit(struct cs35l41_data *cs35l41)
{
mfd_remove_devices(cs35l41->dev);
regulator_bulk_disable(cs35l41->num_supplies, cs35l41->supplies);
return 0;
}

View file

@ -1,26 +0,0 @@
/*
* cs35l41.h -- MFD internals for Cirrus Logic CS35L41 codec
*
* Copyright 2017 Cirrus Logic
*
* 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.
*/
#ifndef CS35L41_MFD_H
#define CS35L41_MFD_H
#include <linux/pm.h>
#include <linux/of.h>
#include <linux/mfd/cs35l41/core.h>
int cs35l41_dev_init(struct cs35l41_data *cs35l41);
int cs35l41_dev_exit(struct cs35l41_data *cs35l41);
#endif

View file

@ -1,30 +0,0 @@
/*
* core.h -- MFD includes for Cirrus Logic CS35L41 codecs
*
* Copyright 2017 Cirrus Logic
*
* 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.
*/
#ifndef CS35L41_MFD_CORE_H
#define CS35L41_MFD_CORE_H
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
struct cs35l41_data {
struct cs35l41_platform_data *pdata;
struct device *dev;
struct regmap *regmap;
struct class *mfd_class;
struct regulator_bulk_data supplies[2];
struct gpio_desc *reset_gpio;
int num_supplies;
int irq;
};
#endif

View file

@ -1,7 +1,7 @@
/*
* linux/sound/cs35l41.h -- Platform data for CS35L41
*
* Copyright (c) 2016 Cirrus Logic Inc.
* 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
@ -22,7 +22,7 @@ struct classh_cfg {
int classh_wk_fet_thld;
};
struct cs35l41_irq_cfg {
struct irq_cfg {
bool is_present;
bool irq_pol_inv;
bool irq_out_en;
@ -34,25 +34,46 @@ struct cs35l41_platform_data {
bool lrclk_frc;
bool right_channel;
bool amp_gain_zc;
bool dsp_ng_enable;
bool ng_enable;
int bst_ind;
int bst_vctrl;
int bst_ipk;
int bst_cap;
int temp_warn_thld;
int dsp_ng_pcm_thld;
int dsp_ng_delay;
int ng_pcm_thld;
int ng_delay;
int dout_hiz;
unsigned int hw_ng_sel;
unsigned int hw_ng_delay;
unsigned int hw_ng_thld;
unsigned int fixed_rate;
unsigned int fixed_width;
unsigned int fixed_wl;
bool fixed_params;
const char * dsp_part_name;
struct cs35l41_irq_cfg irq_config1;
struct cs35l41_irq_cfg irq_config2;
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;
bool tdm_mode;
bool i2s_mode;
bool swire_mode;
bool halo_booted;
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

@ -7,6 +7,12 @@ 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
@ -19,12 +25,6 @@ LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk
include $(CLEAR_VARS)
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_cs47l35.ko
LOCAL_MODULE_TAGS := optional
@ -49,5 +49,14 @@ 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
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

View file

@ -16,9 +16,12 @@ endif
EXTRA_CFLAGS += -DCONFIG_SND_SOC_AOV_TRIGGER -DCONFIG_SND_SOC_OPALUM
cirrus_madera-objs = madera.o madera-slimbus.o wm_adsp.o
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
@ -28,9 +31,6 @@ obj-m += cirrus_cs35l36.o
cirrus_cs47l35-objs = cs47l35.o
obj-m += cirrus_cs47l35.o
cirrus_cs35l41-objs = cs35l41.o
obj-m += cirrus_cs35l41.o
cirrus_cs47l90-objs = cs47l90.o
obj-m += cirrus_cs47l90.o
@ -38,3 +38,12 @@ cirrus_ospl-objs = ospl2xx.o
obj-m += cirrus_ospl.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

View file

@ -1,26 +1,36 @@
/*
* I2C bus interface to Cirrus Logic CS35L41 codec
* cs35l41-i2c.c -- CS35l41 I2C driver
*
* Copyright 2017 Cirrus Logic
* 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/device.h>
#include <linux/err.h>
#include <linux/i2c.h>
#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/of.h>
#include <linux/gpio.h>
#include <linux/mfd/cs35l41/registers.h>
#include "sound/cs35l41.h"
#include "wm_adsp.h"
#include "cs35l41.h"
#include <sound/cs35l41.h>
static struct regmap_config cs35l41_regmap_i2c = {
.reg_bits = 32,
@ -36,13 +46,6 @@ static struct regmap_config cs35l41_regmap_i2c = {
.cache_type = REGCACHE_RBTREE,
};
static const struct of_device_id cs35l41_of_match[] = {
{.compatible = "cirrus,cs35l40"},
{.compatible = "cirrus,cs35l41"},
{},
};
MODULE_DEVICE_TABLE(of, cs35l41_of_match);
static const struct i2c_device_id cs35l41_id_i2c[] = {
{"cs35l40", 0},
{"cs35l41", 0},
@ -54,20 +57,20 @@ MODULE_DEVICE_TABLE(i2c, cs35l41_id_i2c);
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;
struct cs35l41_data *cs35l41;
int ret;
cs35l41 = devm_kzalloc(dev, sizeof(struct cs35l41_data), GFP_KERNEL);
cs35l41 = devm_kzalloc(dev, sizeof(struct cs35l41_private), GFP_KERNEL);
if (cs35l41 == NULL)
return -ENOMEM;
cs35l41->dev = dev;
cs35l41->irq = client->irq;
cs35l41->pdata = pdata;
cs35l41->bus_spi = false;
i2c_set_clientdata(client, cs35l41);
cs35l41->regmap = devm_regmap_init_i2c(client, regmap_config);
@ -78,16 +81,27 @@ static int cs35l41_i2c_probe(struct i2c_client *client,
return ret;
}
return cs35l41_dev_init(cs35l41);
return cs35l41_probe(cs35l41, pdata);
}
static int cs35l41_i2c_remove(struct i2c_client *client)
{
struct cs35l41_data *cs35l41 = i2c_get_clientdata(client);
struct cs35l41_private *cs35l41 = i2c_get_clientdata(client);
return cs35l41_dev_exit(cs35l41);
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",

View file

@ -1,25 +1,31 @@
/*
* SPI bus interface to Cirrus Logic CS35L41 codec
* cs35l41-spi.c -- CS35l41 SPI driver
*
* Copyright 2017 Cirrus Logic
* 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/device.h>
#include <linux/err.h>
#include <linux/spi/spi.h>
#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/of.h>
#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include "sound/cs35l41.h"
#include "wm_adsp.h"
#include "cs35l41.h"
#include <linux/mfd/cs35l41/registers.h>
#include <sound/cs35l41.h>
static struct regmap_config cs35l41_regmap_spi = {
.reg_bits = 32,
@ -36,13 +42,6 @@ static struct regmap_config cs35l41_regmap_spi = {
.cache_type = REGCACHE_RBTREE,
};
static const struct of_device_id cs35l41_of_match[] = {
{.compatible = "cirrus,cs35l40"},
{.compatible = "cirrus,cs35l41"},
{},
};
MODULE_DEVICE_TABLE(of, cs35l41_of_match);
static const struct spi_device_id cs35l41_id_spi[] = {
{"cs35l40", 0},
{"cs35l41", 0},
@ -56,11 +55,11 @@ 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_data *cs35l41;
struct cs35l41_private *cs35l41;
int ret;
cs35l41 = devm_kzalloc(&spi->dev,
sizeof(struct cs35l41_data),
sizeof(struct cs35l41_private),
GFP_KERNEL);
if (cs35l41 == NULL)
return -ENOMEM;
@ -76,20 +75,29 @@ static int cs35l41_spi_probe(struct spi_device *spi)
cs35l41->dev = &spi->dev;
cs35l41->irq = spi->irq;
cs35l41->pdata = pdata;
cs35l41->bus_spi = true;
dev_info(&spi->dev, "CS35L41 SPI MFD probe\n");
return cs35l41_dev_init(cs35l41);
return cs35l41_probe(cs35l41, pdata);
}
static int cs35l41_spi_remove(struct spi_device *spi)
{
struct cs35l41_data *cs35l41 = spi_get_drvdata(spi);
struct cs35l41_private *cs35l41 = spi_get_drvdata(spi);
return cs35l41_dev_exit(cs35l41);
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",

View file

@ -1,7 +1,7 @@
/*
* cs35l41-tables.c -- CS35L41 ALSA SoC audio driver
*
* Copyright 2016 Cirrus Logic, Inc.
* Copyright 2018 Cirrus Logic, Inc.
*
* Author: Brian Austin <brian.austin@cirrus.com>
* David Rhodes <david.rhodes@cirrus.com>
@ -12,7 +12,7 @@
*
*/
#include <linux/mfd/cs35l41/registers.h>
#include "cs35l41.h"
const struct reg_default cs35l41_reg[CS35L41_MAX_CACHE_REG] = {
{CS35L41_TEST_KEY_CTL, 0x00000000},
@ -665,13 +665,15 @@ bool cs35l41_volatile_reg(struct device *dev, unsigned int reg)
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 otp_packed_element_t otp_map_1[CS35L41_NUM_OTP_ELEM] = {
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*/
@ -774,7 +776,8 @@ static const struct otp_packed_element_t otp_map_1[CS35L41_NUM_OTP_ELEM] = {
{0x00017044, 0, 24}, /*LOT_NUMBER*/
};
static const struct otp_packed_element_t otp_map_2[CS35L41_NUM_OTP_ELEM] = {
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*/
@ -877,20 +880,34 @@ static const struct otp_packed_element_t otp_map_2[CS35L41_NUM_OTP_ELEM] = {
{0x00017044, 0, 24}, /*LOT_NUMBER*/
};
const struct otp_map_element_t otp_map_map[3] = {
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,7 +1,7 @@
/*
* cs35l41.h -- CS35L41 definitions
* cs35l41.h -- CS35L41 ALSA SoC audio driver
*
* Copyright 2016 Cirrus Logic, Inc.
* Copyright 2018 Cirrus Logic, Inc.
*
* Author: Brian Austin <brian.austin@cirrus.com>
* David Rhodes <david.rhodes@cirrus.com>
@ -536,6 +536,7 @@
#define CS35L41_MAX_CACHE_REG 0x0000006F
#define CS35L41_OTP_SIZE_WORDS 32
#define CS35L41_NUM_OTP_ELEM 100
#define CS35L41_NUM_OTP_MAPS 4
#define CS35L41_VALID_PDATA 0x80000000
@ -560,8 +561,17 @@
#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
@ -579,19 +589,12 @@
#define CS35L41_CH_WKFET_THLD_MASK 0x0F00
#define CS35L41_CH_WKFET_THLD_SHIFT 8
#define CS35L41_HW_NG_SEL_MASK 0x3F00
#define CS35L41_HW_NG_SEL_SHIFT 8
#define CS35L41_HW_NG_DLY_MASK 0x0070
#define CS35L41_HW_NG_DLY_SHIFT 4
#define CS35L41_HW_NG_THLD_MASK 0x0007
#define CS35L41_HW_NG_THLD_SHIFT 0
#define CS35L41_DSP_NG_ENABLE_MASK 0x00010000
#define CS35L41_DSP_NG_ENABLE_SHIFT 16
#define CS35L41_DSP_NG_THLD_MASK 0x7
#define CS35L41_DSP_NG_THLD_SHIFT 0
#define CS35L41_DSP_NG_DELAY_MASK 0x0F00
#define CS35L41_DSP_NG_DELAY_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
@ -655,11 +658,6 @@
#define CS35L36_PUP_DONE_IRQ_UNMASK 0x5F
#define CS35L36_PUP_DONE_IRQ_MASK 0xBF
#define CS35L41_AMP_VOL_PCM_SHIFT 0x03
#define CS35L41_AMP_VOL_PCM_MASK 0x7FF
#define CS35L41_AMP_VOL_PCM_DEFAULT 0x0000
#define CS35L41_AMP_VOL_PCM_MUTE 0x0400
#define CS35L41_AMP_SHORT_ERR 0x80000000
#define CS35L41_BST_SHORT_ERR 0x0100
#define CS35L41_TEMP_WARN 0x8000
@ -667,7 +665,8 @@
#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_PLL_UNLOCK 0x10
#define CS35L41_OTP_BOOT_ERR 0x80000000
#define CS35L41_AMP_SHORT_ERR_RLS 0x02
#define CS35L41_BST_SHORT_ERR_RLS 0x04
@ -699,6 +698,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)
@ -706,25 +707,23 @@
bool cs35l41_readable_reg(struct device *dev, unsigned int reg);
bool cs35l41_volatile_reg(struct device *dev, unsigned int reg);
struct otp_packed_element_t {
struct cs35l41_otp_packed_element_t {
u32 reg;
u8 shift;
u8 size;
};
struct otp_map_element_t {
struct cs35l41_otp_map_element_t {
u32 id;
u32 num_elements;
const struct otp_packed_element_t *map;
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 otp_map_element_t otp_map_map[3];
#define CS35L41_OTP_HDR_MASK_1 0xFFFFFFFE
#define CS35L41_OTP_HDR_MASK_2 0x0000FFFF
#define CS35L41_OTP_HDR_VAL_1 0x00001500
#define CS35L41_OTP_HDR_VAL_2 0x00000300
extern const struct cs35l41_otp_map_element_t
cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS];
#define CS35L41_CSPL_CMD_NONE 0
#define CS35L41_CSPL_CMD_MUTE 1
@ -736,5 +735,4 @@ extern const struct otp_map_element_t otp_map_map[3];
#define CS35L41_CSPL_CAL_STRUCT_ADDR 0x02800224
#define CS35L41_AMB_TEMP_DEFAULT 25
#endif /*__CS35L41_H__*/