2022-03-04 19:13:44

by Lucas Tanure

[permalink] [raw]
Subject: [PATCH v2 00/20] Support external boost at CS35l41 ASoC driver

Move the support for CS35L41 external boost to its shared library
for ASoC use.
This move resulted in cs35l41_hda_reg_sequence being removed,
and its steps were broken down into regmap writes or functions
from the library. And hardware configuration struct was unified
for its use in the shared lib.
While at it, some minor bugs were found and fixed it.

v2 changelog:
- Instead of removing the log, playback actions will log the last regmap access.
- Documentation patch with the correct subject line and fixed bug reported by Rob Herring on the
provided example.

Previous versions:
v1: https://lkml.org/lkml/2022/3/3/759

David Rhodes (2):
ASoC: cs35l41: Fix GPIO2 configuration
ASoC: cs35l41: Document CS35l41 External Boost

Lucas Tanure (18):
ASoC: cs35l41: Fix max number of TX channels
ASoC: cs35l41: Fix DSP mbox start command and global enable order
ASoC: cs35l41: Remove unnecessary param
sound: cs35l41: Unify hardware configuration
sound: cs35l41: Check hw_config before using it
sound: cs35l41: Move cs35l41_gpio_config to shared lib
hda: cs35l41: Fix I2S params comments
hda: cs35l41: Always configure the DAI
hda: cs35l41: Add Boost type flag
hda: cs35l41: Put the device into safe mode for external boost
hda: cs35l41: Mute the device before shutdown
sound: cs35l41: Enable Internal Boost in shared lib
hda: cs35l41: Move boost config to initialization code
hda: cs35l41: Remove cs35l41_hda_reg_sequence struct
hda: cs35l41: Reorganize log for playback actions
hda: cs35l41: Handle all external boost setups the same way
hda: cs35l41: Move external boost handling to lib for ASoC use
ASoC: cs35l41: Support external boost

.../bindings/sound/cirrus,cs35l41.yaml | 44 ++-
include/sound/cs35l41.h | 53 +++-
sound/pci/hda/cs35l41_hda.c | 295 ++++++------------
sound/pci/hda/cs35l41_hda.h | 27 +-
sound/soc/codecs/cs35l41-i2c.c | 4 +-
sound/soc/codecs/cs35l41-lib.c | 190 ++++++++++-
sound/soc/codecs/cs35l41-spi.c | 4 +-
sound/soc/codecs/cs35l41.c | 174 +++++------
sound/soc/codecs/cs35l41.h | 5 +-
9 files changed, 440 insertions(+), 356 deletions(-)

--
2.35.1


2022-03-04 19:35:32

by Lucas Tanure

[permalink] [raw]
Subject: [PATCH v2 15/20] hda: cs35l41: Remove cs35l41_hda_reg_sequence struct

Remove cs35l41_hd_reg_sequence as it adds a
layer of flexibility not needed.

Signed-off-by: Lucas Tanure <[email protected]>
---
sound/pci/hda/cs35l41_hda.c | 79 ++++++++++++++++---------------------
sound/pci/hda/cs35l41_hda.h | 14 -------
2 files changed, 33 insertions(+), 60 deletions(-)

diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
index 3b8167d1ccc1..08ce9b8005ec 100644
--- a/sound/pci/hda/cs35l41_hda.c
+++ b/sound/pci/hda/cs35l41_hda.c
@@ -32,14 +32,6 @@ static const struct reg_sequence cs35l41_hda_mute[] = {
{ CS35L41_AMP_DIG_VOL_CTRL, 0x0000A678 }, // AMP_VOL_PCM Mute
};

-static const struct reg_sequence cs35l41_hda_start_bst[] = {
- { CS35L41_PWR_CTRL1, 0x00000001, 3000}, // set GLOBAL_EN = 1
-};
-
-static const struct reg_sequence cs35l41_hda_stop_bst[] = {
- { CS35L41_PWR_CTRL1, 0x00000000, 3000}, // set GLOBAL_EN = 0
-};
-
// only on amps where GPIO1 is used to control ext. VSPK switch
static const struct reg_sequence cs35l41_start_ext_vspk[] = {
{ 0x00000040, 0x00000055 },
@@ -109,31 +101,44 @@ static const struct reg_sequence cs35l41_reset_to_safe[] = {
{ 0x00000040, 0x00000033 },
};

-static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_no_bst = {
- .prepare = cs35l41_safe_to_active,
- .num_prepare = ARRAY_SIZE(cs35l41_safe_to_active),
- .cleanup = cs35l41_active_to_safe,
- .num_cleanup = ARRAY_SIZE(cs35l41_active_to_safe),
-};
+static int cs35l41_hda_global_enable(struct cs35l41_hda *cs35l41, int enable)
+{
+ int ret;

-static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_ext_bst = {
- .prepare = cs35l41_start_ext_vspk,
- .num_prepare = ARRAY_SIZE(cs35l41_start_ext_vspk),
- .cleanup = cs35l41_stop_ext_vspk,
- .num_cleanup = ARRAY_SIZE(cs35l41_stop_ext_vspk),
-};
+ switch (cs35l41->hw_cfg.bst_type) {
+ case CS35L41_INT_BOOST:
+ ret = regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL1,
+ CS35L41_GLOBAL_EN_MASK,
+ enable << CS35L41_GLOBAL_EN_SHIFT);
+ usleep_range(3000, 3100);
+ break;
+ case CS35L41_EXT_BOOST:
+ if (enable)
+ ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41_start_ext_vspk,
+ ARRAY_SIZE(cs35l41_start_ext_vspk));
+ else
+ ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41_stop_ext_vspk,
+ ARRAY_SIZE(cs35l41_stop_ext_vspk));
+ break;
+ case CS35L41_EXT_BOOST_NO_VSPK_SWITCH:
+ if (enable)
+ ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41_safe_to_active,
+ ARRAY_SIZE(cs35l41_safe_to_active));
+ else
+ ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41_active_to_safe,
+ ARRAY_SIZE(cs35l41_active_to_safe));
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }

-static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_int_bst = {
- .prepare = cs35l41_hda_start_bst,
- .num_prepare = ARRAY_SIZE(cs35l41_hda_start_bst),
- .cleanup = cs35l41_hda_stop_bst,
- .num_cleanup = ARRAY_SIZE(cs35l41_hda_stop_bst),
+ return ret;
};

static void cs35l41_hda_playback_hook(struct device *dev, int action)
{
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
- const struct cs35l41_hda_reg_sequence *reg_seq = cs35l41->reg_seq;
struct regmap *reg = cs35l41->regmap;
int ret = 0;

@@ -145,19 +150,15 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action)
CS35L41_AMP_EN_MASK, 1 << CS35L41_AMP_EN_SHIFT);
break;
case HDA_GEN_PCM_ACT_PREPARE:
- if (reg_seq->prepare)
- ret = regmap_multi_reg_write(reg, reg_seq->prepare, reg_seq->num_prepare);
+ ret = cs35l41_hda_global_enable(cs35l41, 1);
break;
case HDA_GEN_PCM_ACT_CLEANUP:
regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute));
- if (reg_seq->cleanup)
- ret = regmap_multi_reg_write(reg, reg_seq->cleanup, reg_seq->num_cleanup);
+ ret = cs35l41_hda_global_enable(cs35l41, 0);
break;
case HDA_GEN_PCM_ACT_CLOSE:
regmap_update_bits(reg, CS35L41_PWR_CTRL2,
CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT);
- if (reg_seq->close)
- ret = regmap_multi_reg_write(reg, reg_seq->close, reg_seq->num_close);
break;
default:
ret = -EINVAL;
@@ -221,7 +222,6 @@ static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41)

switch (hw_cfg->bst_type) {
case CS35L41_INT_BOOST:
- cs35l41->reg_seq = &cs35l41_hda_reg_seq_int_bst;
ret = cs35l41_boost_config(cs35l41->dev, cs35l41->regmap,
hw_cfg->bst_ind, hw_cfg->bst_cap, hw_cfg->bst_ipk);
if (ret)
@@ -229,10 +229,6 @@ static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41)
break;
case CS35L41_EXT_BOOST:
case CS35L41_EXT_BOOST_NO_VSPK_SWITCH:
- if (hw_cfg->bst_type == CS35L41_EXT_BOOST)
- cs35l41->reg_seq = &cs35l41_hda_reg_seq_ext_bst;
- else
- cs35l41->reg_seq = &cs35l41_hda_reg_seq_no_bst;
regmap_multi_reg_write(cs35l41->regmap, cs35l41_reset_to_safe,
ARRAY_SIZE(cs35l41_reset_to_safe));
ret = regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, CS35L41_BST_EN_MASK,
@@ -511,15 +507,6 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
if (ret)
goto err;

