Unverified Commit 1ee45e64 authored by Mark Brown's avatar Mark Brown
Browse files

firmware: cs_dsp: Some small coding improvements

Merge series from Richard Fitzgerald <rf@opensource.cirrus.com>:

Commit series that makes some small improvements to code and the
kernel log messages.
parents 0d1ebba7 dc0e5ca8
Loading
Loading
Loading
Loading
+185 −110
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include <linux/ctype.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/seq_file.h>
@@ -1050,7 +1051,7 @@ static int cs_dsp_create_control(struct cs_dsp *dsp,

	ctl->fw_name = dsp->fw_name;
	ctl->alg_region = *alg_region;
	if (subname && dsp->fw_ver >= 2) {
	if (subname && dsp->wmfw_ver >= 2) {
		ctl->subname_len = subname_len;
		ctl->subname = kasprintf(GFP_KERNEL, "%.*s", subname_len, subname);
		if (!ctl->subname) {
@@ -1110,9 +1111,16 @@ struct cs_dsp_coeff_parsed_coeff {
	int len;
};

static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, const u8 **str)
static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, unsigned int avail,
				     const u8 **str)
{
	int length;
	int length, total_field_len;

	/* String fields are at least one __le32 */
	if (sizeof(__le32) > avail) {
		*pos = NULL;
		return 0;
	}

	switch (bytes) {
	case 1:
@@ -1125,10 +1133,16 @@ static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, const u8 **str)
		return 0;
	}

	total_field_len = ((length + bytes) + 3) & ~0x03;
	if ((unsigned int)total_field_len > avail) {
		*pos = NULL;
		return 0;
	}

	if (str)
		*str = *pos + bytes;

	*pos += ((length + bytes) + 3) & ~0x03;
	*pos += total_field_len;

	return length;
}
@@ -1153,71 +1167,134 @@ static int cs_dsp_coeff_parse_int(int bytes, const u8 **pos)
	return val;
}

static inline void cs_dsp_coeff_parse_alg(struct cs_dsp *dsp, const u8 **data,
static int cs_dsp_coeff_parse_alg(struct cs_dsp *dsp,
				  const struct wmfw_region *region,
				  struct cs_dsp_coeff_parsed_alg *blk)
{
	const struct wmfw_adsp_alg_data *raw;
	unsigned int data_len = le32_to_cpu(region->len);
	unsigned int pos;
	const u8 *tmp;

	raw = (const struct wmfw_adsp_alg_data *)region->data;

	switch (dsp->fw_ver) {
	switch (dsp->wmfw_ver) {
	case 0:
	case 1:
		raw = (const struct wmfw_adsp_alg_data *)*data;
		*data = raw->data;
		if (sizeof(*raw) > data_len)
			return -EOVERFLOW;

		blk->id = le32_to_cpu(raw->id);
		blk->name = raw->name;
		blk->name_len = strlen(raw->name);
		blk->name_len = strnlen(raw->name, ARRAY_SIZE(raw->name));
		blk->ncoeff = le32_to_cpu(raw->ncoeff);

		pos = sizeof(*raw);
		break;
	default:
		blk->id = cs_dsp_coeff_parse_int(sizeof(raw->id), data);
		blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), data,
		if (sizeof(raw->id) > data_len)
			return -EOVERFLOW;

		tmp = region->data;
		blk->id = cs_dsp_coeff_parse_int(sizeof(raw->id), &tmp);
		pos = tmp - region->data;

		tmp = &region->data[pos];
		blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos,
							  &blk->name);
		cs_dsp_coeff_parse_string(sizeof(u16), data, NULL);
		blk->ncoeff = cs_dsp_coeff_parse_int(sizeof(raw->ncoeff), data);
		if (!tmp)
			return -EOVERFLOW;

		pos = tmp - region->data;
		cs_dsp_coeff_parse_string(sizeof(u16), &tmp, data_len - pos, NULL);
		if (!tmp)
			return -EOVERFLOW;

		pos = tmp - region->data;
		if (sizeof(raw->ncoeff) > (data_len - pos))
			return -EOVERFLOW;

		blk->ncoeff = cs_dsp_coeff_parse_int(sizeof(raw->ncoeff), &tmp);
		pos += sizeof(raw->ncoeff);
		break;
	}

	if ((int)blk->ncoeff < 0)
		return -EOVERFLOW;

	cs_dsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id);
	cs_dsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name);
	cs_dsp_dbg(dsp, "# of coefficient descriptors: %#x\n", blk->ncoeff);

	return pos;
}

