summaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/aw88395/aw88395_lib.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2023-08-30 13:45:05 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2023-08-30 13:45:05 -0700
commit4fb0dacb78c6a041bbd38ddd998df806af5c2c69 (patch)
treef175caac9bc11c78632959a954a6b618fbf8f5c1 /sound/soc/codecs/aw88395/aw88395_lib.c
parent461f35f014466c4e26dca6be0f431f57297df3f2 (diff)
parent358040e3807754944dbddf948a23c6d914297ed7 (diff)
downloadlinux-stable-4fb0dacb78c6a041bbd38ddd998df806af5c2c69.tar.gz
linux-stable-4fb0dacb78c6a041bbd38ddd998df806af5c2c69.tar.bz2
linux-stable-4fb0dacb78c6a041bbd38ddd998df806af5c2c69.zip
Merge tag 'sound-6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "We've received a fairly wide range of changes at this time, including for ALSA and ASoC core, but all of them are rather small changes. Here are some highlights: ALSA / ASoC Core: - Fixes of inconsistent locking around control API helpers - A few new control API functions and cleanups - Workarounds for potential UAFs by delayed kobj releases - Unified PCM copy ops with iov_iter - Continued efforts for ASoC API cleanups ASoC: - An adaptor to allow use of IIO DACs and ADCs in ASoC which pulls in some IIO changes - Create a library function for intlog10() and use it in the NAU8825 driver - Convert drivers to use the more modern maple tree register cache - Lots of work on the SOF framework, AMD and Intel drivers, including a lot of cleanup and new device support - Standardization of the presentation of jacks from drivers - Provision of some generic sound card DT properties - Support for AMD Van Gogh, AMD machines with MAX98388 and NAU8821, AWInic AW88261, Cirrus Logic CS35L36 and CS42L43, various Intel platforms including AVS machines with ES8336 and RT5663, Mediatek MT7986, NXP i.MX93, RealTek RT1017 and StarFive JH7110 Others: - New test coverage including ASoC and topology tests in KUnit; this also involves enabling UML builds of ALSA since that's the default KUnit test environment which pulls in the addition of some stubs to the driver - More enhancement of pcmtest driver - A few fixes / enhancements of MIDI 2.0 UMP core - Using PCI definitions in allover HD-audio code - Support for Cirrus CS35L56 and TI TAS2781 HD-audio sub-codecs - CS35L41 HD-audio sub-codec improvements - Continued emu10k1 improvements" * tag 'sound-6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (693 commits) ALSA: pcm: Fix missing fixup call in compat hw_refine ioctl ASoC: dwc: i2s: Fix unused functions ALSA: usb-audio: Don't try to submit URBs after disconnection ALSA: emu10k1: add separate documentation for E-MU cards ALSA: emu10k1: more documentation updates ALSA: emu10k1: de-duplicate audigy-mixer.rst vs. sb-live-mixer.rst ALSA: ump: Fix -Wformat-truncation warnings ALSA: hda: Add missing dependency on CONFIG_EFI for Cirrus/TI sub-codecs ALSA: doc: Fix missing backquote in midi-2.0.rst ALSA: hda/realtek: Add quirk for mute LEDs on HP ENVY x360 15-eu0xxx ALSA: hda/tas2781: Switch back to use struct i2c_driver's .probe() ASoC: soc-core.c: Do not error if a DAI link component is not found ASoC: codecs: Fix error code in aw88261_i2c_probe() ASoC: audio-graph-card.c: move audio_graph_parse_of() ASoC: cs42l43: Use new-style PM runtime macros ALSA: documentation: Add description for USB MIDI 2.0 gadget driver ALSA: ump: Don't create unused substreams for static blocks ALSA: ump: Fill group names for legacy rawmidi substreams ALSA: usb-audio: Attach legacy rawmidi after probing all UMP EPs ALSA: ac97: Fix possible error value of *rac97 ...
Diffstat (limited to 'sound/soc/codecs/aw88395/aw88395_lib.c')
-rw-r--r--sound/soc/codecs/aw88395/aw88395_lib.c193
1 files changed, 176 insertions, 17 deletions
diff --git a/sound/soc/codecs/aw88395/aw88395_lib.c b/sound/soc/codecs/aw88395/aw88395_lib.c
index 05bcf49da857..8ee1baa03269 100644
--- a/sound/soc/codecs/aw88395/aw88395_lib.c
+++ b/sound/soc/codecs/aw88395/aw88395_lib.c
@@ -11,6 +11,7 @@
#include <linux/i2c.h>
#include "aw88395_lib.h"
#include "aw88395_device.h"
+#include "aw88395_reg.h"
#define AW88395_CRC8_POLYNOMIAL 0x8C
DECLARE_CRC8_TABLE(aw_crc8_table);
@@ -429,6 +430,53 @@ parse_bin_failed:
return ret;
}
+static int aw_dev_parse_reg_bin_with_hdr(struct aw_device *aw_dev,
+ uint8_t *data, uint32_t data_len, struct aw_prof_desc *prof_desc)
+{
+ struct aw_bin *aw_bin;
+ int ret;
+
+ aw_bin = devm_kzalloc(aw_dev->dev, data_len + sizeof(*aw_bin), GFP_KERNEL);
+ if (!aw_bin)
+ return -ENOMEM;
+
+ aw_bin->info.len = data_len;
+ memcpy(aw_bin->info.data, data, data_len);
+
+ ret = aw_parsing_bin_file(aw_dev, aw_bin);
+ if (ret < 0) {
+ dev_err(aw_dev->dev, "parse bin failed");
+ goto parse_bin_failed;
+ }
+
+ if ((aw_bin->all_bin_parse_num != 1) ||
+ (aw_bin->header_info[0].bin_data_type != DATA_TYPE_REGISTER)) {
+ dev_err(aw_dev->dev, "bin num or type error");
+ 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;
+ }
+
+ prof_desc->sec_desc[AW88395_DATA_TYPE_REG].data =
+ data + aw_bin->header_info[0].valid_data_addr;
+ prof_desc->sec_desc[AW88395_DATA_TYPE_REG].len =
+ aw_bin->header_info[0].valid_data_len;
+ prof_desc->prof_st = AW88395_PROFILE_OK;
+
+ devm_kfree(aw_dev->dev, aw_bin);
+ aw_bin = NULL;
+
+ return 0;
+
+parse_bin_failed:
+ devm_kfree(aw_dev->dev, aw_bin);
+ aw_bin = NULL;
+ return ret;
+}
+
static int aw_dev_parse_data_by_sec_type(struct aw_device *aw_dev, struct aw_cfg_hdr *cfg_hdr,
struct aw_cfg_dde *cfg_dde, struct aw_prof_desc *scene_prof_desc)
{
@@ -447,6 +495,9 @@ static int aw_dev_parse_data_by_sec_type(struct aw_device *aw_dev, struct aw_cfg
return aw_dev_prof_parse_multi_bin(
aw_dev, (u8 *)cfg_hdr + cfg_dde->data_offset,
cfg_dde->data_size, scene_prof_desc);
+ case ACF_SEC_TYPE_HDR_REG:
+ return aw_dev_parse_reg_bin_with_hdr(aw_dev, (u8 *)cfg_hdr + cfg_dde->data_offset,
+ cfg_dde->data_size, scene_prof_desc);
default:
dev_err(aw_dev->dev, "%s cfg_dde->data_type = %d\n", __func__, cfg_dde->data_type);
break;
@@ -527,7 +578,49 @@ static int aw_dev_parse_dev_default_type(struct aw_device *aw_dev,
return 0;
}
-static int aw_dev_cfg_get_valid_prof(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_prof_desc *prof_desc = all_prof_info.prof_desc;
+ struct aw_prof_info *prof_info = &aw_dev->prof_info;
+ int num = 0;
+ int i;
+
+ for (i = 0; i < AW88395_PROFILE_MAX; i++) {
+ if (prof_desc[i].prof_st == AW88395_PROFILE_OK)
+ prof_info->count++;
+ }
+
+ dev_dbg(aw_dev->dev, "get valid profile:%d", aw_dev->prof_info.count);
+
+ if (!prof_info->count) {
+ dev_err(aw_dev->dev, "no profile data");
+ return -EPERM;
+ }
+
+ prof_info->prof_desc = devm_kcalloc(aw_dev->dev,
+ prof_info->count, sizeof(struct aw_prof_desc),
+ GFP_KERNEL);
+ if (!prof_info->prof_desc)
+ return -ENOMEM;
+
+ for (i = 0; i < AW88395_PROFILE_MAX; i++) {
+ if (prof_desc[i].prof_st == AW88395_PROFILE_OK) {
+ if (num >= prof_info->count) {
+ dev_err(aw_dev->dev, "overflow count[%d]",
+ prof_info->count);
+ return -EINVAL;
+ }
+ prof_info->prof_desc[num] = prof_desc[i];
+ prof_info->prof_desc[num].id = i;
+ num++;
+ }
+ }
+
+ return 0;
+}
+
+static int aw88395_dev_cfg_get_valid_prof(struct aw_device *aw_dev,
struct aw_all_prof_info all_prof_info)
{
struct aw_prof_desc *prof_desc = all_prof_info.prof_desc;
@@ -606,9 +699,22 @@ static int aw_dev_load_cfg_by_hdr(struct aw_device *aw_dev,
goto exit;
}
- ret = aw_dev_cfg_get_valid_prof(aw_dev, *all_prof_info);
- if (ret < 0)
- goto exit;
+ switch (aw_dev->chip_id) {
+ case AW88395_CHIP_ID:
+ 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);
+ if (ret < 0)
+ goto exit;
+ break;
+ default:
+ dev_err(aw_dev->dev, "valid prof unsupported");
+ ret = -EINVAL;
+ break;
+ }
aw_dev->prof_info.prof_name_list = profile_name;
@@ -679,16 +785,37 @@ static int aw_get_dev_scene_count_v1(struct aw_device *aw_dev, struct aw_contain
struct aw_cfg_dde_v1 *cfg_dde =
(struct aw_cfg_dde_v1 *)(aw_cfg->data + cfg_hdr->hdr_offset);
unsigned int i;
+ int ret;
- for (i = 0; i < cfg_hdr->ddt_num; ++i) {
- if ((cfg_dde[i].data_type == ACF_SEC_TYPE_MULTIPLE_BIN) &&
- (aw_dev->chip_id == cfg_dde[i].chip_id) &&
- (aw_dev->i2c->adapter->nr == cfg_dde[i].dev_bus) &&
- (aw_dev->i2c->addr == cfg_dde[i].dev_addr))
- (*scene_num)++;
+ switch (aw_dev->chip_id) {
+ case AW88395_CHIP_ID:
+ for (i = 0; i < cfg_hdr->ddt_num; ++i) {
+ if ((cfg_dde[i].data_type == ACF_SEC_TYPE_MULTIPLE_BIN) &&
+ (aw_dev->chip_id == cfg_dde[i].chip_id) &&
+ (aw_dev->i2c->adapter->nr == cfg_dde[i].dev_bus) &&
+ (aw_dev->i2c->addr == cfg_dde[i].dev_addr))
+ (*scene_num)++;
+ }
+ ret = 0;
+ break;
+ case AW88261_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)) &&
+ (aw_dev->chip_id == cfg_dde[i].chip_id) &&
+ (aw_dev->i2c->adapter->nr == cfg_dde[i].dev_bus) &&
+ (aw_dev->i2c->addr == cfg_dde[i].dev_addr))
+ (*scene_num)++;
+ }
+ ret = 0;
+ break;
+ default:
+ dev_err(aw_dev->dev, "unsupported device");
+ ret = -EINVAL;
+ break;
}
- return 0;
+ return ret;
}
static int aw_get_default_scene_count_v1(struct aw_device *aw_dev,
@@ -699,15 +826,35 @@ static int aw_get_default_scene_count_v1(struct aw_device *aw_dev,
struct aw_cfg_dde_v1 *cfg_dde =
(struct aw_cfg_dde_v1 *)(aw_cfg->data + cfg_hdr->hdr_offset);
unsigned int i;
+ int ret;
- for (i = 0; i < cfg_hdr->ddt_num; ++i) {
- if ((cfg_dde[i].data_type == ACF_SEC_TYPE_MULTIPLE_BIN) &&
- (aw_dev->chip_id == cfg_dde[i].chip_id) &&
- (aw_dev->channel == cfg_dde[i].dev_index))
- (*scene_num)++;
+ switch (aw_dev->chip_id) {
+ case AW88395_CHIP_ID:
+ for (i = 0; i < cfg_hdr->ddt_num; ++i) {
+ if ((cfg_dde[i].data_type == ACF_SEC_TYPE_MULTIPLE_BIN) &&
+ (aw_dev->chip_id == cfg_dde[i].chip_id) &&
+ (aw_dev->channel == cfg_dde[i].dev_index))
+ (*scene_num)++;
+ }
+ ret = 0;
+ break;
+ case AW88261_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)) &&
+ (aw_dev->chip_id == cfg_dde[i].chip_id) &&
+ (aw_dev->channel == cfg_dde[i].dev_index))
+ (*scene_num)++;
+ }
+ ret = 0;
+ break;
+ default:
+ dev_err(aw_dev->dev, "unsupported device");
+ ret = -EINVAL;
+ break;
}
- return 0;
+ return ret;
}
static int aw_dev_parse_scene_count_v1(struct aw_device *aw_dev,
@@ -756,6 +903,18 @@ static int aw_dev_parse_data_by_sec_type_v1(struct aw_device *aw_dev,
prof_info->prof_desc[*cur_scene_id].id = cfg_dde->dev_profile;
(*cur_scene_id)++;
break;
+ case ACF_SEC_TYPE_HDR_REG:
+ ret = aw_dev_parse_reg_bin_with_hdr(aw_dev,
+ (uint8_t *)prof_hdr + cfg_dde->data_offset,
+ cfg_dde->data_size, &prof_info->prof_desc[*cur_scene_id]);
+ if (ret < 0) {
+ dev_err(aw_dev->dev, "parse reg bin with hdr failed");
+ return ret;
+ }
+ prof_info->prof_desc[*cur_scene_id].prf_str = cfg_dde->dev_profile_str;
+ prof_info->prof_desc[*cur_scene_id].id = cfg_dde->dev_profile;
+ (*cur_scene_id)++;
+ break;
default:
dev_err(aw_dev->dev, "unsupported SEC_TYPE [%d]", cfg_dde->data_type);
return -EINVAL;