2023-09-12 07:00:15

by wangweidong.a

[permalink] [raw]
Subject: [PATCH V2 0/5] ASoC: codecs: Add aw87390 amplifier driver

From: Weidong Wang <[email protected]>

The awinic aw87390 is a new high efficiency, low noise,
constant large volume, 6th Smart K audio amplifier.

Add a DT schema for describing awinic aw87390 audio amplifiers.
They are controlled using I2C.

v1 -> v2 : Added properties in awinic,aw88395 file
Remove fade-enable because the functionality is
duplicated in the aw88395 driver
Modify dev_err_probe usage
Delete unused header files
Change the i2c driver name
Modify the way a function returns a value

Weidong Wang (5):
ASoC: dt-bindings: Adds properties to "awinic,aw88395"
ASoC: dt-bindings: Add schema for "awinic,aw87390"
ASoC: codecs: Add code for bin parsing compatible with aw87390
ASoC: codecs: Change the aw88261 variable name and i2c driver name
ASoC: codecs: Add aw87390 amplifier driver

.../bindings/sound/awinic,aw87390.yaml | 58 +++
.../bindings/sound/awinic,aw88395.yaml | 19 +
sound/soc/codecs/Kconfig | 15 +-
sound/soc/codecs/Makefile | 2 +
sound/soc/codecs/aw87390.c | 462 ++++++++++++++++++
sound/soc/codecs/aw87390.h | 85 ++++
sound/soc/codecs/aw88261.c | 23 +-
sound/soc/codecs/aw88261.h | 2 +-
sound/soc/codecs/aw88395/aw88395.c | 9 +-
sound/soc/codecs/aw88395/aw88395.h | 2 +-
sound/soc/codecs/aw88395/aw88395_device.c | 47 +-
sound/soc/codecs/aw88395/aw88395_device.h | 6 +-
sound/soc/codecs/aw88395/aw88395_lib.c | 23 +-
sound/soc/codecs/aw88395/aw88395_reg.h | 1 +
14 files changed, 685 insertions(+), 69 deletions(-)
create mode 100644 Documentation/devicetree/bindings/sound/awinic,aw87390.yaml
create mode 100644 sound/soc/codecs/aw87390.c
create mode 100644 sound/soc/codecs/aw87390.h


base-commit: 0bb80ecc33a8fb5a682236443c1e740d5c917d1d
--
2.41.0


2023-09-12 07:00:19

by wangweidong.a

[permalink] [raw]
Subject: [PATCH V2 2/5] ASoC: dt-bindings: Add schema for "awinic,aw87390"

From: Weidong Wang <[email protected]>

Add a DT schema for describing awinic aw87390 audio amplifiers.
They are controlled using I2C.

Signed-off-by: Weidong Wang <[email protected]>
---
.../bindings/sound/awinic,aw87390.yaml | 58 +++++++++++++++++++
1 file changed, 58 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/awinic,aw87390.yaml

diff --git a/Documentation/devicetree/bindings/sound/awinic,aw87390.yaml b/Documentation/devicetree/bindings/sound/awinic,aw87390.yaml
new file mode 100644
index 000000000000..ba9d8767c5d5
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/awinic,aw87390.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/awinic,aw87390.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Awinic Aw87390 Audio Amplifier
+
+maintainers:
+ - Weidong Wang <[email protected]>
+
+description:
+ The awinic aw87390 is specifically designed to improve
+ the musical output dynamic range, enhance the overall
+ sound quallity, which is a new high efficiency, low
+ noise, constant large volume, 6th Smart K audio amplifier.
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ const: awinic,aw87390
+
+ reg:
+ maxItems: 1
+
+ "#sound-dai-cells":
+ const: 0
+
+ awinic,audio-channel:
+ description:
+ It is used to distinguish multiple PA devices, so that different
+ configurations can be loaded to different PA devices
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 7
+
+required:
+ - compatible
+ - reg
+ - "#sound-dai-cells"
+ - awinic,audio-channel
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ audio-codec@58 {
+ compatible = "awinic,aw87390";
+ reg = <0x58>;
+ #sound-dai-cells = <0>;
+ awinic,audio-channel = <0>;
+ };
+ };
--
2.41.0

2023-09-12 07:00:35

by wangweidong.a

[permalink] [raw]
Subject: [PATCH V2 4/5] ASoC: codecs: Change the aw88261 variable name and i2c driver name

From: Weidong Wang <[email protected]>

Change "sound-channel" to "awinic,audio-channel"
Change "aw88261_smartpa" to "aw88261"

Signed-off-by: Weidong Wang <[email protected]>
---
sound/soc/codecs/aw88261.c | 23 ++++++++++++-----------
sound/soc/codecs/aw88261.h | 2 +-
2 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/sound/soc/codecs/aw88261.c b/sound/soc/codecs/aw88261.c
index a697b5006b45..d01c3ea1bb7d 100644
--- a/sound/soc/codecs/aw88261.c
+++ b/sound/soc/codecs/aw88261.c
@@ -477,7 +477,7 @@ static int aw88261_dev_reg_update(struct aw88261 *aw88261,
return ret;
}

-static char *aw88261_dev_get_prof_name(struct aw_device *aw_dev, int index)
+static int aw88261_dev_get_prof_name(struct aw_device *aw_dev, int index, char **prof_name)
{
struct aw_prof_info *prof_info = &aw_dev->prof_info;
struct aw_prof_desc *prof_desc;
@@ -485,12 +485,14 @@ static char *aw88261_dev_get_prof_name(struct aw_device *aw_dev, int index)
if ((index >= aw_dev->prof_info.count) || (index < 0)) {
dev_err(aw_dev->dev, "index[%d] overflow count[%d]",
index, aw_dev->prof_info.count);
- return NULL;
+ return -EINVAL;
}

prof_desc = &aw_dev->prof_info.prof_desc[index];

- return prof_info->prof_name_list[prof_desc->id];
+ *prof_name = prof_info->prof_name_list[prof_desc->id];
+
+ return 0;
}