- if (cs35l41->reg_seq->probe) {
- ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41->reg_seq->probe,
- cs35l41->reg_seq->num_probe);
- if (ret) {
- dev_err(cs35l41->dev, "Fail to apply probe reg patch: %d\n", ret);
- goto err;
- }
- }
-
ret = component_add(cs35l41->dev, &cs35l41_hda_comp_ops);
if (ret) {
dev_err(cs35l41->dev, "Register component failed: %d\n", ret);
diff --git a/sound/pci/hda/cs35l41_hda.h b/sound/pci/hda/cs35l41_hda.h
index 17f10764f174..44d9204ffdf1 100644
--- a/sound/pci/hda/cs35l41_hda.h
+++ b/sound/pci/hda/cs35l41_hda.h
@@ -27,24 +27,10 @@ enum cs35l41_hda_gpio_function {
CS35l41_SYNC,
};

-struct cs35l41_hda_reg_sequence {
- const struct reg_sequence *probe;
- unsigned int num_probe;
- const struct reg_sequence *open;
- unsigned int num_open;
- const struct reg_sequence *prepare;
- unsigned int num_prepare;
- const struct reg_sequence *cleanup;
- unsigned int num_cleanup;
- const struct reg_sequence *close;
- unsigned int num_close;
-};
-
struct cs35l41_hda {
struct device *dev;
struct regmap *regmap;
struct gpio_desc *reset_gpio;
- const struct cs35l41_hda_reg_sequence *reg_seq;
struct cs35l41_hw_cfg hw_cfg;

int irq;
--
2.35.1

2022-03-04 19:36:50

by Lucas Tanure

[permalink] [raw]
Subject: [PATCH v2 05/20] sound: cs35l41: Unify hardware configuration

Both ASoC and HDA require to configure the GPIOs
and Boost, so put that in single shared struct.

Signed-off-by: Lucas Tanure <[email protected]>
Acked-by: Charles Keepax <[email protected]>
---
include/sound/cs35l41.h | 35 +++++++++----
sound/pci/hda/cs35l41_hda.c | 69 +++++++++++--------------
sound/pci/hda/cs35l41_hda.h | 13 +----
sound/soc/codecs/cs35l41-i2c.c | 4 +-
sound/soc/codecs/cs35l41-spi.c | 4 +-
sound/soc/codecs/cs35l41.c | 93 +++++++++++++++-------------------
sound/soc/codecs/cs35l41.h | 5 +-
7 files changed, 102 insertions(+), 121 deletions(-)

diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h
index bf7f9a9aeba0..262c75109c9e 100644
--- a/include/sound/cs35l41.h
+++ b/include/sound/cs35l41.h
@@ -701,9 +701,6 @@
#define CS35L41_GPIO1_CTRL_SHIFT 16
#define CS35L41_GPIO2_CTRL_MASK 0x07000000
#define CS35L41_GPIO2_CTRL_SHIFT 24
-#define CS35L41_GPIO_CTRL_OPEN_INT 2
-#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

@@ -735,19 +732,37 @@ enum cs35l41_clk_ids {
CS35L41_CLKID_MCLK = 4,
};

-struct cs35l41_irq_cfg {
- bool irq_pol_inv;
- bool irq_out_en;
- int irq_src_sel;
+enum cs35l41_gpio_func {
+ CS35L41_HIZ,
+ CS35L41_GPIO,
+ CS35L41_INT_OPEN_DRAIN_GPIO2,
+ CS35L41_MCLK,
+ CS35L41_INT_PUSH_PULL_LOW_GPIO2,
+ CS35L41_INT_PUSH_PULL_HIGH_GPIO2,
+ CS35L41_PDM_CLK_GPIO2,
+ CS35L41_PDM_DATA_GPIO2,
+ CS35L41_MDSYNC_GPIO1 = 2,
+ CS35L41_PDM_CLK_GPIO1 = 4,
+ CS35L41_PDM_DATA_GPIO1 = 5,
};

-struct cs35l41_platform_data {
+struct cs35l41_gpio_cfg {
+ bool pol_inv;
+ bool out_en;
+ enum cs35l41_gpio_func func;
+};
+
+struct cs35l41_hw_cfg {
int bst_ind;
int bst_ipk;
int bst_cap;
int dout_hiz;
- struct cs35l41_irq_cfg irq_config1;
- struct cs35l41_irq_cfg irq_config2;
+ struct cs35l41_gpio_cfg gpio1;
+ struct cs35l41_gpio_cfg gpio2;
+ unsigned int spk_pos;
+
+ /* Don't put the AMP in reset if VSPK can not be turned off */
+ bool vspk_always_on;
};

struct cs35l41_otp_packed_element_t {
diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
index 718595380868..b79d6ad4b4f5 100644
--- a/sound/pci/hda/cs35l41_hda.c
+++ b/sound/pci/hda/cs35l41_hda.c
@@ -213,13 +213,13 @@ static const struct component_ops cs35l41_hda_comp_ops = {
.unbind = cs35l41_hda_unbind,
};

-static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41,
- const struct cs35l41_hda_hw_config *hw_cfg)
+static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41)
{
+ struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;
bool internal_boost = false;
int ret;

- if (!hw_cfg) {
+ if (hw_cfg->vspk_always_on) {
cs35l41->reg_seq = &cs35l41_hda_reg_seq_no_bst;
return 0;
}
@@ -227,7 +227,7 @@ static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41,
if (hw_cfg->bst_ind || hw_cfg->bst_cap || hw_cfg->bst_ipk)
internal_boost = true;

- switch (hw_cfg->gpio1_func) {
+ switch (hw_cfg->gpio1.func) {
case CS35L41_NOT_USED:
break;
case CS35l41_VSPK_SWITCH:
@@ -239,11 +239,11 @@ static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41,
CS35L41_GPIO1_CTRL_MASK, 2 << CS35L41_GPIO1_CTRL_SHIFT);
break;
default:
- dev_err(cs35l41->dev, "Invalid function %d for GPIO1\n", hw_cfg->gpio1_func);
+ dev_err(cs35l41->dev, "Invalid function %d for GPIO1\n", hw_cfg->gpio1.func);
return -EINVAL;
}

- switch (hw_cfg->gpio2_func) {
+ switch (hw_cfg->gpio2.func) {
case CS35L41_NOT_USED:
break;
case CS35L41_INTERRUPT:
@@ -251,7 +251,7 @@ static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41,
CS35L41_GPIO2_CTRL_MASK, 2 << CS35L41_GPIO2_CTRL_SHIFT);
break;
default:
- dev_err(cs35l41->dev, "Invalid function %d for GPIO2\n", hw_cfg->gpio2_func);
+ dev_err(cs35l41->dev, "Invalid function %d for GPIO2\n", hw_cfg->gpio2.func);
return -EINVAL;
}

@@ -267,13 +267,12 @@ static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41,
cs35l41->reg_seq = &cs35l41_hda_reg_seq_ext_bst;
}

- return cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, (unsigned int *)&hw_cfg->spk_pos);
+ return cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, &hw_cfg->spk_pos);
}

-static struct cs35l41_hda_hw_config *cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41,
- const char *hid, int id)
+static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, int id)
{
- struct cs35l41_hda_hw_config *hw_cfg;
+ struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;
u32 values[HDA_MAX_COMPONENTS];
struct acpi_device *adev;
struct device *physdev;
@@ -284,7 +283,7 @@ static struct cs35l41_hda_hw_config *cs35l41_hda_read_acpi(struct cs35l41_hda *c
adev = acpi_dev_get_first_match_dev(hid, NULL, -1);
if (!adev) {
dev_err(cs35l41->dev, "Failed to find an ACPI device for %s\n", hid);
- return ERR_PTR(-ENODEV);
+ return -ENODEV;
}

physdev = get_device(acpi_get_first_physical_node(adev));
@@ -324,29 +323,23 @@ static struct cs35l41_hda_hw_config *cs35l41_hda_read_acpi(struct cs35l41_hda *c
cs35l41->reset_gpio = fwnode_gpiod_get_index(&adev->fwnode, "reset", cs35l41->index,
GPIOD_OUT_LOW, "cs35l41-reset");

- hw_cfg = kzalloc(sizeof(*hw_cfg), GFP_KERNEL);
- if (!hw_cfg) {
- ret = -ENOMEM;
- goto err;
- }
-
property = "cirrus,speaker-position";
ret = device_property_read_u32_array(physdev, property, values, nval);
if (ret)
- goto err_free;
+ goto err;
hw_cfg->spk_pos = values[cs35l41->index];

property = "cirrus,gpio1-func";
ret = device_property_read_u32_array(physdev, property, values, nval);
if (ret)
- goto err_free;
- hw_cfg->gpio1_func = values[cs35l41->index];
+ goto err;
+ hw_cfg->gpio1.func = values[cs35l41->index];

property = "cirrus,gpio2-func";
ret = device_property_read_u32_array(physdev, property, values, nval);
if (ret)
- goto err_free;
- hw_cfg->gpio2_func = values[cs35l41->index];
+ goto err;
+ hw_cfg->gpio2.func = values[cs35l41->index];

property = "cirrus,boost-peak-milliamp";
ret = device_property_read_u32_array(physdev, property, values, nval);
@@ -365,15 +358,13 @@ static struct cs35l41_hda_hw_config *cs35l41_hda_read_acpi(struct cs35l41_hda *c

put_device(physdev);

- return hw_cfg;
+ return 0;

-err_free:
- kfree(hw_cfg);
err:
put_device(physdev);
dev_err(cs35l41->dev, "Failed property %s: %d\n", property, ret);

- return ERR_PTR(ret);
+ return ret;

no_acpi_dsd:
/*
@@ -384,22 +375,21 @@ static struct cs35l41_hda_hw_config *cs35l41_hda_read_acpi(struct cs35l41_hda *c
* fwnode.
*/
if (strncmp(hid, "CLSA0100", 8) != 0)
- return ERR_PTR(-EINVAL);
+ return -EINVAL;

/* check I2C address to assign the index */
cs35l41->index = id == 0x40 ? 0 : 1;
cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH);
- cs35l41->vspk_always_on = true;
+ cs35l41->hw_cfg.vspk_always_on = true;
put_device(physdev);

- return NULL;
+ return 0;
}

int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
struct regmap *regmap)
{
unsigned int int_sts, regid, reg_revid, mtl_revid, chipid, int_status;
- struct cs35l41_hda_hw_config *acpi_hw_cfg;
struct cs35l41_hda *cs35l41;
int ret;

@@ -415,9 +405,11 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
cs35l41->regmap = regmap;
dev_set_drvdata(dev, cs35l41);

- acpi_hw_cfg = cs35l41_hda_read_acpi(cs35l41, device_name, id);
- if (IS_ERR(acpi_hw_cfg))
- return PTR_ERR(acpi_hw_cfg);
+ ret = cs35l41_hda_read_acpi(cs35l41, device_name, id);
+ if (ret) {
+ dev_err_probe(cs35l41->dev, ret, "Platform not supported %d\n", ret);
+ return ret;
+ }

if (IS_ERR(cs35l41->reset_gpio)) {
ret = PTR_ERR(cs35l41->reset_gpio);
@@ -490,11 +482,9 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
if (ret)
goto err;

- ret = cs35l41_hda_apply_properties(cs35l41, acpi_hw_cfg);
+ ret = cs35l41_hda_apply_properties(cs35l41);
if (ret)
goto err;
- kfree(acpi_hw_cfg);
- acpi_hw_cfg = NULL;

if (cs35l41->reg_seq->probe) {
ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41->reg_seq->probe,
@@ -516,8 +506,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
return 0;

err:
- kfree(acpi_hw_cfg);
- if (!cs35l41->vspk_always_on)
+ if (!cs35l41->hw_cfg.vspk_always_on)
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
gpiod_put(cs35l41->reset_gpio);

@@ -531,7 +520,7 @@ void cs35l41_hda_remove(struct device *dev)

component_del(cs35l41->dev, &cs35l41_hda_comp_ops);

- if (!cs35l41->vspk_always_on)
+ if (!cs35l41->hw_cfg.vspk_always_on)
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
gpiod_put(cs35l41->reset_gpio);
}
diff --git a/sound/pci/hda/cs35l41_hda.h b/sound/pci/hda/cs35l41_hda.h
index 74951001501c..17f10764f174 100644
--- a/sound/pci/hda/cs35l41_hda.h
+++ b/sound/pci/hda/cs35l41_hda.h
@@ -40,26 +40,15 @@ struct cs35l41_hda_reg_sequence {
unsigned int num_close;
};

-struct cs35l41_hda_hw_config {
- unsigned int spk_pos;
- unsigned int gpio1_func;
- unsigned int gpio2_func;
- int bst_ind;
- int bst_ipk;
- int bst_cap;
-};
-
struct cs35l41_hda {
struct device *dev;
struct regmap *regmap;
struct gpio_desc *reset_gpio;
const struct cs35l41_hda_reg_sequence *reg_seq;
+ struct cs35l41_hw_cfg hw_cfg;

int irq;
int index;
-
- /* Don't put the AMP in reset of VSPK can not be turned off */
- bool vspk_always_on;
};

int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
diff --git a/sound/soc/codecs/cs35l41-i2c.c b/sound/soc/codecs/cs35l41-i2c.c
index faad5c638cb8..5ff0f00a2de4 100644
--- a/sound/soc/codecs/cs35l41-i2c.c
+++ b/sound/soc/codecs/cs35l41-i2c.c
@@ -34,7 +34,7 @@ static int cs35l41_i2c_probe(struct i2c_client *client,
{
struct cs35l41_private *cs35l41;
struct device *dev = &client->dev;
- struct cs35l41_platform_data *pdata = dev_get_platdata(dev);
+ struct cs35l41_hw_cfg *hw_cfg = dev_get_platdata(dev);
const struct regmap_config *regmap_config = &cs35l41_regmap_i2c;
int ret;

@@ -54,7 +54,7 @@ static int cs35l41_i2c_probe(struct i2c_client *client,
return ret;
}

- return cs35l41_probe(cs35l41, pdata);
+ return cs35l41_probe(cs35l41, hw_cfg);
}

static int cs35l41_i2c_remove(struct i2c_client *client)
diff --git a/sound/soc/codecs/cs35l41-spi.c b/sound/soc/codecs/cs35l41-spi.c
index 169221a5b09f..9e19c946a66b 100644
--- a/sound/soc/codecs/cs35l41-spi.c
+++ b/sound/soc/codecs/cs35l41-spi.c
@@ -30,7 +30,7 @@ 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_hw_cfg *hw_cfg = dev_get_platdata(&spi->dev);
struct cs35l41_private *cs35l41;
int ret;

@@ -52,7 +52,7 @@ static int cs35l41_spi_probe(struct spi_device *spi)
cs35l41->dev = &spi->dev;
cs35l41->irq = spi->irq;

- return cs35l41_probe(cs35l41, pdata);
+ return cs35l41_probe(cs35l41, hw_cfg);
}

static void cs35l41_spi_remove(struct spi_device *spi)
diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index 6b784a62df0c..67b33c5c3d44 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -999,10 +999,10 @@ static int cs35l41_set_pdata(struct cs35l41_private *cs35l41)

/* Set Platform Data */
/* Required */
- if (cs35l41->pdata.bst_ipk &&
- cs35l41->pdata.bst_ind && cs35l41->pdata.bst_cap) {
- ret = cs35l41_boost_config(cs35l41->dev, cs35l41->regmap, cs35l41->pdata.bst_ind,
- cs35l41->pdata.bst_cap, cs35l41->pdata.bst_ipk);
+ if (cs35l41->hw_cfg.bst_ipk &&
+ cs35l41->hw_cfg.bst_ind && cs35l41->hw_cfg.bst_cap) {
+ ret = cs35l41_boost_config(cs35l41->dev, cs35l41->regmap, cs35l41->hw_cfg.bst_ind,
+ cs35l41->hw_cfg.bst_cap, cs35l41->hw_cfg.bst_ipk);
if (ret) {
dev_err(cs35l41->dev, "Error in Boost DT config: %d\n", ret);
return ret;
@@ -1013,43 +1013,39 @@ static int cs35l41_set_pdata(struct cs35l41_private *cs35l41)
}

/* Optional */
- if (cs35l41->pdata.dout_hiz <= CS35L41_ASP_DOUT_HIZ_MASK &&
- cs35l41->pdata.dout_hiz >= 0)
- regmap_update_bits(cs35l41->regmap, CS35L41_SP_HIZ_CTRL,
- CS35L41_ASP_DOUT_HIZ_MASK,
- cs35l41->pdata.dout_hiz);
+ if (cs35l41->hw_cfg.dout_hiz <= CS35L41_ASP_DOUT_HIZ_MASK &&
+ cs35l41->hw_cfg.dout_hiz >= 0)
+ regmap_update_bits(cs35l41->regmap, CS35L41_SP_HIZ_CTRL, CS35L41_ASP_DOUT_HIZ_MASK,
+ cs35l41->hw_cfg.dout_hiz);

return 0;
}

-static int cs35l41_irq_gpio_config(struct cs35l41_private *cs35l41)
+static int cs35l41_gpio_config(struct cs35l41_private *cs35l41)
{
- struct cs35l41_irq_cfg *irq_gpio_cfg1 = &cs35l41->pdata.irq_config1;
- struct cs35l41_irq_cfg *irq_gpio_cfg2 = &cs35l41->pdata.irq_config2;
+ struct cs35l41_gpio_cfg *gpio1 = &cs35l41->hw_cfg.gpio1;
+ struct cs35l41_gpio_cfg *gpio2 = &cs35l41->hw_cfg.gpio2;
int irq_pol = IRQF_TRIGGER_NONE;

regmap_update_bits(cs35l41->regmap, CS35L41_GPIO1_CTRL1,
CS35L41_GPIO_POL_MASK | CS35L41_GPIO_DIR_MASK,
- irq_gpio_cfg1->irq_pol_inv << CS35L41_GPIO_POL_SHIFT |
- !irq_gpio_cfg1->irq_out_en << CS35L41_GPIO_DIR_SHIFT);
+ gpio1->pol_inv << CS35L41_GPIO_POL_SHIFT |
+ !gpio1->out_en << CS35L41_GPIO_DIR_SHIFT);

regmap_update_bits(cs35l41->regmap, CS35L41_GPIO2_CTRL1,
CS35L41_GPIO_POL_MASK | CS35L41_GPIO_DIR_MASK,
- irq_gpio_cfg2->irq_pol_inv << CS35L41_GPIO_POL_SHIFT |
- !irq_gpio_cfg2->irq_out_en << CS35L41_GPIO_DIR_SHIFT);
+ gpio2->pol_inv << CS35L41_GPIO_POL_SHIFT |
+ !gpio2->out_en << CS35L41_GPIO_DIR_SHIFT);

regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
CS35L41_GPIO1_CTRL_MASK | CS35L41_GPIO2_CTRL_MASK,
- irq_gpio_cfg1->irq_src_sel << CS35L41_GPIO1_CTRL_SHIFT |
- irq_gpio_cfg2->irq_src_sel << CS35L41_GPIO2_CTRL_SHIFT);
+ gpio1->func << CS35L41_GPIO1_CTRL_SHIFT |
+ gpio2->func << CS35L41_GPIO2_CTRL_SHIFT);

- if ((irq_gpio_cfg2->irq_src_sel ==
- (CS35L41_GPIO_CTRL_ACTV_LO | CS35L41_VALID_PDATA)) ||
- (irq_gpio_cfg2->irq_src_sel ==
- (CS35L41_GPIO_CTRL_OPEN_INT | CS35L41_VALID_PDATA)))
+ if ((gpio2->func == (CS35L41_INT_PUSH_PULL_LOW_GPIO2 | CS35L41_VALID_PDATA)) ||
+ (gpio2->func == (CS35L41_INT_OPEN_DRAIN_GPIO2 | CS35L41_VALID_PDATA)))
irq_pol = IRQF_TRIGGER_LOW;
- else if (irq_gpio_cfg2->irq_src_sel ==
- (CS35L41_GPIO_CTRL_ACTV_HI | CS35L41_VALID_PDATA))
+ else if (gpio2->func == (CS35L41_INT_PUSH_PULL_HIGH_GPIO2 | CS35L41_VALID_PDATA))
irq_pol = IRQF_TRIGGER_HIGH;

return irq_pol;
@@ -1115,50 +1111,44 @@ static const struct snd_soc_component_driver soc_component_dev_cs35l41 = {
.set_sysclk = cs35l41_component_set_sysclk,
};

-static int cs35l41_handle_pdata(struct device *dev, struct cs35l41_platform_data *pdata)
+static int cs35l41_handle_pdata(struct device *dev, struct cs35l41_hw_cfg *hw_cfg)
{
- struct cs35l41_irq_cfg *irq_gpio1_config = &pdata->irq_config1;
- struct cs35l41_irq_cfg *irq_gpio2_config = &pdata->irq_config2;
+ struct cs35l41_gpio_cfg *gpio1 = &hw_cfg->gpio1;
+ struct cs35l41_gpio_cfg *gpio2 = &hw_cfg->gpio2;
unsigned int val;
int ret;

ret = device_property_read_u32(dev, "cirrus,boost-peak-milliamp", &val);
if (ret >= 0)
- pdata->bst_ipk = val;
+ hw_cfg->bst_ipk = val;

ret = device_property_read_u32(dev, "cirrus,boost-ind-nanohenry", &val);
if (ret >= 0)
- pdata->bst_ind = val;
+ hw_cfg->bst_ind = val;

ret = device_property_read_u32(dev, "cirrus,boost-cap-microfarad", &val);
if (ret >= 0)
- pdata->bst_cap = val;
+ hw_cfg->bst_cap = val;

ret = device_property_read_u32(dev, "cirrus,asp-sdout-hiz", &val);
if (ret >= 0)
- pdata->dout_hiz = val;
+ hw_cfg->dout_hiz = val;
else
- pdata->dout_hiz = -1;
+ hw_cfg->dout_hiz = -1;

/* GPIO1 Pin Config */
- irq_gpio1_config->irq_pol_inv = device_property_read_bool(dev,
- "cirrus,gpio1-polarity-invert");
- irq_gpio1_config->irq_out_en = device_property_read_bool(dev,
- "cirrus,gpio1-output-enable");
- ret = device_property_read_u32(dev, "cirrus,gpio1-src-select",
- &val);
+ gpio1->pol_inv = device_property_read_bool(dev, "cirrus,gpio1-polarity-invert");
+ gpio1->out_en = device_property_read_bool(dev, "cirrus,gpio1-output-enable");
+ ret = device_property_read_u32(dev, "cirrus,gpio1-src-select", &val);
if (ret >= 0)
- irq_gpio1_config->irq_src_sel = val | CS35L41_VALID_PDATA;
+ gpio1->func = val | CS35L41_VALID_PDATA;

/* GPIO2 Pin Config */
- irq_gpio2_config->irq_pol_inv = device_property_read_bool(dev,
- "cirrus,gpio2-polarity-invert");
- irq_gpio2_config->irq_out_en = device_property_read_bool(dev,
- "cirrus,gpio2-output-enable");
- ret = device_property_read_u32(dev, "cirrus,gpio2-src-select",
- &val);
+ gpio2->pol_inv = device_property_read_bool(dev, "cirrus,gpio2-polarity-invert");
+ gpio2->out_en = device_property_read_bool(dev, "cirrus,gpio2-output-enable");
+ ret = device_property_read_u32(dev, "cirrus,gpio2-src-select", &val);
if (ret >= 0)
- irq_gpio2_config->irq_src_sel = val | CS35L41_VALID_PDATA;
+ gpio2->func = val | CS35L41_VALID_PDATA;

return 0;
}
@@ -1248,17 +1238,16 @@ static int cs35l41_dsp_init(struct cs35l41_private *cs35l41)
return ret;
}