static inline void cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp, const u8 **data,
static int cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp,
				    const struct wmfw_region *region,
				    unsigned int pos,
				    struct cs_dsp_coeff_parsed_coeff *blk)
{
	const struct wmfw_adsp_coeff_data *raw;
	unsigned int data_len = le32_to_cpu(region->len);
	unsigned int blk_len, blk_end_pos;
	const u8 *tmp;
	int length;

	switch (dsp->fw_ver) {
	case 0:
	case 1:
		raw = (const struct wmfw_adsp_coeff_data *)*data;
		*data = *data + sizeof(raw->hdr) + le32_to_cpu(raw->hdr.size);
	raw = (const struct wmfw_adsp_coeff_data *)&region->data[pos];
	if (sizeof(raw->hdr) > (data_len - pos))
		return -EOVERFLOW;

	blk_len = le32_to_cpu(raw->hdr.size);
	if (blk_len > S32_MAX)
		return -EOVERFLOW;

	if (blk_len > (data_len - pos - sizeof(raw->hdr)))
		return -EOVERFLOW;

	blk_end_pos = pos + sizeof(raw->hdr) + blk_len;

	blk->offset = le16_to_cpu(raw->hdr.offset);
	blk->mem_type = le16_to_cpu(raw->hdr.type);

	switch (dsp->wmfw_ver) {
	case 0:
	case 1:
		if (sizeof(*raw) > (data_len - pos))
			return -EOVERFLOW;

		blk->name = raw->name;
		blk->name_len = strlen(raw->name);
		blk->name_len = strnlen(raw->name, ARRAY_SIZE(raw->name));
		blk->ctl_type = le16_to_cpu(raw->ctl_type);
		blk->flags = le16_to_cpu(raw->flags);
		blk->len = le32_to_cpu(raw->len);
		break;
	default:
		tmp = *data;
		blk->offset = cs_dsp_coeff_parse_int(sizeof(raw->hdr.offset), &tmp);
		blk->mem_type = cs_dsp_coeff_parse_int(sizeof(raw->hdr.type), &tmp);
		length = cs_dsp_coeff_parse_int(sizeof(raw->hdr.size), &tmp);
		blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp,
		pos += sizeof(raw->hdr);
		tmp = &region->data[pos];
		blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos,
							  &blk->name);
		cs_dsp_coeff_parse_string(sizeof(u8), &tmp, NULL);
		cs_dsp_coeff_parse_string(sizeof(u16), &tmp, NULL);
		if (!tmp)
			return -EOVERFLOW;

		pos = tmp - region->data;
		cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos, NULL);
		if (!tmp)
			return -EOVERFLOW;

		pos = tmp - region->data;
		cs_dsp_coeff_parse_string(sizeof(u16), &tmp, data_len - pos, NULL);
		if (!tmp)
			return -EOVERFLOW;

		pos = tmp - region->data;
		if (sizeof(raw->ctl_type) + sizeof(raw->flags) + sizeof(raw->len) >
		    (data_len - pos))
			return -EOVERFLOW;

		blk->ctl_type = cs_dsp_coeff_parse_int(sizeof(raw->ctl_type), &tmp);
		pos += sizeof(raw->ctl_type);
		blk->flags = cs_dsp_coeff_parse_int(sizeof(raw->flags), &tmp);
		pos += sizeof(raw->flags);
		blk->len = cs_dsp_coeff_parse_int(sizeof(raw->len), &tmp);