static int aw88261_dev_get_prof_data(struct aw_device *aw_dev, int index,
@@ -515,8 +517,8 @@ static int aw88261_dev_fw_update(struct aw88261 *aw88261)
char *prof_name;
int ret;

- prof_name = aw88261_dev_get_prof_name(aw_dev, aw_dev->prof_index);
- if (!prof_name) {
+ ret = aw88261_dev_get_prof_name(aw_dev, aw_dev->prof_index, &prof_name);
+ if (ret) {
dev_err(aw_dev->dev, "get prof name failed");
return -EINVAL;
}
@@ -818,9 +820,8 @@ static int aw88261_profile_info(struct snd_kcontrol *kcontrol,
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct aw88261 *aw88261 = snd_soc_component_get_drvdata(codec);
- const char *prof_name;
- char *name;
- int count;
+ char *prof_name, *name;
+ int count, ret;

uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -839,8 +840,8 @@ static int aw88261_profile_info(struct snd_kcontrol *kcontrol,
name = uinfo->value.enumerated.name;
count = uinfo->value.enumerated.item;

- prof_name = aw88261_dev_get_prof_name(aw88261->aw_pa, count);
- if (!prof_name) {
+ ret = aw88261_dev_get_prof_name(aw88261->aw_pa, count, &prof_name);
+ if (ret) {
strscpy(uinfo->value.enumerated.name, "null",
strlen("null") + 1);
return 0;
@@ -1189,7 +1190,7 @@ static void aw88261_parse_channel_dt(struct aw88261 *aw88261)
u32 channel_value = AW88261_DEV_DEFAULT_CH;
u32 sync_enable = false;

- of_property_read_u32(np, "sound-channel", &channel_value);
+ of_property_read_u32(np, "awinic,audio-channel", &channel_value);
of_property_read_u32(np, "sync-flag", &sync_enable);

aw_dev->channel = channel_value;
diff --git a/sound/soc/codecs/aw88261.h b/sound/soc/codecs/aw88261.h
index 4f3dbf438510..bd0841fa9b77 100644
--- a/sound/soc/codecs/aw88261.h
+++ b/sound/soc/codecs/aw88261.h
@@ -370,7 +370,7 @@
#define AW88261_START_RETRIES (5)
#define AW88261_START_WORK_DELAY_MS (0)

-#define AW88261_I2C_NAME "aw88261_smartpa"
+#define AW88261_I2C_NAME "aw88261"

#define AW88261_RATES (SNDRV_PCM_RATE_8000_48000 | \
SNDRV_PCM_RATE_96000)
--
2.41.0

2023-09-12 07:00:35

by wangweidong.a

[permalink] [raw]
Subject: [PATCH V2 5/5] ASoC: codecs: Add aw87390 amplifier driver

From: Weidong Wang <[email protected]>

Add i2c and amplifier registration for aw87390 and
their associated operation functions.

Signed-off-by: Weidong Wang <[email protected]>
---
sound/soc/codecs/Kconfig | 15 +-
sound/soc/codecs/Makefile | 2 +
sound/soc/codecs/aw87390.c | 462 +++++++++++++++++++++++++++++++++++++
sound/soc/codecs/aw87390.h | 85 +++++++
4 files changed, 562 insertions(+), 2 deletions(-)
create mode 100644 sound/soc/codecs/aw87390.c
create mode 100644 sound/soc/codecs/aw87390.h

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index f1e1dbc509f6..8c101919259f 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -54,6 +54,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_ALC5632
imply SND_SOC_AUDIO_IIO_AUX
imply SND_SOC_AW8738
+ imply SND_SOC_AW87390
imply SND_SOC_AW88395
imply SND_SOC_AW88261
imply SND_SOC_BT_SCO
@@ -638,12 +639,12 @@ config SND_SOC_AW8738
operation mode using the Awinic-specific one-wire pulse control.

config SND_SOC_AW88395_LIB
+ select CRC8
tristate

config SND_SOC_AW88395
tristate "Soc Audio for awinic aw88395"
depends on I2C
- select CRC8
select CRC32
select REGMAP_I2C
select GPIOLIB
@@ -657,7 +658,6 @@ config SND_SOC_AW88395
config SND_SOC_AW88261
tristate "Soc Audio for awinic aw88261"
depends on I2C
- select CRC8
select REGMAP_I2C
select GPIOLIB
select SND_SOC_AW88395_LIB
@@ -668,6 +668,17 @@ config SND_SOC_AW88261
boost converter can be adjusted smartly according to
the input amplitude.

+config SND_SOC_AW87390
+ tristate "Soc Audio for awinic aw87390"
+ depends on I2C
+ select REGMAP_I2C
+ select SND_SOC_AW88395_LIB
+ help
+ The awinic aw87390 is specifically designed to improve
+ the musical output dynamic range, enhance the overall
+ sound quallity, which is a new high efficiency, low
+ noise, constant large volume, 6th Smart K audio amplifier.
+
config SND_SOC_BD28623
tristate "ROHM BD28623 CODEC"
help
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index a87e56938ce5..60df97b67c01 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -47,6 +47,7 @@ snd-soc-ak5558-objs := ak5558.o
snd-soc-arizona-objs := arizona.o arizona-jack.o
snd-soc-audio-iio-aux-objs := audio-iio-aux.o
snd-soc-aw8738-objs := aw8738.o
+snd-soc-aw87390-objs := aw87390.o
snd-soc-aw88395-lib-objs := aw88395/aw88395_lib.o
snd-soc-aw88395-objs := aw88395/aw88395.o \
aw88395/aw88395_device.o
@@ -434,6 +435,7 @@ obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o
obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o
obj-$(CONFIG_SND_SOC_AUDIO_IIO_AUX) += snd-soc-audio-iio-aux.o
obj-$(CONFIG_SND_SOC_AW8738) += snd-soc-aw8738.o
+obj-$(CONFIG_SND_SOC_AW87390) += snd-soc-aw87390.o
obj-$(CONFIG_SND_SOC_AW88395_LIB) += snd-soc-aw88395-lib.o
obj-$(CONFIG_SND_SOC_AW88395) +=snd-soc-aw88395.o
obj-$(CONFIG_SND_SOC_AW88261) +=snd-soc-aw88261.o
diff --git a/sound/soc/codecs/aw87390.c b/sound/soc/codecs/aw87390.c
new file mode 100644
index 000000000000..8efae3b73eea
--- /dev/null
+++ b/sound/soc/codecs/aw87390.c
@@ -0,0 +1,462 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// aw87390.c -- AW87390 ALSA SoC Audio driver
+//
+// Copyright (c) 2023 awinic Technology CO., LTD
+//
+// Author: Weidong Wang <[email protected]>
+//
+
+#include <linux/i2c.h>
+#include <linux/firmware.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+#include "aw87390.h"
+#include "aw88395/aw88395_data_type.h"
+#include "aw88395/aw88395_device.h"
+
+static const struct regmap_config aw87390_remap_config = {
+ .val_bits = 8,
+ .reg_bits = 8,
+ .max_register = AW87390_REG_MAX,
+ .reg_format_endian = REGMAP_ENDIAN_LITTLE,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+};
+
+static int aw87390_dev_reg_update(struct aw_device *aw_dev,
+ unsigned char *data, unsigned int len)
+{
+ int i, ret;
+
+ if (!data) {
+ dev_err(aw_dev->dev, "data is NULL\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < len; i = i + 2) {
+ if (data[i] == AW87390_DELAY_REG_ADDR) {
+ usleep_range(data[i + 1] * AW87390_REG_DELAY_TIME,
+ data[i + 1] * AW87390_REG_DELAY_TIME + 10);
+ continue;
+ }
+ ret = regmap_write(aw_dev->regmap, data[i], data[i + 1]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int aw87390_dev_get_prof_name(struct aw_device *aw_dev, int index, char **prof_name)
+{
+ struct aw_prof_info *prof_info = &aw_dev->prof_info;
+ struct aw_prof_desc *prof_desc;
+
+ if ((index >= aw_dev->prof_info.count) || (index < 0)) {
+ dev_err(aw_dev->dev, "index[%d] overflow count[%d]\n",
+ index, aw_dev->prof_info.count);
+ return -EINVAL;
+ }
+
+ prof_desc = &aw_dev->prof_info.prof_desc[index];
+
+ *prof_name = prof_info->prof_name_list[prof_desc->id];
+
+ return 0;
+}
+
+static int aw87390_dev_get_prof_data(struct aw_device *aw_dev, int index,
+ struct aw_prof_desc **prof_desc)
+{
+ if ((index >= aw_dev->prof_info.count) || (index < 0)) {
+ dev_err(aw_dev->dev, "%s: index[%d] overflow count[%d]\n",
+ __func__, index, aw_dev->prof_info.count);
+ return -EINVAL;
+ }
+
+ *prof_desc = &aw_dev->prof_info.prof_desc[index];
+
+ return 0;
+}
+
+static int aw87390_dev_fw_update(struct aw_device *aw_dev)
+{
+ struct aw_prof_desc *prof_index_desc;
+ struct aw_sec_data_desc *sec_desc;
+ char *prof_name;
+ int ret;
+
+ ret = aw87390_dev_get_prof_name(aw_dev, aw_dev->prof_index, &prof_name);
+ if (ret) {
+ dev_err(aw_dev->dev, "get prof name failed\n");
+ return -EINVAL;
+ }
+
+ dev_dbg(aw_dev->dev, "start update %s", prof_name);
+
+ ret = aw87390_dev_get_prof_data(aw_dev, aw_dev->prof_index, &prof_index_desc);
+ if (ret) {
+ dev_err(aw_dev->dev, "aw87390_dev_get_prof_data failed\n");
+ return ret;
+ }
+
+ /* update reg */
+ sec_desc = prof_index_desc->sec_desc;
+ ret = aw87390_dev_reg_update(aw_dev, sec_desc[AW88395_DATA_TYPE_REG].data,
+ sec_desc[AW88395_DATA_TYPE_REG].len);
+ if (ret) {
+ dev_err(aw_dev->dev, "update reg failed\n");
+ return ret;
+ }
+
+ aw_dev->prof_cur = aw_dev->prof_index;
+
+ return ret;
+}
+
+static int aw87390_power_off(struct aw_device *aw_dev)
+{
+ int ret;
+
+ if (aw_dev->status == AW87390_DEV_PW_OFF) {
+ dev_info(aw_dev->dev, "already power off\n");
+ return 0;
+ }
+
+ ret = regmap_write(aw_dev->regmap, AW87390_SYSCTRL_REG, AW87390_POWER_DOWN_VALUE);
+ if (ret)
+ return ret;
+ aw_dev->status = AW87390_DEV_PW_OFF;
+
+ return ret;
+}
+
+static int aw87390_power_on(struct aw_device *aw_dev)
+{
+ int ret;
+
+ if (aw_dev->status == AW87390_DEV_PW_ON) {
+ dev_info(aw_dev->dev, "already power on\n");
+ return 0;
+ }
+
+ if (!aw_dev->fw_status) {
+ dev_err(aw_dev->dev, "fw not load\n");
+ return -EINVAL;
+ }
+
+ ret = regmap_write(aw_dev->regmap, AW87390_SYSCTRL_REG, AW87390_POWER_DOWN_VALUE);
+ if (ret)
+ return ret;
+
+ ret = aw87390_dev_fw_update(aw_dev);
+ if (ret) {
+ dev_err(aw_dev->dev, "%s load profile failed\n", __func__);
+ return ret;
+ }
+ aw_dev->status = AW87390_DEV_PW_ON;
+
+ return ret;
+}
+
+static int aw87390_dev_set_profile_index(struct aw_device *aw_dev, int index)
+{
+ if ((index >= aw_dev->prof_info.count) || (index < 0))
+ return -EINVAL;
+
+ if (aw_dev->prof_index == index)
+ return -EPERM;
+
+ aw_dev->prof_index = index;
+
+ return 0;
+}
+
+static int aw87390_profile_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct aw87390 *aw87390 = snd_soc_component_get_drvdata(codec);
+ char *prof_name, *name;
+ int count, ret;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+
+ count = aw87390->aw_pa->prof_info.count;
+ if (count <= 0) {
+ uinfo->value.enumerated.items = 0;
+ return 0;
+ }
+
+ uinfo->value.enumerated.items = count;
+
+ if (uinfo->value.enumerated.item >= count)
+ uinfo->value.enumerated.item = count - 1;
+
+ name = uinfo->value.enumerated.name;
+ count = uinfo->value.enumerated.item;
+
+ ret = aw87390_dev_get_prof_name(aw87390->aw_pa, count, &prof_name);
+ if (ret) {
+ strscpy(uinfo->value.enumerated.name, "null",
+ strlen("null") + 1);
+ return 0;
+ }
+
+ strscpy(name, prof_name, sizeof(uinfo->value.enumerated.name));
+
+ return 0;
+}
+
+static int aw87390_profile_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct aw87390 *aw87390 = snd_soc_component_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = aw87390->aw_pa->prof_index;
+
+ return 0;
+}
+
+static int aw87390_profile_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct aw87390 *aw87390 = snd_soc_component_get_drvdata(codec);
+ int ret;
+
+ mutex_lock(&aw87390->lock);
+ ret = aw87390_dev_set_profile_index(aw87390->aw_pa, ucontrol->value.integer.value[0]);
+ if (ret) {
+ dev_dbg(codec->dev, "profile index does not change\n");
+ mutex_unlock(&aw87390->lock);
+ return 0;
+ }
+
+ if (aw87390->aw_pa->status == AW87390_DEV_PW_ON) {
+ aw87390_power_off(aw87390->aw_pa);
+ aw87390_power_on(aw87390->aw_pa);
+ }
+
+ mutex_unlock(&aw87390->lock);
+
+ return 1;
+}
+
+static const struct snd_kcontrol_new aw87390_controls[] = {
+ AW87390_PROFILE_EXT("AW87390 Profile Set", aw87390_profile_info,
+ aw87390_profile_get, aw87390_profile_set),
+};
+
+static int aw87390_request_firmware_file(struct aw87390 *aw87390)
+{
+ const struct firmware *cont = NULL;
+ int ret;
+
+ aw87390->aw_pa->fw_status = AW87390_DEV_FW_FAILED;
+
+ ret = request_firmware(&cont, AW87390_ACF_FILE, aw87390->aw_pa->dev);
+ if (ret)
+ return dev_err_probe(aw87390->aw_pa->dev, ret,
+ "load [%s] failed!\n", AW87390_ACF_FILE);
+
+ dev_dbg(aw87390->aw_pa->dev, "loaded %s - size: %zu\n",
+ AW87390_ACF_FILE, cont ? cont->size : 0);
+
+ aw87390->aw_cfg = devm_kzalloc(aw87390->aw_pa->dev, cont->size + sizeof(int), GFP_KERNEL);
+ if (!aw87390->aw_cfg) {
+ release_firmware(cont);
+ return -ENOMEM;
+ }
+
+ aw87390->aw_cfg->len = (int)cont->size;
+ memcpy(aw87390->aw_cfg->data, cont->data, cont->size);
+ release_firmware(cont);
+
+ ret = aw88395_dev_load_acf_check(aw87390->aw_pa, aw87390->aw_cfg);
+ if (ret) {
+ dev_err(aw87390->aw_pa->dev, "load [%s] failed !\n", AW87390_ACF_FILE);
+ return ret;
+ }
+
+ mutex_lock(&aw87390->lock);
+
+ ret = aw88395_dev_cfg_load(aw87390->aw_pa, aw87390->aw_cfg);
+ if (ret)
+ dev_err(aw87390->aw_pa->dev, "aw_dev acf parse failed\n");
+
+ mutex_unlock(&aw87390->lock);
+
+ return ret;
+}
+
+static int aw87390_drv_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+ struct aw87390 *aw87390 = snd_soc_component_get_drvdata(component);
+ struct aw_device *aw_dev = aw87390->aw_pa;
+ int ret;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ ret = aw87390_power_on(aw_dev);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ ret = aw87390_power_off(aw_dev);
+ break;
+ default:
+ dev_err(aw_dev->dev, "%s: invalid event %d\n", __func__, event);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static const struct snd_soc_dapm_widget aw87390_dapm_widgets[] = {
+ SND_SOC_DAPM_INPUT("IN"),
+ SND_SOC_DAPM_PGA_E("SPK PA", SND_SOC_NOPM, 0, 0, NULL, 0, aw87390_drv_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_OUTPUT("OUT"),
+};
+
+static const struct snd_soc_dapm_route aw87390_dapm_routes[] = {
+ { "SPK PA", NULL, "IN" },
+ { "OUT", NULL, "SPK PA" },
+};
+
+static int aw87390_codec_probe(struct snd_soc_component *component)
+{
+ struct aw87390 *aw87390 = snd_soc_component_get_drvdata(component);
+ int ret;
+
+ ret = aw87390_request_firmware_file(aw87390);
+ if (ret)
+ return dev_err_probe(aw87390->aw_pa->dev, ret,
+ "aw87390_request_firmware_file failed\n");
+
+ return 0;
+}
+
+static const struct snd_soc_component_driver soc_codec_dev_aw87390 = {
+ .probe = aw87390_codec_probe,
+ .dapm_widgets = aw87390_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(aw87390_dapm_widgets),
+ .dapm_routes = aw87390_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(aw87390_dapm_routes),
+ .controls = aw87390_controls,
+ .num_controls = ARRAY_SIZE(aw87390_controls),
+};
+
+static void aw87390_parse_channel_dt(struct aw87390 *aw87390)
+{
+ struct aw_device *aw_dev = aw87390->aw_pa;
+ struct device_node *np = aw_dev->dev->of_node;
+ u32 channel_value = AW87390_DEV_DEFAULT_CH;
+
+ of_property_read_u32(np, "awinic,audio-channel", &channel_value);
+
+ aw_dev->channel = channel_value;
+}
+
+static int aw87390_init(struct aw87390 **aw87390, struct i2c_client *i2c, struct regmap *regmap)
+{
+ struct aw_device *aw_dev;
+ unsigned int chip_id;
+ int ret;
+
+ /* read chip id */
+ ret = regmap_read(regmap, AW87390_ID_REG, &chip_id);
+ if (ret) {
+ dev_err(&i2c->dev, "%s read chipid error. ret = %d\n", __func__, ret);
+ return ret;
+ }
+
+ if (chip_id != AW87390_CHIP_ID) {
+ dev_err(&i2c->dev, "unsupported device\n");
+ return -ENXIO;
+ }
+
+ dev_info(&i2c->dev, "chip id = 0x%x\n", chip_id);
+
+ aw_dev = devm_kzalloc(&i2c->dev, sizeof(*aw_dev), GFP_KERNEL);
+ if (!aw_dev)
+ return -ENOMEM;
+
+ (*aw87390)->aw_pa = aw_dev;
+ aw_dev->i2c = i2c;
+ aw_dev->regmap = regmap;
+ aw_dev->dev = &i2c->dev;
+ aw_dev->chip_id = AW87390_CHIP_ID;
+ aw_dev->acf = NULL;
+ aw_dev->prof_info.prof_desc = NULL;
+ aw_dev->prof_info.count = 0;
+ aw_dev->prof_info.prof_type = AW88395_DEV_NONE_TYPE_ID;
+ aw_dev->channel = AW87390_DEV_DEFAULT_CH;
+ aw_dev->fw_status = AW87390_DEV_FW_FAILED;
+ aw_dev->prof_index = AW87390_INIT_PROFILE;
+ aw_dev->status = AW87390_DEV_PW_OFF;
+
+ aw87390_parse_channel_dt(*aw87390);
+
+ return ret;
+}
+
+static int aw87390_i2c_probe(struct i2c_client *i2c)
+{
+ struct aw87390 *aw87390;
+ int ret;
+
+ ret = i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C);
+ if (!ret)
+ return dev_err_probe(&i2c->dev, -ENXIO, "check_functionality failed\n");
+
+ aw87390 = devm_kzalloc(&i2c->dev, sizeof(*aw87390), GFP_KERNEL);
+ if (!aw87390)
+ return -ENOMEM;
+
+ mutex_init(&aw87390->lock);
+
+ i2c_set_clientdata(i2c, aw87390);
+
+ aw87390->regmap = devm_regmap_init_i2c(i2c, &aw87390_remap_config);
+ if (IS_ERR(aw87390->regmap))
+ return dev_err_probe(&i2c->dev, PTR_ERR(aw87390->regmap),
+ "failed to init regmap\n");
+
+ /* aw pa init */
+ ret = aw87390_init(&aw87390, i2c, aw87390->regmap);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(aw87390->regmap, AW87390_ID_REG, AW87390_SOFT_RESET_VALUE);
+ if (ret)
+ return ret;
+
+ ret = devm_snd_soc_register_component(&i2c->dev,
+ &soc_codec_dev_aw87390, NULL, 0);
+ if (ret)
+ dev_err(&i2c->dev, "failed to register aw87390: %d\n", ret);
+
+ return ret;
+}
+
+static const struct i2c_device_id aw87390_i2c_id[] = {
+ { AW87390_I2C_NAME, 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, aw87390_i2c_id);
+
+static struct i2c_driver aw87390_i2c_driver = {
+ .driver = {
+ .name = AW87390_I2C_NAME,
+ },
+ .probe = aw87390_i2c_probe,
+ .id_table = aw87390_i2c_id,
+};
+module_i2c_driver(aw87390_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC AW87390 PA Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/aw87390.h b/sound/soc/codecs/aw87390.h
new file mode 100644
index 000000000000..54c268c18e72
--- /dev/null
+++ b/sound/soc/codecs/aw87390.h
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// aw87390.h -- aw87390 ALSA SoC Audio driver
+//
+// Copyright (c) 2023 awinic Technology CO., LTD
+//
+// Author: Weidong Wang <[email protected]>
+//
+
+#ifndef __AW87390_H__
+#define __AW87390_H__
+
+#define AW87390_ID_REG (0x00)
+#define AW87390_SYSCTRL_REG (0x01)
+#define AW87390_MDCTRL_REG (0x02)
+#define AW87390_CPOVP_REG (0x03)
+#define AW87390_CPP_REG (0x04)
+#define AW87390_PAG_REG (0x05)
+#define AW87390_AGC3P_REG (0x06)
+#define AW87390_AGC3PA_REG (0x07)
+#define AW87390_AGC2P_REG (0x08)
+#define AW87390_AGC2PA_REG (0x09)
+#define AW87390_AGC1PA_REG (0x0A)
+#define AW87390_SYSST_REG (0x59)
+#define AW87390_SYSINT_REG (0x60)
+#define AW87390_DFT_SYSCTRL_REG (0x61)
+#define AW87390_DFT_MDCTRL_REG (0x62)
+#define AW87390_DFT_CPADP_REG (0x63)
+#define AW87390_DFT_AGCPA_REG (0x64)
+#define AW87390_DFT_POFR_REG (0x65)
+#define AW87390_DFT_OC_REG (0x66)
+#define AW87390_DFT_ADP1_REG (0x67)
+#define AW87390_DFT_REF_REG (0x68)
+#define AW87390_DFT_LDO_REG (0x69)
+#define AW87390_ADP1_REG (0x70)
+#define AW87390_ADP2_REG (0x71)
+#define AW87390_NG1_REG (0x72)
+#define AW87390_NG2_REG (0x73)
+#define AW87390_NG3_REG (0x74)
+#define AW87390_CP_REG (0x75)
+#define AW87390_AB_REG (0x76)
+#define AW87390_TEST_REG (0x77)
+#define AW87390_ENCR_REG (0x78)
+#define AW87390_DELAY_REG_ADDR (0xFE)
+
+#define AW87390_SOFT_RESET_VALUE (0xAA)
+#define AW87390_POWER_DOWN_VALUE (0x00)
+#define AW87390_REG_MAX (0xFF)
+#define AW87390_DEV_DEFAULT_CH (0)
+#define AW87390_INIT_PROFILE (0)
+#define AW87390_REG_DELAY_TIME (1000)
+#define AW87390_I2C_NAME "aw87390"
+#define AW87390_ACF_FILE "aw87390_acf.bin"
+
+#define AW87390_PROFILE_EXT(xname, profile_info, profile_get, profile_set) \
+{ \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = xname, \
+ .info = profile_info, \
+ .get = profile_get, \
+ .put = profile_set, \
+}
+
+enum aw87390_id {
+ AW87390_CHIP_ID = 0x76,
+};
+
+enum {
+ AW87390_DEV_FW_FAILED = 0,
+ AW87390_DEV_FW_OK,
+};
+
+enum {
+ AW87390_DEV_PW_OFF = 0,
+ AW87390_DEV_PW_ON,
+};
+
+struct aw87390 {
+ struct aw_device *aw_pa;
+ struct mutex lock;
+ struct regmap *regmap;
+ struct aw_container *aw_cfg;
+};
+
+#endif
--
2.41.0

2023-09-12 07:00:40

by wangweidong.a

[permalink] [raw]
Subject: [PATCH V2 1/5] ASoC: dt-bindings: Adds properties to "awinic,aw88395"

From: Weidong Wang <[email protected]>

Adds properties to "awinic,aw88395" to make files more complete

Signed-off-by: Weidong Wang <[email protected]>
---
.../bindings/sound/awinic,aw88395.yaml | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml b/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml
index 4051c2538caf..4965aa4a5370 100644
--- a/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml
+++ b/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml
@@ -32,11 +32,28 @@ properties:
reset-gpios:
maxItems: 1

+ awinic,audio-channel:
+ description:
+ It is used to distinguish multiple PA devices, so that different
+ configurations can be loaded to different PA devices
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 7
+
+ awinic,sync-flag:
+ description:
+ Flag bit used to keep the phase synchronized in the case of multiple PA
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 1
+
required:
- compatible
- reg
- '#sound-dai-cells'
- reset-gpios
+ - awinic,audio-channel
+ - awinic,sync-flag

unevaluatedProperties: false

@@ -51,5 +68,7 @@ examples:
reg = <0x34>;
#sound-dai-cells = <0>;
reset-gpios = <&gpio 10 GPIO_ACTIVE_LOW>;
+ awinic,audio-channel = <0>;
+ awinic,sync-flag = <0>;
};
};
--
2.41.0

2023-09-12 07:01:10

by wangweidong.a

[permalink] [raw]
Subject: [PATCH V2 3/5] ASoC: codecs: Add code for bin parsing compatible with aw87390

From: Weidong Wang <[email protected]>

Add aw87390 compatible code to the aw88395_lib.c file
so that it can parse aw87390's bin file and function
return method

Signed-off-by: Weidong Wang <[email protected]>
---
sound/soc/codecs/aw88395/aw88395.c | 9 ++---
sound/soc/codecs/aw88395/aw88395.h | 2 +-
sound/soc/codecs/aw88395/aw88395_device.c | 47 ++++++-----------------
sound/soc/codecs/aw88395/aw88395_device.h | 6 +--
sound/soc/codecs/aw88395/aw88395_lib.c | 23 ++++++-----
sound/soc/codecs/aw88395/aw88395_reg.h | 1 +
6 files changed, 33 insertions(+), 55 deletions(-)

diff --git a/sound/soc/codecs/aw88395/aw88395.c b/sound/soc/codecs/aw88395/aw88395.c
index 9dcd75dd799a..77227c8f01f6 100644
--- a/sound/soc/codecs/aw88395/aw88395.c
+++ b/sound/soc/codecs/aw88395/aw88395.c
@@ -175,9 +175,8 @@ static int aw88395_profile_info(struct snd_kcontrol *kcontrol,
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct aw88395 *aw88395 = snd_soc_component_get_drvdata(codec);
- const char *prof_name;
- char *name;
- int count;
+ char *prof_name, *name;
+ int count, ret;

uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -196,8 +195,8 @@ static int aw88395_profile_info(struct snd_kcontrol *kcontrol,
name = uinfo->value.enumerated.name;
count = uinfo->value.enumerated.item;

- prof_name = aw88395_dev_get_prof_name(aw88395->aw_pa, count);
- if (!prof_name) {
+ ret = aw88395_dev_get_prof_name(aw88395->aw_pa, count, &prof_name);
+ if (ret) {
strscpy(uinfo->value.enumerated.name, "null",
strlen("null") + 1);
return 0;
diff --git a/sound/soc/codecs/aw88395/aw88395.h b/sound/soc/codecs/aw88395/aw88395.h
index 8036ba27f68d..c2a4f0cb8cd5 100644
--- a/sound/soc/codecs/aw88395/aw88395.h
+++ b/sound/soc/codecs/aw88395/aw88395.h
@@ -16,7 +16,7 @@

#define AW88395_DSP_16_DATA_MASK (0x0000ffff)

-#define AW88395_I2C_NAME "aw88395_smartpa"
+#define AW88395_I2C_NAME "aw88395"

#define AW88395_RATES (SNDRV_PCM_RATE_8000_48000 | \
SNDRV_PCM_RATE_96000)
diff --git a/sound/soc/codecs/aw88395/aw88395_device.c b/sound/soc/codecs/aw88395/aw88395_device.c
index 33eda3741464..fd1f67d5f22f 100644
--- a/sound/soc/codecs/aw88395/aw88395_device.c
+++ b/sound/soc/codecs/aw88395/aw88395_device.c
@@ -297,9 +297,6 @@ static void aw_dev_fade_in(struct aw_device *aw_dev)
int fade_step = aw_dev->fade_step;
int i;

- if (!aw_dev->fade_en)
- return;
-
if (fade_step == 0 || aw_dev->fade_in_time == 0) {
aw_dev_set_volume(aw_dev, fade_in_vol);
return;
@@ -320,9 +317,6 @@ static void aw_dev_fade_out(struct aw_device *aw_dev)
int fade_step = aw_dev->fade_step;
int i;

- if (!aw_dev->fade_en)
- return;
-
if (fade_step == 0 || aw_dev->fade_out_time == 0) {
aw_dev_set_volume(aw_dev, AW88395_MUTE_VOL);
return;
@@ -1062,10 +1056,6 @@ static int aw_dev_update_reg_container(struct aw_device *aw_dev,
aw_dev_set_volume(aw_dev, vol_desc->ctl_volume);
}

- /* keep min volume */
- if (aw_dev->fade_en)
- aw_dev_set_volume(aw_dev, AW88395_MUTE_VOL);
-
aw_dev_get_dsp_config(aw_dev, &aw_dev->dsp_cfg);

return ret;
@@ -1306,7 +1296,9 @@ int aw88395_dev_fw_update(struct aw_device *aw_dev, bool up_dsp_fw_en, bool forc
return -EPERM;
}

- prof_name = aw88395_dev_get_prof_name(aw_dev, aw_dev->prof_index);
+ ret = aw88395_dev_get_prof_name(aw_dev, aw_dev->prof_index, &prof_name);
+ if (ret)
+ return ret;

dev_dbg(aw_dev->dev, "start update %s", prof_name);

@@ -1594,37 +1586,19 @@ static void aw88395_parse_channel_dt(struct aw_device *aw_dev)
u32 channel_value;
int ret;

- ret = of_property_read_u32(np, "sound-channel", &channel_value);
+ ret = of_property_read_u32(np, "awinic,audio-channel", &channel_value);
if (ret) {
dev_dbg(aw_dev->dev,
- "read sound-channel failed,use default 0");
+ "read audio-channel failed,use default 0");
aw_dev->channel = AW88395_DEV_DEFAULT_CH;
return;
}

- dev_dbg(aw_dev->dev, "read sound-channel value is: %d",
+ dev_dbg(aw_dev->dev, "read audio-channel value is: %d",
channel_value);
aw_dev->channel = channel_value;
}

-static void aw88395_parse_fade_enable_dt(struct aw_device *aw_dev)
-{
- struct device_node *np = aw_dev->dev->of_node;
- u32 fade_en;
- int ret;
-
- ret = of_property_read_u32(np, "fade-enable", &fade_en);
- if (ret) {
- dev_dbg(aw_dev->dev,
- "read fade-enable failed, close fade_in_out");
- fade_en = AW88395_FADE_IN_OUT_DEFAULT;
- }
-
- dev_dbg(aw_dev->dev, "read fade-enable value is: %d", fade_en);
-
- aw_dev->fade_en = fade_en;
-}
-
static int aw_dev_init(struct aw_device *aw_dev)
{
aw_dev->chip_id = AW88395_CHIP_ID;
@@ -1639,7 +1613,6 @@ static int aw_dev_init(struct aw_device *aw_dev)
aw_dev->fade_step = AW88395_VOLUME_STEP_DB;
aw_dev->volume_desc.ctl_volume = AW88395_VOL_DEFAULT_VALUE;
aw88395_parse_channel_dt(aw_dev);
- aw88395_parse_fade_enable_dt(aw_dev);

return 0;
}
@@ -1673,7 +1646,7 @@ int aw88395_dev_set_profile_index(struct aw_device *aw_dev, int index)
}
EXPORT_SYMBOL_GPL(aw88395_dev_set_profile_index);

-char *aw88395_dev_get_prof_name(struct aw_device *aw_dev, int index)
+int aw88395_dev_get_prof_name(struct aw_device *aw_dev, int index, char **prof_name)
{
struct aw_prof_info *prof_info = &aw_dev->prof_info;
struct aw_prof_desc *prof_desc;
@@ -1681,12 +1654,14 @@ char *aw88395_dev_get_prof_name(struct aw_device *aw_dev, int index)
if ((index >= aw_dev->prof_info.count) || (index < 0)) {
dev_err(aw_dev->dev, "index[%d] overflow count[%d]",
index, aw_dev->prof_info.count);
- return NULL;
+ return -EINVAL;
}

prof_desc = &aw_dev->prof_info.prof_desc[index];

- return prof_info->prof_name_list[prof_desc->id];
+ *prof_name = prof_info->prof_name_list[prof_desc->id];
+
+ return 0;
}
EXPORT_SYMBOL_GPL(aw88395_dev_get_prof_name);

diff --git a/sound/soc/codecs/aw88395/aw88395_device.h b/sound/soc/codecs/aw88395/aw88395_device.h
index caf730753167..791c8c106557 100644
--- a/sound/soc/codecs/aw88395/aw88395_device.h
+++ b/sound/soc/codecs/aw88395/aw88395_device.h
@@ -141,6 +141,7 @@ struct aw_device {
unsigned char prof_cur;
unsigned char prof_index;
unsigned char dsp_crc_st;
+ unsigned char dsp_cfg;
u16 chip_id;

unsigned int channel;
@@ -151,9 +152,6 @@ struct aw_device {
struct regmap *regmap;
char *acf;

- u32 fade_en;
- unsigned char dsp_cfg;
-
u32 dsp_fw_len;
u32 dsp_cfg_len;
u8 platform;
@@ -183,7 +181,7 @@ int aw88395_dev_fw_update(struct aw_device *aw_dev, bool up_dsp_fw_en, bool forc
void aw88395_dev_set_volume(struct aw_device *aw_dev, unsigned short set_vol);
int aw88395_dev_get_prof_data(struct aw_device *aw_dev, int index,
struct aw_prof_desc **prof_desc);
-char *aw88395_dev_get_prof_name(struct aw_device *aw_dev, int index);
+int aw88395_dev_get_prof_name(struct aw_device *aw_dev, int index, char **prof_name);
int aw88395_dev_set_profile_index(struct aw_device *aw_dev, int index);
int aw88395_dev_get_profile_index(struct aw_device *aw_dev);
int aw88395_dev_get_profile_count(struct aw_device *aw_dev);
diff --git a/sound/soc/codecs/aw88395/aw88395_lib.c b/sound/soc/codecs/aw88395/aw88395_lib.c
index 8ee1baa03269..9d561ae27feb 100644
--- a/sound/soc/codecs/aw88395/aw88395_lib.c
+++ b/sound/soc/codecs/aw88395/aw88395_lib.c
@@ -455,9 +455,11 @@ static int aw_dev_parse_reg_bin_with_hdr(struct aw_device *aw_dev,
goto parse_bin_failed;
}

- if (aw_bin->header_info[0].valid_data_len % 4) {
- dev_err(aw_dev->dev, "bin data len get error!");
- goto parse_bin_failed;
+ if (aw_dev->chip_id == AW88261_CHIP_ID) {
+ if (aw_bin->header_info[0].valid_data_len % 4) {
+ dev_err(aw_dev->dev, "bin data len get error!");
+ goto parse_bin_failed;
+ }
}

prof_desc->sec_desc[AW88395_DATA_TYPE_REG].data =
@@ -579,9 +581,9 @@ static int aw_dev_parse_dev_default_type(struct aw_device *aw_dev,
}

static int aw88261_dev_cfg_get_valid_prof(struct aw_device *aw_dev,
- struct aw_all_prof_info all_prof_info)
+ struct aw_all_prof_info *all_prof_info)
{
- struct aw_prof_desc *prof_desc = all_prof_info.prof_desc;
+ struct aw_prof_desc *prof_desc = all_prof_info->prof_desc;
struct aw_prof_info *prof_info = &aw_dev->prof_info;
int num = 0;
int i;
@@ -621,9 +623,9 @@ static int aw88261_dev_cfg_get_valid_prof(struct aw_device *aw_dev,
}

static int aw88395_dev_cfg_get_valid_prof(struct aw_device *aw_dev,
- struct aw_all_prof_info all_prof_info)
+ struct aw_all_prof_info *all_prof_info)
{
- struct aw_prof_desc *prof_desc = all_prof_info.prof_desc;
+ struct aw_prof_desc *prof_desc = all_prof_info->prof_desc;
struct aw_prof_info *prof_info = &aw_dev->prof_info;
struct aw_sec_data_desc *sec_desc;
int num = 0;
@@ -701,12 +703,13 @@ static int aw_dev_load_cfg_by_hdr(struct aw_device *aw_dev,

switch (aw_dev->chip_id) {
case AW88395_CHIP_ID:
- ret = aw88395_dev_cfg_get_valid_prof(aw_dev, *all_prof_info);
+ ret = aw88395_dev_cfg_get_valid_prof(aw_dev, all_prof_info);
if (ret < 0)
goto exit;
break;
case AW88261_CHIP_ID:
- ret = aw88261_dev_cfg_get_valid_prof(aw_dev, *all_prof_info);
+ case AW87390_CHIP_ID:
+ ret = aw88261_dev_cfg_get_valid_prof(aw_dev, all_prof_info);
if (ret < 0)
goto exit;
break;
@@ -799,6 +802,7 @@ static int aw_get_dev_scene_count_v1(struct aw_device *aw_dev, struct aw_contain
ret = 0;
break;
case AW88261_CHIP_ID:
+ case AW87390_CHIP_ID:
for (i = 0; i < cfg_hdr->ddt_num; ++i) {
if (((cfg_dde[i].data_type == ACF_SEC_TYPE_REG) ||
(cfg_dde[i].data_type == ACF_SEC_TYPE_HDR_REG)) &&
@@ -839,6 +843,7 @@ static int aw_get_default_scene_count_v1(struct aw_device *aw_dev,
ret = 0;
break;
case AW88261_CHIP_ID:
+ case AW87390_CHIP_ID:
for (i = 0; i < cfg_hdr->ddt_num; ++i) {
if (((cfg_dde[i].data_type == ACF_SEC_TYPE_REG) ||
(cfg_dde[i].data_type == ACF_SEC_TYPE_HDR_REG)) &&
diff --git a/sound/soc/codecs/aw88395/aw88395_reg.h b/sound/soc/codecs/aw88395/aw88395_reg.h
index e7a7c02efaf3..d0a273387313 100644
--- a/sound/soc/codecs/aw88395/aw88395_reg.h
+++ b/sound/soc/codecs/aw88395/aw88395_reg.h
@@ -97,6 +97,7 @@
enum aw88395_id {
AW88395_CHIP_ID = 0x2049,
AW88261_CHIP_ID = 0x2113,
+ AW87390_CHIP_ID = 0x76,
};

#define AW88395_REG_MAX (0x7D)
--
2.41.0

2023-09-12 16:28:20

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH V2 1/5] ASoC: dt-bindings: Adds properties to "awinic,aw88395"

On Tue, Sep 12, 2023 at 02:58:48PM +0800, [email protected] wrote:
> From: Weidong Wang <[email protected]>

The subject is still pretty generic. Ideally, we'd never have the same
subject twice. I'd do something like this:

ASoC: dt-bindings: awinic,aw88395: Add properties for multiple PA support

>
> Adds properties to "awinic,aw88395" to make files more complete

Complete in what way? multiple PAs, right. It's not really clear
to me though how these properties enable support for multiple PAs.

>
> Signed-off-by: Weidong Wang <[email protected]>
> ---
> .../bindings/sound/awinic,aw88395.yaml | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml b/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml
> index 4051c2538caf..4965aa4a5370 100644
> --- a/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml
> +++ b/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml
> @@ -32,11 +32,28 @@ properties:
> reset-gpios:
> maxItems: 1
>
> + awinic,audio-channel:
> + description:
> + It is used to distinguish multiple PA devices, so that different
> + configurations can be loaded to different PA devices
> + $ref: /schemas/types.yaml#/definitions/uint32
> + minimum: 0
> + maximum: 7
> +
> + awinic,sync-flag:
> + description:
> + Flag bit used to keep the phase synchronized in the case of multiple PA
> + $ref: /schemas/types.yaml#/definitions/uint32
> + minimum: 0
> + maximum: 1
> +
> required:
> - compatible
> - reg
> - '#sound-dai-cells'
> - reset-gpios
> + - awinic,audio-channel
> + - awinic,sync-flag
>
> unevaluatedProperties: false
>
> @@ -51,5 +68,7 @@ examples:
> reg = <0x34>;
> #sound-dai-cells = <0>;
> reset-gpios = <&gpio 10 GPIO_ACTIVE_LOW>;
> + awinic,audio-channel = <0>;
> + awinic,sync-flag = <0>;
> };
> };
> --
> 2.41.0
>

2023-09-12 18:05:09

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH V2 2/5] ASoC: dt-bindings: Add schema for "awinic,aw87390"


On Tue, 12 Sep 2023 14:58:49 +0800, [email protected] wrote:
> From: Weidong Wang <[email protected]>
>
> Add a DT schema for describing awinic aw87390 audio amplifiers.
> They are controlled using I2C.
>
> Signed-off-by: Weidong Wang <[email protected]>
> ---
> .../bindings/sound/awinic,aw87390.yaml | 58 +++++++++++++++++++
> 1 file changed, 58 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/sound/awinic,aw87390.yaml
>

Reviewed-by: Rob Herring <[email protected]>

2023-09-13 08:02:45

by wangweidong.a

[permalink] [raw]
Subject: Re: [PATCH V2 4/5] ASoC: codecs: Change the aw88261 variable name and i2c driver name

Thank you very much for your review.



On 13/09/2023 09:03, [email protected] wrote:

> On 12/09/2023 08:58, [email protected] wrote:

>> From: Weidong Wang <[email protected]>

>>

>> Change "sound-channel" to "awinic,audio-channel"

>> Change "aw88261_smartpa" to "aw88261"



I'll add "This change is for consistency with yaml properties" to the commit message.



>> - prof_name = aw88261_dev_get_prof_name(aw88261->aw_pa, count);

>> - if (!prof_name) {

>> + ret = aw88261_dev_get_prof_name(aw88261->aw_pa, count, &prof_name);

>> + if (ret) {

>> strscpy(uinfo->value.enumerated.name, "null",

>> strlen("null") + 1);

>> return 0;

>> @@ -1189,7 +1190,7 @@ static void aw88261_parse_channel_dt(struct aw88261 *aw88261)

>> u32 channel_value = AW88261_DEV_DEFAULT_CH;

>> u32 sync_enable = false;

>>

>> - of_property_read_u32(np, "sound-channel", &channel_value);

>> + of_property_read_u32(np, "awinic,audio-channel", &channel_value);

>> of_property_read_u32(np, "sync-flag", &sync_enable);



> What about this?



This change is to be consistent with the name in the yaml file



Best regards,

Weidong Wang

2023-09-13 08:22:31

by wangweidong.a

[permalink] [raw]
Subject: Re: [PATCH V2 1/5] ASoC: dt-bindings: Adds properties to "awinic,aw88395"

Thank you very much for your advice, and I will modify it in the next patch.

On Tue, Sep 12, 2023 at 11:21:22PM -0500, [email protected] wrote:
> On Tue, Sep 12, 2023 at 02:58:48PM +0800, [email protected] wrote:
>> From: Weidong Wang <[email protected]>

> The subject is still pretty generic. Ideally, we'd never have the same
> subject twice. I'd do something like this:

> ASoC: dt-bindings: awinic,aw88395: Add properties for multiple PA support

Thank you very much. I will modify according to your suggestion in the next patch

>>
>> Adds properties to "awinic,aw88395" to make files more complete

> Complete in what way? multiple PAs, right. It's not really clear
> to me though how these properties enable support for multiple PAs.

Thank you very much. I will change the following content in the next patch:
Add two properties, the "awinic,audio-channel" property and the
"awinic,sync-flag". The "awinic,audio-channel" is used to make
different PA load different configurations, the "awinic,sync-flag"
is used to synchronize the phases of multiple PA. These two properties
will be read by the corresponding driver, so that the multi-PA to
achieve better playback effect.

>>
>> Signed-off-by: Weidong Wang <[email protected]>
>> ---
>> .../bindings/sound/awinic,aw88395.yaml | 19 +++++++++++++++++++
>> 1 file changed, 19 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml b/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml
>> index 4051c2538caf..4965aa4a5370 100644
>> --- a/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml
>> +++ b/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml
>> @@ -32,11 +32,28 @@ properties:
>> reset-gpios:
>> maxItems: 1
>>
>> + awinic,audio-channel:
>> + description:
>> + It is used to distinguish multiple PA devices, so that different
>> + configurations can be loaded to different PA devices
>> + $ref: /schemas/types.yaml#/definitions/uint32
>> + minimum: 0
>> + maximum: 7
>> +
>> + awinic,sync-flag:
>> + description:
>> + Flag bit used to keep the phase synchronized in the case of multiple PA
>> + $ref: /schemas/types.yaml#/definitions/uint32
>> + minimum: 0
>> + maximum: 1
>> +
>> required:
>> - compatible
>> - reg
>> - '#sound-dai-cells'
>> - reset-gpios
>> + - awinic,audio-channel
>> + - awinic,sync-flag
>>
>> unevaluatedProperties: false
>>
>> @@ -51,5 +68,7 @@ examples:
>> reg = <0x34>;
>> #sound-dai-cells = <0>;
>> reset-gpios = <&gpio 10 GPIO_ACTIVE_LOW>;
>> + awinic,audio-channel = <0>;
>> + awinic,sync-flag = <0>;
>> };
>> };
>> --
>> 2.41.0
>>

2023-09-13 13:37:28

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH V2 4/5] ASoC: codecs: Change the aw88261 variable name and i2c driver name

On 12/09/2023 08:58, [email protected] wrote:
> From: Weidong Wang <[email protected]>
>
> Change "sound-channel" to "awinic,audio-channel"
> Change "aw88261_smartpa" to "aw88261"



> - prof_name = aw88261_dev_get_prof_name(aw88261->aw_pa, count);
> - if (!prof_name) {
> + ret = aw88261_dev_get_prof_name(aw88261->aw_pa, count, &prof_name);
> + if (ret) {
> strscpy(uinfo->value.enumerated.name, "null",
> strlen("null") + 1);
> return 0;
> @@ -1189,7 +1190,7 @@ static void aw88261_parse_channel_dt(struct aw88261 *aw88261)
> u32 channel_value = AW88261_DEV_DEFAULT_CH;
> u32 sync_enable = false;
>
> - of_property_read_u32(np, "sound-channel", &channel_value);
> + of_property_read_u32(np, "awinic,audio-channel", &channel_value);
> of_property_read_u32(np, "sync-flag", &sync_enable);

What about this?

Best regards,
Krzysztof

2023-09-13 15:06:04

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH V2 1/5] ASoC: dt-bindings: Adds properties to "awinic,aw88395"

On 12/09/2023 08:58, [email protected] wrote:
> From: Weidong Wang <[email protected]>
>
> Adds properties to "awinic,aw88395" to make files more complete
>
> Signed-off-by: Weidong Wang <[email protected]>
> ---
> .../bindings/sound/awinic,aw88395.yaml | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml b/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml
> index 4051c2538caf..4965aa4a5370 100644
> --- a/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml
> +++ b/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml
> @@ -32,11 +32,28 @@ properties:
> reset-gpios:
> maxItems: 1
>
> + awinic,audio-channel:
> + description:
> + It is used to distinguish multiple PA devices, so that different
> + configurations can be loaded to different PA devices
> + $ref: /schemas/types.yaml#/definitions/uint32
> + minimum: 0
> + maximum: 7
> +
> + awinic,sync-flag:
> + description:
> + Flag bit used to keep the phase synchronized in the case of multiple PA
> + $ref: /schemas/types.yaml#/definitions/uint32

Looks like bool, not uint32. If you made it uint32 for some future
purpose, then the name "flag" is misleading and anyway what would be the
third option here for sync?

Best regards,
Krzysztof

2023-09-13 20:56:28

by wangweidong.a

[permalink] [raw]
Subject: Re: [PATCH V2 1/5] ASoC: dt-bindings: Adds properties to "awinic,aw88395"

Thank you very much for your review, but I have a question that I would like to consult



On 13/09/2023 09:03, [email protected] wrote:

> On 12/09/2023 08:58, [email protected] wrote:

>> From: Weidong Wang <[email protected]>

>>

>> Adds properties to "awinic,aw88395" to make files more complete

>>

>> Signed-off-by: Weidong Wang <[email protected]>

>> ---

>> .../bindings/sound/awinic,aw88395.yaml | 19 +++++++++++++++++++

>> 1 file changed, 19 insertions(+)

>>

>> diff --git a/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml b/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml

>> index 4051c2538caf..4965aa4a5370 100644

>> --- a/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml

>> +++ b/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml

>> @@ -32,11 +32,28 @@ properties:

>> reset-gpios:

>> maxItems: 1

>>

>> + awinic,audio-channel:

>> + description:

>> + It is used to distinguish multiple PA devices, so that different

>> + configurations can be loaded to different PA devices

>> + $ref: /schemas/types.yaml#/definitions/uint32

>> + minimum: 0

>> + maximum: 7

>> +

>> + awinic,sync-flag:

>> + description:

>> + Flag bit used to keep the phase synchronized in the case of multiple PA

>> + $ref: /schemas/types.yaml#/definitions/uint32



> Looks like bool, not uint32. If you made it uint32 for some future

> purpose, then the name "flag" is misleading and anyway what would be the

> third option here for sync?



Thank you very much. Can I Change it to "$ref: /schemas/types.yaml#/definitions/bool"?



Best regards,

Weidong Wang