-int cs35l41_probe(struct cs35l41_private *cs35l41,
- struct cs35l41_platform_data *pdata)
+int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg *hw_cfg)
{
u32 regid, reg_revid, i, mtl_revid, int_status, chipid_match;
int irq_pol = 0;
int ret;

- if (pdata) {
- cs35l41->pdata = *pdata;
+ if (hw_cfg) {
+ cs35l41->hw_cfg = *hw_cfg;
} else {
- ret = cs35l41_handle_pdata(cs35l41->dev, &cs35l41->pdata);
+ ret = cs35l41_handle_pdata(cs35l41->dev, &cs35l41->hw_cfg);
if (ret != 0)
return ret;
}
@@ -1357,7 +1346,7 @@ int cs35l41_probe(struct cs35l41_private *cs35l41,

cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap);

- irq_pol = cs35l41_irq_gpio_config(cs35l41);
+ irq_pol = cs35l41_gpio_config(cs35l41);

/* Set interrupt masks for critical errors */
regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1,
diff --git a/sound/soc/codecs/cs35l41.h b/sound/soc/codecs/cs35l41.h
index 88a3d6e3434f..e3369e0aa89f 100644
--- a/sound/soc/codecs/cs35l41.h
+++ b/sound/soc/codecs/cs35l41.h
@@ -44,7 +44,7 @@ enum cs35l41_cspl_mbox_cmd {
struct cs35l41_private {
struct wm_adsp dsp; /* needs to be first member */
struct snd_soc_codec *codec;
- struct cs35l41_platform_data pdata;
+ struct cs35l41_hw_cfg hw_cfg;
struct device *dev;
struct regmap *regmap;
struct regulator_bulk_data supplies[CS35L41_NUM_SUPPLIES];
@@ -53,8 +53,7 @@ struct cs35l41_private {
struct gpio_desc *reset_gpio;
};

-int cs35l41_probe(struct cs35l41_private *cs35l41,
- struct cs35l41_platform_data *pdata);
+int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg *hw_cfg);
void cs35l41_remove(struct cs35l41_private *cs35l41);

#endif /*__CS35L41_H__*/
--
2.35.1

2022-03-04 19:41:17

by Lucas Tanure

[permalink] [raw]
Subject: [PATCH v2 03/20] ASoC: cs35l41: Fix DSP mbox start command and global enable order

Global enable must happen before CSPL_MBOX_CMD_RESUME command
is sent. Move it to PRE_PMU as both events use
SND_SOC_DAPM_OUT_DRV_E macro.

Signed-off-by: Lucas Tanure <[email protected]>
Acked-by: Charles Keepax <[email protected]>
---
sound/soc/codecs/cs35l41.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index f3787d77f892..05de94fd2e55 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -573,7 +573,7 @@ static int cs35l41_main_amp_event(struct snd_soc_dapm_widget *w,
int ret = 0;

switch (event) {
- case SND_SOC_DAPM_POST_PMU:
+ case SND_SOC_DAPM_PRE_PMU:
regmap_multi_reg_write_bypassed(cs35l41->regmap,
cs35l41_pup_patch,
ARRAY_SIZE(cs35l41_pup_patch));
@@ -649,7 +649,7 @@ static const struct snd_soc_dapm_widget cs35l41_dapm_widgets[] = {

SND_SOC_DAPM_OUT_DRV_E("Main AMP", CS35L41_PWR_CTRL2, 0, 0, NULL, 0,
cs35l41_main_amp_event,
- SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_PRE_PMU),

SND_SOC_DAPM_MUX("ASP TX1 Source", SND_SOC_NOPM, 0, 0, &asp_tx1_mux),
SND_SOC_DAPM_MUX("ASP TX2 Source", SND_SOC_NOPM, 0, 0, &asp_tx2_mux),
--
2.35.1

2022-03-04 19:50:51

by Lucas Tanure

[permalink] [raw]
Subject: [PATCH v2 04/20] ASoC: cs35l41: Remove unnecessary param

cs35l41_private is not used on cs35l41_handle_pdata

Signed-off-by: Lucas Tanure <[email protected]>
Acked-by: Charles Keepax <[email protected]>
---
sound/soc/codecs/cs35l41.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index 05de94fd2e55..6b784a62df0c 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -1115,9 +1115,7 @@ static const struct snd_soc_component_driver soc_component_dev_cs35l41 = {
.set_sysclk = cs35l41_component_set_sysclk,
};

-static int cs35l41_handle_pdata(struct device *dev,
- struct cs35l41_platform_data *pdata,
- struct cs35l41_private *cs35l41)
+static int cs35l41_handle_pdata(struct device *dev, struct cs35l41_platform_data *pdata)
{
struct cs35l41_irq_cfg *irq_gpio1_config = &pdata->irq_config1;
struct cs35l41_irq_cfg *irq_gpio2_config = &pdata->irq_config2;
@@ -1260,7 +1258,7 @@ int cs35l41_probe(struct cs35l41_private *cs35l41,
if (pdata) {
cs35l41->pdata = *pdata;
} else {
- ret = cs35l41_handle_pdata(cs35l41->dev, &cs35l41->pdata, cs35l41);
+ ret = cs35l41_handle_pdata(cs35l41->dev, &cs35l41->pdata);
if (ret != 0)
return ret;
}
--
2.35.1

2022-03-04 19:53:01

by Lucas Tanure

[permalink] [raw]
Subject: [PATCH v2 09/20] hda: cs35l41: Always configure the DAI

The Dai configuration is always the same and
should always configured during open.

Signed-off-by: Lucas Tanure <[email protected]>
---
sound/pci/hda/cs35l41_hda.c | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
index fe6f6a208d29..4c99dcac2dd7 100644
--- a/sound/pci/hda/cs35l41_hda.c
+++ b/sound/pci/hda/cs35l41_hda.c
@@ -111,8 +111,6 @@ static const struct reg_sequence cs35l41_reset_to_safe[] = {
static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_no_bst = {
.probe = cs35l41_reset_to_safe,
.num_probe = ARRAY_SIZE(cs35l41_reset_to_safe),
- .open = cs35l41_hda_config,
- .num_open = ARRAY_SIZE(cs35l41_hda_config),
.prepare = cs35l41_safe_to_active,
.num_prepare = ARRAY_SIZE(cs35l41_safe_to_active),
.cleanup = cs35l41_active_to_safe,
@@ -120,8 +118,6 @@ static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_no_bst = {
};

static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_ext_bst = {
- .open = cs35l41_hda_config,
- .num_open = ARRAY_SIZE(cs35l41_hda_config),
.prepare = cs35l41_start_ext_vspk,
.num_prepare = ARRAY_SIZE(cs35l41_start_ext_vspk),
.cleanup = cs35l41_stop_ext_vspk,
@@ -129,8 +125,6 @@ static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_ext_bst = {
};

static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_int_bst = {
- .open = cs35l41_hda_config,
- .num_open = ARRAY_SIZE(cs35l41_hda_config),
.prepare = cs35l41_hda_start_bst,
.num_prepare = ARRAY_SIZE(cs35l41_hda_start_bst),
.cleanup = cs35l41_hda_stop_bst,
@@ -146,8 +140,8 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action)

switch (action) {
case HDA_GEN_PCM_ACT_OPEN:
- if (reg_seq->open)
- ret = regmap_multi_reg_write(reg, reg_seq->open, reg_seq->num_open);
+ ret = regmap_multi_reg_write(reg, cs35l41_hda_config,
+ ARRAY_SIZE(cs35l41_hda_config));
break;
case HDA_GEN_PCM_ACT_PREPARE:
if (reg_seq->prepare)
--
2.35.1

2022-03-04 20:18:07

by Lucas Tanure

[permalink] [raw]
Subject: [PATCH v2 07/20] sound: cs35l41: Move cs35l41_gpio_config to shared lib

ASoC and HDA can use a single function to configure gpios

Signed-off-by: Lucas Tanure <[email protected]>
Acked-by: Charles Keepax <[email protected]>
---
include/sound/cs35l41.h | 1 +
sound/pci/hda/cs35l41_hda.c | 11 ++++-----
sound/soc/codecs/cs35l41-lib.c | 41 +++++++++++++++++++++++++++++++
sound/soc/codecs/cs35l41.c | 45 +---------------------------------
4 files changed, 48 insertions(+), 50 deletions(-)

diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h
index 57c47636c223..e3ec0f422fff 100644
--- a/include/sound/cs35l41.h
+++ b/include/sound/cs35l41.h
@@ -792,5 +792,6 @@ int cs35l41_set_channels(struct device *dev, struct regmap *reg,
unsigned int rx_num, unsigned int *rx_slot);
int cs35l41_boost_config(struct device *dev, struct regmap *regmap, int boost_ind, int boost_cap,
int boost_ipk);
+int cs35l41_gpio_config(struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg);

#endif /* __CS35L41_H */
diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
index a14ad3b0d516..81cdbd84cf7d 100644
--- a/sound/pci/hda/cs35l41_hda.c
+++ b/sound/pci/hda/cs35l41_hda.c
@@ -235,12 +235,11 @@ static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41)
case CS35L41_NOT_USED:
break;
case CS35l41_VSPK_SWITCH:
- regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
- CS35L41_GPIO1_CTRL_MASK, 1 << CS35L41_GPIO1_CTRL_SHIFT);
+ hw_cfg->gpio1.func = CS35L41_GPIO;
+ hw_cfg->gpio1.out_en = true;
break;
case CS35l41_SYNC:
- regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
- CS35L41_GPIO1_CTRL_MASK, 2 << CS35L41_GPIO1_CTRL_SHIFT);
+ hw_cfg->gpio1.func = CS35L41_MDSYNC_GPIO1;
break;
default:
dev_err(cs35l41->dev, "Invalid function %d for GPIO1\n",
@@ -254,8 +253,6 @@ static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41)
case CS35L41_NOT_USED:
break;
case CS35L41_INTERRUPT:
- regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
- CS35L41_GPIO2_CTRL_MASK, 2 << CS35L41_GPIO2_CTRL_SHIFT);
break;
default:
dev_err(cs35l41->dev, "Invalid GPIO2 function %d\n", hw_cfg->gpio2.func);
@@ -263,6 +260,8 @@ static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41)
}
}

+ cs35l41_gpio_config(cs35l41->regmap, hw_cfg);
+
if (internal_boost) {
cs35l41->reg_seq = &cs35l41_hda_reg_seq_int_bst;
ret = cs35l41_boost_config(cs35l41->dev, cs35l41->regmap,
diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c
index 905c648a8f49..3fae34a232cd 100644
--- a/sound/soc/codecs/cs35l41-lib.c
+++ b/sound/soc/codecs/cs35l41-lib.c
@@ -1040,6 +1040,47 @@ int cs35l41_boost_config(struct device *dev, struct regmap *regmap, int boost_in
}
EXPORT_SYMBOL_GPL(cs35l41_boost_config);

+int cs35l41_gpio_config(struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg)
+{
+ struct cs35l41_gpio_cfg *gpio1 = &hw_cfg->gpio1;
+ struct cs35l41_gpio_cfg *gpio2 = &hw_cfg->gpio2;
+ int irq_pol = IRQF_TRIGGER_NONE;
+
+ regmap_update_bits(regmap, CS35L41_GPIO1_CTRL1,
+ CS35L41_GPIO_POL_MASK | CS35L41_GPIO_DIR_MASK,
+ gpio1->pol_inv << CS35L41_GPIO_POL_SHIFT |
+ !gpio1->out_en << CS35L41_GPIO_DIR_SHIFT);
+
+ regmap_update_bits(regmap, CS35L41_GPIO2_CTRL1,
+ CS35L41_GPIO_POL_MASK | CS35L41_GPIO_DIR_MASK,
+ gpio2->pol_inv << CS35L41_GPIO_POL_SHIFT |
+ !gpio2->out_en << CS35L41_GPIO_DIR_SHIFT);
+
+ if (gpio1->valid)
+ regmap_update_bits(regmap, CS35L41_GPIO_PAD_CONTROL, CS35L41_GPIO1_CTRL_MASK,
+ gpio1->func << CS35L41_GPIO1_CTRL_SHIFT);
+
+ if (gpio2->valid) {
+ regmap_update_bits(regmap, CS35L41_GPIO_PAD_CONTROL, CS35L41_GPIO2_CTRL_MASK,
+ gpio2->func << CS35L41_GPIO2_CTRL_SHIFT);
+
+ switch (gpio2->func) {
+ case CS35L41_INT_PUSH_PULL_LOW_GPIO2:
+ case CS35L41_INT_OPEN_DRAIN_GPIO2:
+ irq_pol = IRQF_TRIGGER_LOW;
+ break;
+ case CS35L41_INT_PUSH_PULL_HIGH_GPIO2:
+ irq_pol = IRQF_TRIGGER_HIGH;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return irq_pol;
+}
+EXPORT_SYMBOL_GPL(cs35l41_gpio_config);
+
MODULE_DESCRIPTION("CS35L41 library");
MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <[email protected]>");
MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <[email protected]>");
diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index 5dbc2147209a..d25689fe0c60 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -1017,49 +1017,6 @@ static int cs35l41_set_pdata(struct cs35l41_private *cs35l41)
return 0;
}

-static int cs35l41_gpio_config(struct cs35l41_private *cs35l41)
-{
- struct cs35l41_gpio_cfg *gpio1 = &cs35l41->hw_cfg.gpio1;
- struct cs35l41_gpio_cfg *gpio2 = &cs35l41->hw_cfg.gpio2;
- int irq_pol = IRQF_TRIGGER_NONE;
-
- regmap_update_bits(cs35l41->regmap, CS35L41_GPIO1_CTRL1,
- CS35L41_GPIO_POL_MASK | CS35L41_GPIO_DIR_MASK,
- gpio1->pol_inv << CS35L41_GPIO_POL_SHIFT |
- !gpio1->out_en << CS35L41_GPIO_DIR_SHIFT);
-
- regmap_update_bits(cs35l41->regmap, CS35L41_GPIO2_CTRL1,
- CS35L41_GPIO_POL_MASK | CS35L41_GPIO_DIR_MASK,
- gpio2->pol_inv << CS35L41_GPIO_POL_SHIFT |
- !gpio2->out_en << CS35L41_GPIO_DIR_SHIFT);
-
-
- if (gpio1->valid)
- regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
- CS35L41_GPIO1_CTRL_MASK,
- gpio1->func << CS35L41_GPIO1_CTRL_SHIFT);
-
- if (gpio2->valid) {
- regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
- CS35L41_GPIO2_CTRL_MASK,
- gpio2->func << CS35L41_GPIO2_CTRL_SHIFT);
-
- switch (gpio2->func) {
- case CS35L41_INT_PUSH_PULL_LOW_GPIO2:
- case CS35L41_INT_OPEN_DRAIN_GPIO2:
- irq_pol = IRQF_TRIGGER_LOW;
- break;
- case CS35L41_INT_PUSH_PULL_HIGH_GPIO2:
- irq_pol = IRQF_TRIGGER_HIGH;
- break;
- default:
- break;
- }
- }
-
- return irq_pol;
-}
-
static int cs35l41_component_probe(struct snd_soc_component *component)
{
struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(component);
@@ -1367,7 +1324,7 @@ int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg *

cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap);

- irq_pol = cs35l41_gpio_config(cs35l41);
+ irq_pol = cs35l41_gpio_config(cs35l41->regmap, &cs35l41->hw_cfg);

/* Set interrupt masks for critical errors */
regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1,
--
2.35.1

2022-03-04 20:25:10

by Takashi Iwai

[permalink] [raw]
Subject: Re: [PATCH v2 00/20] Support external boost at CS35l41 ASoC driver

On Fri, 04 Mar 2022 16:07:01 +0100,
Lucas Tanure wrote:
>
> Move the support for CS35L41 external boost to its shared library
> for ASoC use.
> This move resulted in cs35l41_hda_reg_sequence being removed,
> and its steps were broken down into regmap writes or functions
> from the library. And hardware configuration struct was unified
> for its use in the shared lib.
> While at it, some minor bugs were found and fixed it.
>
> v2 changelog:
> - Instead of removing the log, playback actions will log the last regmap access.
> - Documentation patch with the correct subject line and fixed bug reported by Rob Herring on the
> provided example.
>
> Previous versions:
> v1: https://lkml.org/lkml/2022/3/3/759
>
> David Rhodes (2):
> ASoC: cs35l41: Fix GPIO2 configuration
> ASoC: cs35l41: Document CS35l41 External Boost
>
> Lucas Tanure (18):
> ASoC: cs35l41: Fix max number of TX channels
> ASoC: cs35l41: Fix DSP mbox start command and global enable order
> ASoC: cs35l41: Remove unnecessary param
> sound: cs35l41: Unify hardware configuration
> sound: cs35l41: Check hw_config before using it
> sound: cs35l41: Move cs35l41_gpio_config to shared lib
> hda: cs35l41: Fix I2S params comments
> hda: cs35l41: Always configure the DAI
> hda: cs35l41: Add Boost type flag
> hda: cs35l41: Put the device into safe mode for external boost
> hda: cs35l41: Mute the device before shutdown
> sound: cs35l41: Enable Internal Boost in shared lib
> hda: cs35l41: Move boost config to initialization code
> hda: cs35l41: Remove cs35l41_hda_reg_sequence struct
> hda: cs35l41: Reorganize log for playback actions
> hda: cs35l41: Handle all external boost setups the same way
> hda: cs35l41: Move external boost handling to lib for ASoC use
> ASoC: cs35l41: Support external boost

Through a quick glance, the code changes look OK in general.
But please correct the subject prefix. For non-ASoC patches (that
begin with either "hda" or "sound" in this patch set) should be with
"ALSA: hda: xxx" or such.

Also, although I respect the spirit of Haiku, the patch logs could be
a bit more verbose and descriptive, and the texts can be folded at the
right column. Some patch descriptions are too short, e.g. patch 15
doesn't mention about the new usleep_range() addition in the code.


thanks,

Takashi

2022-03-04 20:28:03

by Lucas Tanure

[permalink] [raw]
Subject: [PATCH v2 12/20] hda: cs35l41: Mute the device before shutdown

Mute the device before shutdown to avoid pops
and clicks all types of boost.

Signed-off-by: Lucas Tanure <[email protected]>
---
sound/pci/hda/cs35l41_hda.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
index 3b9515ed871d..b3cc7db3fc42 100644
--- a/sound/pci/hda/cs35l41_hda.c
+++ b/sound/pci/hda/cs35l41_hda.c
@@ -28,6 +28,11 @@ static const struct reg_sequence cs35l41_hda_config[] = {
{ CS35L41_PWR_CTRL2, 0x00000001 }, // AMP_EN = 1
};

+static const struct reg_sequence cs35l41_hda_mute[] = {
+ { CS35L41_AMP_GAIN_CTRL, 0x00000000 }, // AMP_GAIN_PCM 0.5 dB
+ { CS35L41_AMP_DIG_VOL_CTRL, 0x0000A678 }, // AMP_VOL_PCM Mute
+};
+
static const struct reg_sequence cs35l41_hda_start_bst[] = {
{ CS35L41_PWR_CTRL2, 0x00000021 }, // BST_EN = 10, AMP_EN = 1
{ CS35L41_PWR_CTRL1, 0x00000001, 3000}, // set GLOBAL_EN = 1
@@ -89,7 +94,6 @@ static const struct reg_sequence cs35l41_active_to_safe[] = {
{ 0x00000040, 0x00000055 },
{ 0x00000040, 0x000000AA },
{ 0x00007438, 0x00585941 },
- { CS35L41_AMP_DIG_VOL_CTRL, 0x0000A678 }, // AMP_VOL_PCM Mute
{ CS35L41_PWR_CTRL2, 0x00000000 }, // AMP_EN = 0
{ CS35L41_PWR_CTRL1, 0x00000000 },
{ 0x0000742C, 0x00000009, 2000 },
@@ -146,6 +150,7 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action)
ret = regmap_multi_reg_write(reg, reg_seq->prepare, reg_seq->num_prepare);
break;
case HDA_GEN_PCM_ACT_CLEANUP:
+ regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute));
if (reg_seq->cleanup)
ret = regmap_multi_reg_write(reg, reg_seq->cleanup, reg_seq->num_cleanup);
break;
--
2.35.1

2022-03-04 20:34:13

by Lucas Tanure

[permalink] [raw]
Subject: [PATCH v2 14/20] hda: cs35l41: Move boost config to initialization code

Boost configuration doesn't need to be written for
every new stream, so move it to the initialization code.

Signed-off-by: Lucas Tanure <[email protected]>
---
include/sound/cs35l41.h | 1 +
sound/pci/hda/cs35l41_hda.c | 13 ++++++++-----
2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h
index fbf38f32e36d..a8537bccedcf 100644
--- a/include/sound/cs35l41.h
+++ b/include/sound/cs35l41.h
@@ -661,6 +661,7 @@
#define CS35L41_GLOBAL_EN_SHIFT 0
#define CS35L41_BST_EN_MASK 0x0030
#define CS35L41_BST_EN_SHIFT 4
+#define CS35L41_BST_DIS_FET_OFF 0x00
#define CS35L41_BST_EN_DEFAULT 0x2
#define CS35L41_AMP_EN_SHIFT 0
#define CS35L41_AMP_EN_MASK 1
diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
index b3cc7db3fc42..3b8167d1ccc1 100644
--- a/sound/pci/hda/cs35l41_hda.c
+++ b/sound/pci/hda/cs35l41_hda.c
@@ -25,7 +25,6 @@ static const struct reg_sequence cs35l41_hda_config[] = {
{ CS35L41_DAC_PCM1_SRC, 0x00000008 }, // DACPCM1_SRC = ASPRX1
{ CS35L41_AMP_DIG_VOL_CTRL, 0x00000000 }, // AMP_VOL_PCM 0.0 dB
{ CS35L41_AMP_GAIN_CTRL, 0x00000084 }, // AMP_GAIN_PCM 4.5 dB
- { CS35L41_PWR_CTRL2, 0x00000001 }, // AMP_EN = 1
};

static const struct reg_sequence cs35l41_hda_mute[] = {
@@ -34,7 +33,6 @@ static const struct reg_sequence cs35l41_hda_mute[] = {
};

static const struct reg_sequence cs35l41_hda_start_bst[] = {
- { CS35L41_PWR_CTRL2, 0x00000021 }, // BST_EN = 10, AMP_EN = 1
{ CS35L41_PWR_CTRL1, 0x00000001, 3000}, // set GLOBAL_EN = 1
};

@@ -94,7 +92,6 @@ static const struct reg_sequence cs35l41_active_to_safe[] = {
{ 0x00000040, 0x00000055 },
{ 0x00000040, 0x000000AA },
{ 0x00007438, 0x00585941 },
- { CS35L41_PWR_CTRL2, 0x00000000 }, // AMP_EN = 0
{ CS35L41_PWR_CTRL1, 0x00000000 },
{ 0x0000742C, 0x00000009, 2000 },
{ 0x00007438, 0x00580941 },
@@ -144,6 +141,8 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action)
case HDA_GEN_PCM_ACT_OPEN:
ret = regmap_multi_reg_write(reg, cs35l41_hda_config,
ARRAY_SIZE(cs35l41_hda_config));
+ regmap_update_bits(reg, CS35L41_PWR_CTRL2,
+ CS35L41_AMP_EN_MASK, 1 << CS35L41_AMP_EN_SHIFT);
break;
case HDA_GEN_PCM_ACT_PREPARE:
if (reg_seq->prepare)
@@ -155,6 +154,8 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action)
ret = regmap_multi_reg_write(reg, reg_seq->cleanup, reg_seq->num_cleanup);
break;
case HDA_GEN_PCM_ACT_CLOSE:
+ regmap_update_bits(reg, CS35L41_PWR_CTRL2,
+ CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT);
if (reg_seq->close)
ret = regmap_multi_reg_write(reg, reg_seq->close, reg_seq->num_close);
break;
@@ -232,8 +233,10 @@ static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41)
cs35l41->reg_seq = &cs35l41_hda_reg_seq_ext_bst;
else
cs35l41->reg_seq = &cs35l41_hda_reg_seq_no_bst;
- ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41_reset_to_safe,
- ARRAY_SIZE(cs35l41_reset_to_safe));
+ regmap_multi_reg_write(cs35l41->regmap, cs35l41_reset_to_safe,
+ ARRAY_SIZE(cs35l41_reset_to_safe));
+ ret = regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, CS35L41_BST_EN_MASK,
+ CS35L41_BST_DIS_FET_OFF << CS35L41_BST_EN_SHIFT);
if (ret)
return ret;
break;
--
2.35.1

2022-03-04 20:51:55

by Lucas Tanure

[permalink] [raw]
Subject: [PATCH v2 17/20] hda: cs35l41: Handle all external boost setups the same way

Regmap sequences for external boost with or without the GPIO1
as VSPK switch are almost the same.
Unify them and use the GPIO1 VSPK switch to handle the difference.

Signed-off-by: Lucas Tanure <[email protected]>
---
sound/pci/hda/cs35l41_hda.c | 60 +++++++++++++++----------------------
1 file changed, 24 insertions(+), 36 deletions(-)

diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
index fda4af323c32..2ae074c8613e 100644
--- a/sound/pci/hda/cs35l41_hda.c
+++ b/sound/pci/hda/cs35l41_hda.c
@@ -32,33 +32,9 @@ static const struct reg_sequence cs35l41_hda_mute[] = {
{ CS35L41_AMP_DIG_VOL_CTRL, 0x0000A678 }, // AMP_VOL_PCM Mute
};

-// only on amps where GPIO1 is used to control ext. VSPK switch
-static const struct reg_sequence cs35l41_start_ext_vspk[] = {
+static const struct reg_sequence cs35l41_safe_to_reset[] = {
{ 0x00000040, 0x00000055 },
{ 0x00000040, 0x000000AA },
- { 0x00007438, 0x00585941 },
- { 0x00007414, 0x08C82222 },
- { 0x0000742C, 0x00000009 },
- { 0x00011008, 0x00008001 },
- { 0x0000742C, 0x0000000F },
- { 0x0000742C, 0x00000079 },
- { 0x00007438, 0x00585941 },
- { CS35L41_PWR_CTRL1, 0x00000001, 3000}, // set GLOBAL_EN = 1
- { 0x0000742C, 0x000000F9 },
- { 0x00007438, 0x00580941 },
- { 0x00000040, 0x000000CC },
- { 0x00000040, 0x00000033 },
-};
-
-//only on amps where GPIO1 is used to control ext. VSPK switch
-static const struct reg_sequence cs35l41_stop_ext_vspk[] = {
- { 0x00000040, 0x00000055 },
- { 0x00000040, 0x000000AA },
- { 0x00007438, 0x00585941 },
- { 0x00002014, 0x00000000, 3000}, // set GLOBAL_EN = 0
- { 0x0000742C, 0x00000009 },
- { 0x00007438, 0x00580941 },
- { 0x00011008, 0x00000001 },
{ 0x0000393C, 0x000000C0, 6000},
{ 0x0000393C, 0x00000000 },
{ 0x00007414, 0x00C82222 },
@@ -73,7 +49,7 @@ static const struct reg_sequence cs35l41_safe_to_active[] = {
{ 0x0000742C, 0x0000000F },
{ 0x0000742C, 0x00000079 },
{ 0x00007438, 0x00585941 },
- { CS35L41_PWR_CTRL1, 0x00000001, 2000 }, // GLOBAL_EN = 1
+ { CS35L41_PWR_CTRL1, 0x00000001, 3000 }, // GLOBAL_EN = 1
{ 0x0000742C, 0x000000F9 },
{ 0x00007438, 0x00580941 },
{ 0x00000040, 0x000000CC },
@@ -85,7 +61,7 @@ static const struct reg_sequence cs35l41_active_to_safe[] = {
{ 0x00000040, 0x000000AA },
{ 0x00007438, 0x00585941 },
{ CS35L41_PWR_CTRL1, 0x00000000 },
- { 0x0000742C, 0x00000009, 2000 },
+ { 0x0000742C, 0x00000009, 3000 },
{ 0x00007438, 0x00580941 },
{ 0x00000040, 0x000000CC },
{ 0x00000040, 0x00000033 },
@@ -101,6 +77,21 @@ static const struct reg_sequence cs35l41_reset_to_safe[] = {
{ 0x00000040, 0x00000033 },
};

+static bool cs35l41_hda_safe_reset(struct cs35l41_hda *cs35l41)
+{
+ switch (cs35l41->hw_cfg.bst_type) {
+ case CS35L41_EXT_BOOST:
+ regmap_write(cs35l41->regmap, CS35L41_GPIO1_CTRL1, 0x00000001);
+ regmap_multi_reg_write(cs35l41->regmap, cs35l41_safe_to_reset,
+ ARRAY_SIZE(cs35l41_safe_to_reset));
+ return true;
+ case CS35L41_EXT_BOOST_NO_VSPK_SWITCH:
+ return false;
+ default:
+ return true;
+ }
+};
+
static int cs35l41_hda_global_enable(struct cs35l41_hda *cs35l41, int enable)
{
int ret;
@@ -113,13 +104,6 @@ static int cs35l41_hda_global_enable(struct cs35l41_hda *cs35l41, int enable)
usleep_range(3000, 3100);
break;
case CS35L41_EXT_BOOST:
- if (enable)
- ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41_start_ext_vspk,
- ARRAY_SIZE(cs35l41_start_ext_vspk));
- else
- ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41_stop_ext_vspk,
- ARRAY_SIZE(cs35l41_stop_ext_vspk));
- break;
case CS35L41_EXT_BOOST_NO_VSPK_SWITCH:
if (enable)
ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41_safe_to_active,
@@ -147,6 +131,8 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action)
regmap_multi_reg_write(reg, cs35l41_hda_config, ARRAY_SIZE(cs35l41_hda_config));
ret = regmap_update_bits(reg, CS35L41_PWR_CTRL2,
CS35L41_AMP_EN_MASK, 1 << CS35L41_AMP_EN_SHIFT);
+ if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)
+ regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00008001);
break;
case HDA_GEN_PCM_ACT_PREPARE:
ret = cs35l41_hda_global_enable(cs35l41, 1);
@@ -158,6 +144,8 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action)
case HDA_GEN_PCM_ACT_CLOSE:
ret = regmap_update_bits(reg, CS35L41_PWR_CTRL2,
CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT);
+ if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)
+ regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00000001);
break;
default:
dev_warn(cs35l41->dev, "Playback action not supported: %d\n", action);
@@ -517,7 +505,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
return 0;