		*data = *data + sizeof(raw->hdr) + length;
		break;
	}

@@ -1227,6 +1304,8 @@ static inline void cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp, const u8 **data,
	cs_dsp_dbg(dsp, "\tCoefficient flags: %#x\n", blk->flags);
	cs_dsp_dbg(dsp, "\tALSA control type: %#x\n", blk->ctl_type);
	cs_dsp_dbg(dsp, "\tALSA control len: %#x\n", blk->len);

	return blk_end_pos;
}

static int cs_dsp_check_coeff_flags(struct cs_dsp *dsp,
@@ -1250,12 +1329,16 @@ static int cs_dsp_parse_coeff(struct cs_dsp *dsp,
	struct cs_dsp_alg_region alg_region = {};
	struct cs_dsp_coeff_parsed_alg alg_blk;
	struct cs_dsp_coeff_parsed_coeff coeff_blk;
	const u8 *data = region->data;
	int i, ret;
	int i, pos, ret;

	pos = cs_dsp_coeff_parse_alg(dsp, region, &alg_blk);
	if (pos < 0)
		return pos;

	cs_dsp_coeff_parse_alg(dsp, &data, &alg_blk);
	for (i = 0; i < alg_blk.ncoeff; i++) {
		cs_dsp_coeff_parse_coeff(dsp, &data, &coeff_blk);
		pos = cs_dsp_coeff_parse_coeff(dsp, region, pos, &coeff_blk);
		if (pos < 0)
			return pos;

		switch (coeff_blk.ctl_type) {
		case WMFW_CTL_TYPE_BYTES:
@@ -1324,6 +1407,10 @@ static unsigned int cs_dsp_adsp1_parse_sizes(struct cs_dsp *dsp,
	const struct wmfw_adsp1_sizes *adsp1_sizes;

	adsp1_sizes = (void *)&firmware->data[pos];
	if (sizeof(*adsp1_sizes) > firmware->size - pos) {
		cs_dsp_err(dsp, "%s: file truncated\n", file);
		return 0;
	}

	cs_dsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", file,
		   le32_to_cpu(adsp1_sizes->dm), le32_to_cpu(adsp1_sizes->pm),
@@ -1340,6 +1427,10 @@ static unsigned int cs_dsp_adsp2_parse_sizes(struct cs_dsp *dsp,
	const struct wmfw_adsp2_sizes *adsp2_sizes;

	adsp2_sizes = (void *)&firmware->data[pos];
	if (sizeof(*adsp2_sizes) > firmware->size - pos) {
		cs_dsp_err(dsp, "%s: file truncated\n", file);
		return 0;
	}

	cs_dsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", file,
		   le32_to_cpu(adsp2_sizes->xm), le32_to_cpu(adsp2_sizes->ym),
@@ -1379,12 +1470,10 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
	struct regmap *regmap = dsp->regmap;
	unsigned int pos = 0;
	const struct wmfw_header *header;
	const struct wmfw_adsp1_sizes *adsp1_sizes;
	const struct wmfw_footer *footer;
	const struct wmfw_region *region;
	const struct cs_dsp_region *mem;
	const char *region_name;
	char *text = NULL;
	struct cs_dsp_buf *buf;
	unsigned int reg;
	int regions = 0;
@@ -1395,10 +1484,8 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,

	ret = -EINVAL;

	pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
	if (pos >= firmware->size) {
		cs_dsp_err(dsp, "%s: file too short, %zu bytes\n",
			   file, firmware->size);
	if (sizeof(*header) >= firmware->size) {
		ret = -EOVERFLOW;
		goto out_fw;
	}

@@ -1415,8 +1502,7 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
		goto out_fw;
	}

	cs_dsp_info(dsp, "Firmware version: %d\n", header->ver);
	dsp->fw_ver = header->ver;
	dsp->wmfw_ver = header->ver;

	if (header->core != dsp->type) {
		cs_dsp_err(dsp, "%s: invalid core %d != %d\n",
@@ -1426,33 +1512,47 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,

	pos = sizeof(*header);
	pos = dsp->ops->parse_sizes(dsp, file, pos, firmware);
	if ((pos == 0) || (sizeof(*footer) > firmware->size - pos)) {
		ret = -EOVERFLOW;
		goto out_fw;
	}

	footer = (void *)&firmware->data[pos];
	pos += sizeof(*footer);

	if (le32_to_cpu(header->len) != pos) {
		cs_dsp_err(dsp, "%s: unexpected header length %d\n",
			   file, le32_to_cpu(header->len));
		ret = -EOVERFLOW;
		goto out_fw;
	}

	cs_dsp_dbg(dsp, "%s: timestamp %llu\n", file,
	cs_dsp_info(dsp, "%s: format %d timestamp %#llx\n", file, header->ver,
		    le64_to_cpu(footer->timestamp));

	while (pos < firmware->size &&
	       sizeof(*region) < firmware->size - pos) {
	while (pos < firmware->size) {
		/* Is there enough data for a complete block header? */
		if (sizeof(*region) > firmware->size - pos) {
			ret = -EOVERFLOW;
			goto out_fw;
		}

		region = (void *)&(firmware->data[pos]);

		if (le32_to_cpu(region->len) > firmware->size - pos - sizeof(*region)) {
			ret = -EOVERFLOW;
			goto out_fw;
		}

		region_name = "Unknown";
		reg = 0;
		text = NULL;
		offset = le32_to_cpu(region->offset) & 0xffffff;
		type = be32_to_cpu(region->type) & 0xff;

		switch (type) {
		case WMFW_INFO_TEXT:
		case WMFW_NAME_TEXT:
			region_name = "Firmware name";
			text = kzalloc(le32_to_cpu(region->len) + 1,
				       GFP_KERNEL);
			region_name = "Info/Name";
			cs_dsp_info(dsp, "%s: %.*s\n", file,
				    min(le32_to_cpu(region->len), 100), region->data);
			break;
		case WMFW_ALGORITHM_DATA:
			region_name = "Algorithm";
@@ -1460,11 +1560,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
			if (ret != 0)
				goto out_fw;
			break;
		case WMFW_INFO_TEXT:
			region_name = "Information";
			text = kzalloc(le32_to_cpu(region->len) + 1,
				       GFP_KERNEL);
			break;
		case WMFW_ABSOLUTE:
			region_name = "Absolute";
			reg = offset;
@@ -1498,23 +1593,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
			   regions, le32_to_cpu(region->len), offset,
			   region_name);

		if (le32_to_cpu(region->len) >
		    firmware->size - pos - sizeof(*region)) {
			cs_dsp_err(dsp,
				   "%s.%d: %s region len %d bytes exceeds file length %zu\n",
				   file, regions, region_name,
				   le32_to_cpu(region->len), firmware->size);
			ret = -EINVAL;
			goto out_fw;
		}

		if (text) {
			memcpy(text, region->data, le32_to_cpu(region->len));
			cs_dsp_info(dsp, "%s: %s\n", file, text);
			kfree(text);
			text = NULL;
		}

		if (reg) {
			buf = cs_dsp_buf_alloc(region->data,
					       le32_to_cpu(region->len),
@@ -1556,7 +1634,9 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
out_fw:
	regmap_async_complete(regmap);
	cs_dsp_buf_free(&buf_list);
	kfree(text);

	if (ret == -EOVERFLOW)
		cs_dsp_err(dsp, "%s: file content overflows file data\n", file);

	return ret;
}
@@ -1702,7 +1782,7 @@ static struct cs_dsp_alg_region *cs_dsp_create_region(struct cs_dsp *dsp,

	list_add_tail(&alg_region->list, &dsp->alg_regions);

	if (dsp->fw_ver > 0)
	if (dsp->wmfw_ver > 0)
		cs_dsp_ctl_fixup_base(dsp, alg_region);

	return alg_region;
@@ -1825,7 +1905,7 @@ static int cs_dsp_adsp1_setup_algs(struct cs_dsp *dsp)
			ret = PTR_ERR(alg_region);
			goto out;
		}
		if (dsp->fw_ver == 0) {
		if (dsp->wmfw_ver == 0) {
			if (i + 1 < n_algs) {
				len = be32_to_cpu(adsp1_alg[i + 1].dm);
				len -= be32_to_cpu(adsp1_alg[i].dm);
@@ -1847,7 +1927,7 @@ static int cs_dsp_adsp1_setup_algs(struct cs_dsp *dsp)
			ret = PTR_ERR(alg_region);
			goto out;
		}
		if (dsp->fw_ver == 0) {
		if (dsp->wmfw_ver == 0) {
			if (i + 1 < n_algs) {
				len = be32_to_cpu(adsp1_alg[i + 1].zm);
				len -= be32_to_cpu(adsp1_alg[i].zm);
@@ -1938,7 +2018,7 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp)
			ret = PTR_ERR(alg_region);
			goto out;
		}
		if (dsp->fw_ver == 0) {
		if (dsp->wmfw_ver == 0) {
			if (i + 1 < n_algs) {
				len = be32_to_cpu(adsp2_alg[i + 1].xm);
				len -= be32_to_cpu(adsp2_alg[i].xm);
@@ -1960,7 +2040,7 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp)
			ret = PTR_ERR(alg_region);
			goto out;
		}
		if (dsp->fw_ver == 0) {
		if (dsp->wmfw_ver == 0) {
			if (i + 1 < n_algs) {
				len = be32_to_cpu(adsp2_alg[i + 1].ym);
				len -= be32_to_cpu(adsp2_alg[i].ym);
@@ -1982,7 +2062,7 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp)
			ret = PTR_ERR(alg_region);
			goto out;
		}
		if (dsp->fw_ver == 0) {
		if (dsp->wmfw_ver == 0) {
			if (i + 1 < n_algs) {
				len = be32_to_cpu(adsp2_alg[i + 1].zm);
				len -= be32_to_cpu(adsp2_alg[i].zm);
@@ -2086,7 +2166,6 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
	struct cs_dsp_alg_region *alg_region;
	const char *region_name;
	int ret, pos, blocks, type, offset, reg, version;
	char *text = NULL;
	struct cs_dsp_buf *buf;

	if (!firmware)
@@ -2125,10 +2204,20 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
	pos = le32_to_cpu(hdr->len);

	blocks = 0;
	while (pos < firmware->size &&
	       sizeof(*blk) < firmware->size - pos) {
	while (pos < firmware->size) {
		/* Is there enough data for a complete block header? */
		if (sizeof(*blk) > firmware->size - pos) {
			ret = -EOVERFLOW;
			goto out_fw;
		}

		blk = (void *)(&firmware->data[pos]);

		if (le32_to_cpu(blk->len) > firmware->size - pos - sizeof(*blk)) {
			ret = -EOVERFLOW;
			goto out_fw;
		}

		type = le16_to_cpu(blk->type);
		offset = le16_to_cpu(blk->offset);
		version = le32_to_cpu(blk->ver) >> 8;
@@ -2145,7 +2234,8 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
		region_name = "Unknown";
		switch (type) {
		case (WMFW_NAME_TEXT << 8):
			text = kzalloc(le32_to_cpu(blk->len) + 1, GFP_KERNEL);
			cs_dsp_info(dsp, "%s: %.*s\n", dsp->fw_name,
				    min(le32_to_cpu(blk->len), 100), blk->data);
			break;
		case (WMFW_INFO_TEXT << 8):
		case (WMFW_METADATA << 8):
@@ -2217,25 +2307,7 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
			break;
		}

		if (text) {
			memcpy(text, blk->data, le32_to_cpu(blk->len));
			cs_dsp_info(dsp, "%s: %s\n", dsp->fw_name, text);
			kfree(text);
			text = NULL;
		}

		if (reg) {
			if (le32_to_cpu(blk->len) >
			    firmware->size - pos - sizeof(*blk)) {
				cs_dsp_err(dsp,
					   "%s.%d: %s region len %d bytes exceeds file length %zu\n",
					   file, blocks, region_name,
					   le32_to_cpu(blk->len),
					   firmware->size);
				ret = -EINVAL;
				goto out_fw;
			}

			buf = cs_dsp_buf_alloc(blk->data,
					       le32_to_cpu(blk->len),
					       &buf_list);
@@ -2274,7 +2346,10 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
out_fw:
	regmap_async_complete(regmap);
	cs_dsp_buf_free(&buf_list);
	kfree(text);

	if (ret == -EOVERFLOW)
		cs_dsp_err(dsp, "%s: file content overflows file data\n", file);

	return ret;
}

@@ -2337,8 +2412,8 @@ EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp1_init, FW_CS_DSP);
 * Return: Zero for success, a negative number on error.
 */
int cs_dsp_adsp1_power_up(struct cs_dsp *dsp,
			  const struct firmware *wmfw_firmware, char *wmfw_filename,
			  const struct firmware *coeff_firmware, char *coeff_filename,
			  const struct firmware *wmfw_firmware, const char *wmfw_filename,
			  const struct firmware *coeff_firmware, const char *coeff_filename,
			  const char *fw_name)
{
	unsigned int val;
@@ -2631,8 +2706,8 @@ static void cs_dsp_halo_stop_watchdog(struct cs_dsp *dsp)
 * Return: Zero for success, a negative number on error.
 */
int cs_dsp_power_up(struct cs_dsp *dsp,
		    const struct firmware *wmfw_firmware, char *wmfw_filename,
		    const struct firmware *coeff_firmware, char *coeff_filename,
		    const struct firmware *wmfw_firmware, const char *wmfw_filename,
		    const struct firmware *coeff_firmware, const char *coeff_filename,
		    const char *fw_name)
{
	int ret;
+5 −5
Original line number Diff line number Diff line
@@ -167,7 +167,7 @@ struct cs_dsp {
	const struct cs_dsp_region *mem;
	int num_mems;

	int fw_ver;
	int wmfw_ver;

	bool booted;
	bool running;
@@ -213,13 +213,13 @@ int cs_dsp_adsp2_init(struct cs_dsp *dsp);
int cs_dsp_halo_init(struct cs_dsp *dsp);

int cs_dsp_adsp1_power_up(struct cs_dsp *dsp,
			  const struct firmware *wmfw_firmware, char *wmfw_filename,
			  const struct firmware *coeff_firmware, char *coeff_filename,
			  const struct firmware *wmfw_firmware, const char *wmfw_filename,
			  const struct firmware *coeff_firmware, const char *coeff_filename,
			  const char *fw_name);
void cs_dsp_adsp1_power_down(struct cs_dsp *dsp);
int cs_dsp_power_up(struct cs_dsp *dsp,
		    const struct firmware *wmfw_firmware, char *wmfw_filename,
		    const struct firmware *coeff_firmware, char *coeff_filename,
		    const struct firmware *wmfw_firmware, const char *wmfw_filename,
		    const struct firmware *coeff_firmware, const char *coeff_filename,
		    const char *fw_name);
void cs_dsp_power_down(struct cs_dsp *dsp);
int cs_dsp_run(struct cs_dsp *dsp);
+7 −0
Original line number Diff line number Diff line
@@ -283,6 +283,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
			DMI_MATCH(DMI_PRODUCT_NAME, "M5402RA"),
		}
	},
        {
		.driver_data = &acp6x_card,
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
			DMI_MATCH(DMI_PRODUCT_NAME, "M5602RA"),
		}
	},
	{
		.driver_data = &acp6x_card,
		.matches = {
+18 −6
Original line number Diff line number Diff line
@@ -81,7 +81,7 @@ static const struct reg_sequence init_list[] = {
static const struct reg_sequence rt5650_init_list[] = {
	{0xf6,	0x0100},
	{RT5645_PWR_ANLG1, 0x02},
	{RT5645_IL_CMD3, 0x0018},
	{RT5645_IL_CMD3, 0x6728},
};

static const struct reg_default rt5645_reg[] = {
@@ -3130,20 +3130,32 @@ static void rt5645_enable_push_button_irq(struct snd_soc_component *component,
	bool enable)
{
	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
	int ret;

	if (enable) {
		snd_soc_dapm_force_enable_pin(dapm, "ADC L power");
		snd_soc_dapm_force_enable_pin(dapm, "ADC R power");
		snd_soc_dapm_sync(dapm);

		snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD2,
			RT5645_EN_4BTN_IL_MASK | RT5645_RST_4BTN_IL_MASK,
			RT5645_EN_4BTN_IL_EN | RT5645_RST_4BTN_IL_RST);
		usleep_range(10000, 15000);
		snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD2,
			RT5645_EN_4BTN_IL_MASK | RT5645_RST_4BTN_IL_MASK,
			RT5645_EN_4BTN_IL_EN | RT5645_RST_4BTN_IL_NORM);
		msleep(50);
		ret = snd_soc_component_read(component, RT5645_INT_IRQ_ST);
		pr_debug("%s read %x = %x\n", __func__, RT5645_INT_IRQ_ST,
			snd_soc_component_read(component, RT5645_INT_IRQ_ST));
		snd_soc_component_write(component, RT5645_INT_IRQ_ST, ret);
		ret = snd_soc_component_read(component, RT5650_4BTN_IL_CMD1);
		pr_debug("%s read %x = %x\n", __func__, RT5650_4BTN_IL_CMD1,
			snd_soc_component_read(component, RT5650_4BTN_IL_CMD1));
		snd_soc_component_write(component, RT5650_4BTN_IL_CMD1, ret);
		snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD1, 0x3, 0x3);
		snd_soc_component_update_bits(component,
					RT5645_INT_IRQ_ST, 0x8, 0x8);
		snd_soc_component_update_bits(component,
					RT5650_4BTN_IL_CMD2, 0x8000, 0x8000);
		snd_soc_component_read(component, RT5650_4BTN_IL_CMD1);
		pr_debug("%s read %x = %x\n", __func__, RT5650_4BTN_IL_CMD1,
			snd_soc_component_read(component, RT5650_4BTN_IL_CMD1));
	} else {
		snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD2, 0x8000, 0x0);
		snd_soc_component_update_bits(component, RT5645_INT_IRQ_ST, 0x8, 0x0);
+6 −0
Original line number Diff line number Diff line
@@ -2011,6 +2011,12 @@
#define RT5645_ZCD_HP_DIS			(0x0 << 15)
#define RT5645_ZCD_HP_EN			(0x1 << 15)

/* Buttons Inline Command Function 2 (0xe0) */
#define RT5645_EN_4BTN_IL_MASK			(0x1 << 15)
#define RT5645_EN_4BTN_IL_EN			(0x1 << 15)
#define RT5645_RST_4BTN_IL_MASK			(0x1 << 14)
#define RT5645_RST_4BTN_IL_RST			(0x0 << 14)
#define RT5645_RST_4BTN_IL_NORM			(0x1 << 14)

/* Codec Private Register definition */
/* DAC ADC Digital Volume (0x00) */
Loading