err:
- if (cs35l41->hw_cfg.bst_type != CS35L41_EXT_BOOST_NO_VSPK_SWITCH)
+ if (cs35l41_hda_safe_reset(cs35l41))
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
gpiod_put(cs35l41->reset_gpio);

@@ -531,7 +519,7 @@ void cs35l41_hda_remove(struct device *dev)

component_del(cs35l41->dev, &cs35l41_hda_comp_ops);

- if (cs35l41->hw_cfg.bst_type != CS35L41_EXT_BOOST_NO_VSPK_SWITCH)
+ if (cs35l41_hda_safe_reset(cs35l41))
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
gpiod_put(cs35l41->reset_gpio);
}
--
2.35.1

2022-03-08 10:17:31

by Mark Brown

[permalink] [raw]
Subject: Re: (subset) [PATCH v2 00/20] Support external boost at CS35l41 ASoC driver

On Fri, 4 Mar 2022 15:07:01 +0000, Lucas Tanure wrote:
> Move the support for CS35L41 external boost to its shared library
> for ASoC use.
> This move resulted in cs35l41_hda_reg_sequence being removed,
> and its steps were broken down into regmap writes or functions
> from the library. And hardware configuration struct was unified
> for its use in the shared lib.
> While at it, some minor bugs were found and fixed it.
>
> [...]

Applied to

https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-linus

Thanks!

[02/20] ASoC: cs35l41: Fix max number of TX channels
commit: 16639d39bdf577168d3fe34315917a94365c8d19
[03/20] ASoC: cs35l41: Fix DSP mbox start command and global enable order
commit: 5e02fb590e83684f63217f93a9cdeabd6a925f9c
[04/20] ASoC: cs35l41: Remove unnecessary param
(no commit info)

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark