[alsa-devel] [PATCH 11/19] ALSA: ymu831: add data parser
Yoichi Yuasa
yuasa at linux-mips.org
Wed Jan 16 09:37:04 CET 2013
Signed-off-by: Yoichi Yuasa <yuasa at linux-mips.org>
---
sound/soc/codecs/ymu831/Makefile | 3 +-
sound/soc/codecs/ymu831/mcparser.c | 1132 ++++++++++++++++++++++++++++++++++++
sound/soc/codecs/ymu831/mcparser.h | 40 ++
3 files changed, 1174 insertions(+), 1 deletion(-)
create mode 100644 sound/soc/codecs/ymu831/mcparser.c
create mode 100644 sound/soc/codecs/ymu831/mcparser.h
diff --git a/sound/soc/codecs/ymu831/Makefile b/sound/soc/codecs/ymu831/Makefile
index 01f5910..820dec7 100644
--- a/sound/soc/codecs/ymu831/Makefile
+++ b/sound/soc/codecs/ymu831/Makefile
@@ -5,6 +5,7 @@ snd-soc-ymu831-objs := \
mcdriver.o \
mcedspdrv.o \
mcfdspdrv.o \
- mcpacking.o
+ mcpacking.o \
+ mcparser.o
obj-$(CONFIG_SND_SOC_YMU831) += snd-soc-ymu831.o
diff --git a/sound/soc/codecs/ymu831/mcparser.c b/sound/soc/codecs/ymu831/mcparser.c
new file mode 100644
index 0000000..b2ba4bc
--- /dev/null
+++ b/sound/soc/codecs/ymu831/mcparser.c
@@ -0,0 +1,1132 @@
+/****************************************************************************
+ *
+ * Copyright(c) 2012 Yamaha Corporation. All rights reserved.
+ *
+ * Module : mcparser.c
+ * Description : MC data parser
+ * Version : 1.0.0 Dec 13 2012
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ ****************************************************************************/
+/*
+ * changelog:
+ * - change in the Linux coding style
+ * - remove unnecessary comments
+ * - remove unused codes
+ */
+#include <linux/errno.h>
+#include <linux/types.h>
+
+#include <asm/byteorder.h>
+
+#include "mcbdspdrv.h"
+#include "mccdspdrv.h"
+#include "mcdriver.h"
+#include "mcedspdrv.h"
+#include "mcfdspdrv.h"
+#include "mcparser.h"
+
+#define AEC_MIN_BYTES 12
+#define AEC_REVISION 5
+#define AEC_TARGET 253
+
+#define AEC_D7_MIN_BYTES 6
+#define AEC_D7_CHUNK_CONFIG 0x01000000
+#define AEC_D7_CHUNK_AE 0x02000000
+#define AEC_D7_CHUNK_BDSP_ES1 0x00010000
+#define AEC_D7_CHUNK_BDSP 0x00010001
+#define AEC_D7_CHUNK_FDSP_ES1 0x00020000
+#define AEC_D7_CHUNK_FDSP 0x00020001
+#define AEC_D7_CHUNK_VBOX 0x03000000
+#define AEC_D7_CHUNK_CDSPA 0x00030000
+#define AEC_D7_CHUNK_CDSPB 0x00030001
+#define AEC_D7_CHUNK_CDSP_DEBUG 0x00050000
+#define AEC_D7_CHUNK_OUTPUT0_ES1 0x04000000
+#define AEC_D7_CHUNK_OUTPUT1_ES1 0x04000001
+#define AEC_D7_CHUNK_OUTPUT0 0x04000002
+#define AEC_D7_CHUNK_OUTPUT1 0x04000003
+#define AEC_D7_CHUNK_SYSEQ_EX 0x00060000
+#define AEC_D7_CHUNK_INPUT0 0x05000000
+#define AEC_D7_CHUNK_INPUT1 0x05000001
+#define AEC_D7_CHUNK_INPUT2 0x05000002
+#define AEC_D7_CHUNK_PDM 0x06000000
+#define AEC_D7_CHUNK_E2 0x07000000
+#define AEC_D7_CHUNK_E2_CONFIG 0x00040000
+#define AEC_D7_CHUNK_ADJ 0x08000000
+#define AEC_D7_CHUNK_EDSP_MISC 0x09000000
+#define AEC_D7_CHUNK_CONTROL 0x0A000000
+
+struct mcdrv_aec_d7_info {
+ u8 *top;
+ u32 size;
+};
+
+static int analyze_audioengine_sub_data(u8 *data, u32 *offset, u32 *data_size,
+ struct mcdrv_aec_info *aec)
+{
+ enum mcdrv_dev_id dev_id;
+ u32 id, size;
+
+ dev_id = mc_dev_id_get();
+
+ while (*data_size > 0) {
+ if (*data_size < 8)
+ return -EINVAL;
+
+ id = htonl(*(u32 *) (data + *offset));
+ size = htonl(*(u32 *) (data + *offset + 4));
+
+ *data_size -= 8;
+ if (*data_size < size)
+ return -EINVAL;
+
+ if ((id == AEC_D7_CHUNK_BDSP_ES1 &&
+ dev_id == MCDRV_DEV_ID_80_90H) ||
+ (id == AEC_D7_CHUNK_BDSP &&
+ dev_id != MCDRV_DEV_ID_80_90H)) {
+ if (aec->audio_engine.bdsp.data)
+ return -EINVAL;
+
+ aec->audio_engine.bdsp.data = data + *offset;
+ aec->audio_engine.bdsp.data_size = size;
+ } else if ((id == AEC_D7_CHUNK_FDSP_ES1 &&
+ dev_id == MCDRV_DEV_ID_80_90H) ||
+ (id == AEC_D7_CHUNK_FDSP &&
+ dev_id != MCDRV_DEV_ID_80_90H)) {
+ if (aec->audio_engine.fdsp.data)
+ return -EINVAL;
+
+ aec->audio_engine.fdsp.data = data + *offset;
+ aec->audio_engine.fdsp.data_size = size;
+ } else
+ return -EINVAL;
+
+ *offset += size + 8;
+ *data_size -= size;
+ }
+
+ return 0;
+}
+
+static int analyze_vbox_sub_data(u8 *data, u32 *offset, u32 *data_size,
+ struct mcdrv_aec_info *aec)
+{
+ enum mcdrv_dev_id dev_id;
+ u32 id, size;
+
+ dev_id = mc_dev_id_get();
+
+ while (*data_size > 0) {
+ if (*data_size < 8)
+ return -EINVAL;
+
+ id = htonl(*(u32 *) (data + *offset));
+ size = htonl(*(u32 *) (data + *offset + 4));
+
+ *data_size -= 8;
+ if (*data_size < size)
+ return -EINVAL;
+
+ if (id == AEC_D7_CHUNK_CDSPA) {
+ if (aec->vbox.cdsp_a.data)
+ return -EINVAL;
+
+ aec->vbox.cdsp_a.data = data + *offset;
+ aec->vbox.cdsp_a.data_size = size;
+ } else if (id == AEC_D7_CHUNK_CDSPB) {
+ if (aec->vbox.cdsp_b.data)
+ return -EINVAL;
+
+ aec->vbox.cdsp_b.data = data + *offset;
+ aec->vbox.cdsp_b.data_size = size;
+ } else if ((id == AEC_D7_CHUNK_FDSP_ES1 &&
+ dev_id == MCDRV_DEV_ID_80_90H) ||
+ (id == AEC_D7_CHUNK_FDSP &&
+ dev_id != MCDRV_DEV_ID_80_90H)) {
+ if (aec->vbox.fdsp.data)
+ return -EINVAL;
+
+ aec->vbox.fdsp.data = data + *offset;
+ aec->vbox.fdsp.data_size = size;
+ } else if (id == AEC_D7_CHUNK_CDSP_DEBUG) {
+ if (size != 1)
+ return -EINVAL;
+
+ if (aec->vbox.cdsp_jtag_on != 0xff)
+ return -EINVAL;
+ if (data[*offset + 8] > 1)
+ return -EINVAL;
+ aec->vbox.cdsp_jtag_on = data[*offset + 8];
+ } else
+ return -EINVAL;
+
+ *offset += size + 8;
+ *data_size -= size;
+ }
+
+ return 0;
+}
+
+static int analyze_edsp_sub_data(u8 *data, u32 *offset, u32 *data_size,
+ struct mcdrv_aec_info *aec)
+{
+ u32 id, size;
+
+ while (*data_size > 0) {
+ if (*data_size < 8)
+ return -EINVAL;
+
+ id = htonl(*(u32 *) (data + *offset));
+ size = htonl(*(u32 *) (data + *offset + 4));
+
+ *data_size -= 8;
+ if (*data_size < size)
+ return -EINVAL;
+
+ if (id == AEC_D7_CHUNK_E2_CONFIG) {
+ if (aec->e2.config.data)
+ return -EINVAL;
+
+ aec->e2.config.data = data + *offset;
+ aec->e2.config.data_size = size;
+
+ *offset += size + 8;
+ *data_size -= size;
+ } else
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int get_d7_info(u8 *data, u32 size, struct mcdrv_aec_d7_info *d7_info)
+{
+ u32 data_size, offset, chunk_size;
+
+ if (size < AEC_MIN_BYTES)
+ return -EINVAL;
+
+ /* header */
+ if (data[0] != 0x41 || data[1] != 0x45 || data[2] != 0x43)
+ return -EINVAL;
+
+ /* revision */
+ if (data[3] != AEC_REVISION)
+ return -EINVAL;
+
+ /* size */
+ data_size = htonl(*(u32 *) (data + 4));
+ if (size != data_size + 8)
+ return -EINVAL;
+
+ /* target */
+ if (data[9] != AEC_TARGET)
+ return -EINVAL;
+
+ /* Reserved */
+ if (data[11] != 0x00)
+ return -EINVAL;
+
+ /* D7 Chunk Search */
+ d7_info->top = NULL;
+ d7_info->size = 0;
+ offset = AEC_MIN_BYTES;
+
+ while ((offset + AEC_D7_MIN_BYTES) < size) {
+ if (data[offset] == 0x44 && data[offset + 1] == 0x37) {
+ if (d7_info->top)
+ return -EINVAL;
+
+ chunk_size = htonl(*(u32 *) (data + offset + 2));
+ if ((offset + AEC_D7_MIN_BYTES + chunk_size) > size)
+ return -EINVAL;
+
+ d7_info->top = data + offset + AEC_D7_MIN_BYTES;
+ d7_info->size = chunk_size;
+ } else
+ return -EINVAL;
+
+ /* Next Chunk */
+ offset += chunk_size + AEC_D7_MIN_BYTES;
+ }
+
+ if (!d7_info->top)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int analyze_syseq_ex_sub_data(u8 *data, u32 *offset, u32 *sub_size,
+ struct mcdrv_aec_syseq_ex *syseq_ex)
+{
+ u32 id, size;
+
+ while (*sub_size > 0) {
+ if (*sub_size < 8)
+ return -EINVAL;
+
+ id = htonl(*(u32 *) (data + *offset));
+ size = htonl(*(u32 *) (data + *offset + 4));
+
+ *offset += 8;
+ *sub_size -= 8;
+ if (*sub_size < size)
+ return -EINVAL;
+
+ if (id == AEC_D7_CHUNK_SYSEQ_EX) {
+ if (size != 30)
+ return -EINVAL;
+
+ if (syseq_ex->enable)
+ return -EINVAL;
+
+ syseq_ex->enable = true;
+ syseq_ex->band[0].coef_a0[0] = data[*offset++];
+ syseq_ex->band[0].coef_a0[1] = data[*offset++];
+ syseq_ex->band[0].coef_a0[2] = data[*offset++];
+ syseq_ex->band[0].coef_a1[0] = data[*offset++];
+ syseq_ex->band[0].coef_a1[1] = data[*offset++];
+ syseq_ex->band[0].coef_a1[2] = data[*offset++];
+ syseq_ex->band[0].coef_a2[0] = data[*offset++];
+ syseq_ex->band[0].coef_a2[1] = data[*offset++];
+ syseq_ex->band[0].coef_a2[2] = data[*offset++];
+ syseq_ex->band[0].coef_b1[0] = data[*offset++];
+ syseq_ex->band[0].coef_b1[1] = data[*offset++];
+ syseq_ex->band[0].coef_b1[2] = data[*offset++];
+ syseq_ex->band[0].coef_b2[0] = data[*offset++];
+ syseq_ex->band[0].coef_b2[1] = data[*offset++];
+ syseq_ex->band[0].coef_b2[2] = data[*offset++];
+ syseq_ex->band[1].coef_a0[0] = data[*offset++];
+ syseq_ex->band[1].coef_a0[1] = data[*offset++];
+ syseq_ex->band[1].coef_a0[2] = data[*offset++];
+ syseq_ex->band[1].coef_a1[0] = data[*offset++];
+ syseq_ex->band[1].coef_a1[1] = data[*offset++];
+ syseq_ex->band[1].coef_a1[2] = data[*offset++];
+ syseq_ex->band[1].coef_a2[0] = data[*offset++];
+ syseq_ex->band[1].coef_a2[1] = data[*offset++];
+ syseq_ex->band[1].coef_a2[2] = data[*offset++];
+ syseq_ex->band[1].coef_b1[0] = data[*offset++];
+ syseq_ex->band[1].coef_b1[1] = data[*offset++];
+ syseq_ex->band[1].coef_b1[2] = data[*offset++];
+ syseq_ex->band[1].coef_b2[0] = data[*offset++];
+ syseq_ex->band[1].coef_b2[1] = data[*offset++];
+ syseq_ex->band[1].coef_b2[2] = data[*offset++];
+ *sub_size -= size;
+ } else
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int mc_parser_d7_data_analyze(u8 *data, u32 size, struct mcdrv_aec_info *aec)
+{
+ struct mcdrv_aec_d7_info d7_info;
+ enum mcdrv_dev_id dev_id;
+ u8 *d7_data;
+ u32 offset, d7_data_end;
+ u32 id, sub_size;
+ int n, ret;
+
+ ret = get_d7_info(data, size, &d7_info);
+ if (ret < 0)
+ return ret;
+
+ dev_id = mc_dev_id_get();
+
+ d7_data = d7_info.top;
+ d7_data_end = d7_info.size - 1;
+
+ aec->fdsp_locate = 0xFF;
+ aec->audio_engine.enable = false;
+ aec->audio_engine.bdsp.data = NULL;
+ aec->audio_engine.bdsp.data_size = 0;
+ aec->audio_engine.fdsp.data = NULL;
+ aec->audio_engine.fdsp.data_size = 0;
+ aec->vbox.enable = false;
+ aec->vbox.cdsp_a.data = NULL;
+ aec->vbox.cdsp_a.data_size = 0;
+ aec->vbox.cdsp_b.data = NULL;
+ aec->vbox.cdsp_b.data_size = 0;
+ aec->vbox.fdsp.data = NULL;
+ aec->vbox.fdsp.data_size = 0;
+ aec->vbox.cdsp_jtag_on = 0xff;
+ aec->output.lpf_pre_thru[0] = 0xFF;
+ aec->output.lpf_pre_thru[1] = 0xFF;
+ aec->input.dsf32_l_type[0] = 0xFF;
+ aec->input.dsf32_l_type[1] = 0xFF;
+ aec->input.dsf32_l_type[2] = 0xFF;
+ aec->pdm.mode = 0xFF;
+ aec->e2.enable = false;
+ aec->e2.config.data = NULL;
+ aec->e2.config.data_size = 0;
+ aec->adj.hold = 0xFF;
+ aec->edsp_misc.i2s_out_enable = 0xFF;
+ aec->control.command = 0xFF;
+
+ offset = 0;
+ while (offset <= d7_data_end && !ret) {
+ if ((offset + 8 - 1) > d7_data_end) {
+ ret = -EINVAL;
+ break;
+ }
+
+ id = htonl(*(u32 *) (d7_data + offset));
+ sub_size = htonl(*(u32 *) (d7_data + offset + 4));
+
+ offset += 8;
+ if ((offset + sub_size - 1) > d7_data_end) {
+ ret = -EINVAL;
+ break;
+ }
+
+ switch (id) {
+ case AEC_D7_CHUNK_CONFIG:
+ if (sub_size != 1 || aec->fdsp_locate != 0xFF ||
+ d7_data[offset] > 1) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->fdsp_locate = d7_data[offset++];
+ sub_size = 0;
+ break;
+ case AEC_D7_CHUNK_AE:
+ if (sub_size < 8 || aec->audio_engine.enable ||
+ d7_data[offset] > 2) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->audio_engine.enable = true;
+ aec->audio_engine.on = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 2) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->audio_engine.fdsp_on = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 2) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->audio_engine.bdsp_ae0_src = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 2) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->audio_engine.bdsp_ae1_src = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 2) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->audio_engine.mixer_in0_src = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 2) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->audio_engine.mixer_in1_src = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 2) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->audio_engine.mixer_in2_src = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 2) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->audio_engine.mixer_in3_src = d7_data[offset++];
+ sub_size--;
+
+ if (sub_size > 0) {
+ ret = analyze_audioengine_sub_data(d7_data,
+ &offset,
+ &sub_size,
+ aec);
+ }
+ break;
+ case AEC_D7_CHUNK_VBOX:
+ if (sub_size < 15 || aec->vbox.enable) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->vbox.enable = true;
+
+ if (d7_data[offset] > 2 && d7_data[offset] != 0x11) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->vbox.cdsp_func_a_on = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 2 && d7_data[offset] != 0x11) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->vbox.cdsp_func_b_on = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 2) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->vbox.fdsp_on = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 0x3F && d7_data[offset] < 0xFF) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->vbox.fdsp_po_source = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 1 && d7_data[offset] < 0xFF) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->vbox.isrc2_vsource = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 1 && d7_data[offset] < 0xFF) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->vbox.isrc2_ch1_vsource = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 1 && d7_data[offset] < 0xFF) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->vbox.isrc3_vsource = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 1 && d7_data[offset] < 0xFF) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->vbox.lpt2_vsource = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 3 && d7_data[offset] < 0xFF) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->vbox.lpt2_mix_vol_o = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 3 && d7_data[offset] < 0xFF) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->vbox.lpt2_mix_vol_i = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 3 && d7_data[offset] < 0xFF) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->vbox.src3_ctrl = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] == 3 || d7_data[offset] == 7 ||
+ d7_data[offset] == 11 ||
+ (d7_data[offset] > 13 && d7_data[offset] < 0xFF)) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->vbox.src2_fs = d7_data[offset++];
+ sub_size--;
+
+ if (dev_id == MCDRV_DEV_ID_80_90H) {
+ if (d7_data[offset] > 1 &&
+ d7_data[offset] < 0xFF) {
+ ret = -EINVAL;
+ break;
+ }
+ aec->vbox.src2_thru = d7_data[offset++];
+ } else
+ offset++;
+ sub_size--;
+
+ if (d7_data[offset] == 3 || d7_data[offset] == 7 ||
+ d7_data[offset] == 11 ||
+ (d7_data[offset] > 13 && d7_data[offset] < 0xFF)) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->vbox.src3_fs = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 1 && d7_data[offset] < 0xFF) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->vbox.src3_thru = d7_data[offset++];
+ sub_size--;
+
+ if (sub_size > 0) {
+ ret = analyze_vbox_sub_data(d7_data,
+ &offset,
+ &sub_size, aec);
+ }
+ break;
+ case AEC_D7_CHUNK_OUTPUT0_ES1:
+ case AEC_D7_CHUNK_OUTPUT1_ES1:
+ case AEC_D7_CHUNK_OUTPUT0:
+ case AEC_D7_CHUNK_OUTPUT1:
+ if (dev_id == MCDRV_DEV_ID_80_90H) {
+ if (id != AEC_D7_CHUNK_OUTPUT0_ES1 &&
+ id != AEC_D7_CHUNK_OUTPUT1_ES1)
+ break;
+ n = id - AEC_D7_CHUNK_OUTPUT0_ES1;
+ } else {
+ if (id != AEC_D7_CHUNK_OUTPUT0 &&
+ id != AEC_D7_CHUNK_OUTPUT1)
+ break;
+ n = id - AEC_D7_CHUNK_OUTPUT0;
+ }
+ if (sub_size < 47 ||
+ aec->output.lpf_pre_thru[n] != 0xFF ||
+ d7_data[offset] > 1) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->output.lpf_pre_thru[n] = d7_data[offset++];
+
+ if (d7_data[offset] > 1) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->output.lpf_post_thru[n] = d7_data[offset++];
+
+ if (d7_data[offset] > 3) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->output.dcc_sel[n] = d7_data[offset++];
+
+ if (d7_data[offset] > 5) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->output.signal_detect_level = d7_data[offset++];
+
+ if (d7_data[offset] > 3) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->output.power_detect_level[n] = d7_data[offset++];
+
+ if (d7_data[offset] > 3) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->output.osf_sel[n] = d7_data[offset++];
+
+ if (dev_id == MCDRV_DEV_ID_80_90H) {
+ if (d7_data[offset] > 1) {
+ ret = -EINVAL;
+ break;
+ }
+ } else {
+ if (d7_data[offset] > 7) {
+ ret = -EINVAL;
+ break;
+ }
+ }
+ aec->output.syseq_enb[n] = d7_data[offset++];
+ aec->output.syseq_coef_a0[n][0] = d7_data[offset++];
+ aec->output.syseq_coef_a0[n][1] = d7_data[offset++];
+ aec->output.syseq_coef_a0[n][2] = d7_data[offset++];
+ aec->output.syseq_coef_a1[n][0] = d7_data[offset++];
+ aec->output.syseq_coef_a1[n][1] = d7_data[offset++];
+ aec->output.syseq_coef_a1[n][2] = d7_data[offset++];
+ aec->output.syseq_coef_a2[n][0] = d7_data[offset++];
+ aec->output.syseq_coef_a2[n][1] = d7_data[offset++];
+ aec->output.syseq_coef_a2[n][2] = d7_data[offset++];
+ aec->output.syseq_coef_b1[n][0] = d7_data[offset++];
+ aec->output.syseq_coef_b1[n][1] = d7_data[offset++];
+ aec->output.syseq_coef_b1[n][2] = d7_data[offset++];
+ aec->output.syseq_coef_b2[n][0] = d7_data[offset++];
+ aec->output.syseq_coef_b2[n][1] = d7_data[offset++];
+ aec->output.syseq_coef_b2[n][2] = d7_data[offset++];
+
+ if (d7_data[offset] > 7) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->output.clip_md[n] = d7_data[offset++];
+ aec->output.clip_att[n] = d7_data[offset++];
+ aec->output.clip_rel[n] = d7_data[offset++];
+ aec->output.clip_g[n] = d7_data[offset++];
+ aec->output.osf_gain[n][0] = d7_data[offset++];
+ aec->output.osf_gain[n][1] = d7_data[offset++];
+
+ if (d7_data[offset] > 1) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->output.dcl_on[n] = d7_data[offset++];
+
+ if (d7_data[offset] > 3) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->output.dcl_gain[n] = d7_data[offset++];
+
+ if (d7_data[offset] > 0x7F) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->output.dcl_limit[n][0] = d7_data[offset++];
+ aec->output.dcl_limit[n][1] = d7_data[offset++];
+
+ if (dev_id == MCDRV_DEV_ID_80_90H) {
+ if (d7_data[offset] > 1) {
+ ret = -EINVAL;
+ break;
+ }
+ aec->output.random_dither_on[n] =
+ d7_data[offset++];
+ } else
+ offset++;
+
+ if (dev_id == MCDRV_DEV_ID_80_90H) {
+ if (d7_data[offset] > 3) {
+ ret = -EINVAL;
+ break;
+ }
+ aec->output.random_dither_level[n] =
+ d7_data[offset++];
+ } else
+ offset++;
+
+ if (dev_id == MCDRV_DEV_ID_80_90H) {
+ if (d7_data[offset] > 1) {
+ ret = -EINVAL;
+ break;
+ }
+ aec->output.random_dither_pos[n] =
+ d7_data[offset++];
+ } else
+ offset++;
+
+ if (d7_data[offset] > 1) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->output.dc_dither_on[n] = d7_data[offset++];
+
+ if (dev_id == MCDRV_DEV_ID_80_90H) {
+ if (d7_data[offset] > 15) {
+ ret = -EINVAL;
+ break;
+ }
+ aec->output.dc_dither_level[n] =
+ d7_data[offset++];
+ } else
+ offset++;
+
+ if (d7_data[offset] > 1) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->output.dither_type[n] = d7_data[offset++];
+
+ if (d7_data[offset] > 1) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->output.dng_on[n] = d7_data[offset++];
+
+ if (d7_data[offset] > 31) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->output.dng_zero[n] = d7_data[offset++];
+
+ if (d7_data[offset] > 2) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->output.dng_time[n] = d7_data[offset++];
+ if (d7_data[offset] > 1) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->output.dng_fw[n] = d7_data[offset++];
+ aec->output.dng_attack = d7_data[offset++];
+ aec->output.dng_release = d7_data[offset++];
+ aec->output.dng_target[n] = d7_data[offset++];
+ aec->output.dng_target_lineout[n] = d7_data[offset++];
+ if (n == 0)
+ aec->output.dng_target_rc = d7_data[offset++];
+ else
+ offset++;
+
+ sub_size -= 47;
+ if (sub_size > 0)
+ ret = analyze_syseq_ex_sub_data(data, &offset,
+ &sub_size,
+ &aec->output.
+ syseq_ex[n]);
+ break;
+ case AEC_D7_CHUNK_INPUT0:
+ case AEC_D7_CHUNK_INPUT1:
+ case AEC_D7_CHUNK_INPUT2:
+ n = id - AEC_D7_CHUNK_INPUT0;
+ if (sub_size < 16 ||
+ aec->input.dsf32_l_type[n] != 0xFF ||
+ (n == 0 && d7_data[offset] > 2) ||
+ (n != 0 && d7_data[offset] > 1)) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->input.dsf32_l_type[n] = d7_data[offset++];
+
+ if ((n == 0 && d7_data[offset] > 2) ||
+ (n != 0 && d7_data[offset] > 1)) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->input.dsf32_r_type[n] = d7_data[offset++];
+
+ if (d7_data[offset] > 1) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->input.dsf4_sel[n] = d7_data[offset++];
+ if (d7_data[offset] > 3) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->input.dcc_sel[n] = d7_data[offset++];
+
+ if (d7_data[offset] > 1) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->input.dng_on[n] = d7_data[offset++];
+
+ if (d7_data[offset] > 3) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->input.dng_att[n] = d7_data[offset++];
+ if (d7_data[offset] > 3) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->input.dng_rel[n] = d7_data[offset++];
+
+ if (d7_data[offset] > 1) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->input.dng_fw[n] = d7_data[offset++];
+
+ if (d7_data[offset] > 0x3F) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->input.dng_time[n] = d7_data[offset++];
+ aec->input.dng_zero[n][0] = d7_data[offset++];
+ aec->input.dng_zero[n][1] = d7_data[offset++];
+ aec->input.dng_target[n][0] = d7_data[offset++];
+ aec->input.dng_target[n][1] = d7_data[offset++];
+
+ if (d7_data[offset] > 3) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->input.depop_att[n] = d7_data[offset++];
+
+ if (d7_data[offset] > 3) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->input.depop_wait[n] = d7_data[offset++];
+ if (n == 2) {
+ if (d7_data[offset] > 1) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->input.ref_sel = d7_data[offset++];
+ } else
+ offset++;
+
+ sub_size = 0;
+ break;
+ case AEC_D7_CHUNK_PDM:
+ if (sub_size != 10 || aec->pdm.mode != 0xFF ||
+ d7_data[offset] > 3) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->pdm.mode = d7_data[offset++];
+
+ if (d7_data[offset] > 3) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->pdm.st_wait = d7_data[offset++];
+
+ if (d7_data[offset] > 7) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->pdm.pdm0_loadtime = d7_data[offset++];
+
+ if (d7_data[offset] > 63) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->pdm.pdm0_l_finedelay = d7_data[offset++];
+
+ if (d7_data[offset] > 63) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->pdm.pdm0_r_finedelay = d7_data[offset++];
+
+ if (d7_data[offset] > 7) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->pdm.pdm1_loadtime = d7_data[offset++];
+
+ if (d7_data[offset] > 63) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->pdm.pdm1_l_finedelay = d7_data[offset++];
+
+ if (d7_data[offset] > 63) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->pdm.pdm1_r_finedelay = d7_data[offset++];
+
+ if (d7_data[offset] > 1) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->pdm.pdm0_data_delay = d7_data[offset++];
+
+ if (d7_data[offset] > 1) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->pdm.pdm1_data_delay = d7_data[offset++];
+
+ sub_size = 0;
+ break;
+ case AEC_D7_CHUNK_E2:
+ if (sub_size < 3 || aec->e2.enable) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->e2.enable = true;
+
+ if (d7_data[offset] > 4) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->e2.da_sel = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 8) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->e2.ad_sel = d7_data[offset++];
+ sub_size--;
+
+ if (d7_data[offset] > 2) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->e2.on = d7_data[offset++];
+ sub_size--;
+
+ if (sub_size > 0) {
+ ret = analyze_edsp_sub_data(d7_data,
+ &offset,
+ &sub_size, aec);
+ }
+ break;
+ case AEC_D7_CHUNK_ADJ:
+ if (sub_size != 4 || aec->adj.hold != 0xFF ||
+ d7_data[offset] > 0x3F) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->adj.hold = d7_data[offset++];
+
+ if (d7_data[offset] > 0x0F) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->adj.cnt = d7_data[offset++];
+ aec->adj.max[0] = d7_data[offset++];
+ aec->adj.max[1] = d7_data[offset++];
+
+ sub_size = 0;
+ break;
+ case AEC_D7_CHUNK_EDSP_MISC:
+ if (sub_size != 3 ||
+ aec->edsp_misc.i2s_out_enable != 0xFF ||
+ d7_data[offset] > 1) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->edsp_misc.i2s_out_enable = d7_data[offset++];
+
+ if (d7_data[offset] > 1) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->edsp_misc.ch_sel = d7_data[offset++];
+
+ if (d7_data[offset] > 3) {
+ ret = -EINVAL;
+ break;
+ }
+
+ aec->edsp_misc.loopback = d7_data[offset++];
+
+ sub_size = 0;
+ break;
+ case AEC_D7_CHUNK_CONTROL:
+ if (sub_size != 5 || aec->control.command != 0xFF) {
+ ret = -EINVAL;
+ break;
+ }
+ if (dev_id == MCDRV_DEV_ID_80_90H) {
+ if (d7_data[offset] < 1
+ || d7_data[offset] > 2) {
+ ret = -EINVAL;
+ break;
+ }
+ } else {
+ if (d7_data[offset] < 1
+ || d7_data[offset] > 4) {
+ ret = -EINVAL;
+ break;
+ }
+ }
+
+ aec->control.command = d7_data[offset++];
+ aec->control.param[0] = d7_data[offset++];
+ aec->control.param[1] = d7_data[offset++];
+ aec->control.param[2] = d7_data[offset++];
+ aec->control.param[3] = d7_data[offset++];
+
+ sub_size = 0;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ offset += sub_size;
+ }
+
+ return ret;
+}
diff --git a/sound/soc/codecs/ymu831/mcparser.h b/sound/soc/codecs/ymu831/mcparser.h
new file mode 100644
index 0000000..996c8ab
--- /dev/null
+++ b/sound/soc/codecs/ymu831/mcparser.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+ *
+ * Copyright(c) 2012 Yamaha Corporation. All rights reserved.
+ *
+ * Module : mcparser.h
+ * Description : MC data parser header
+ * Version : 1.0.0 Dec 13 2012
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ ****************************************************************************/
+/*
+ * changelog:
+ * - change in the Linux coding style
+ * - remove unused codes
+ */
+#ifndef _MCPARSER_H
+#define _MCPARSER_H
+
+#include <linux/types.h>
+
+#include "mcresctrl.h"
+
+int mc_parser_d7_data_analyze(u8 *data, u32 size, struct mcdrv_aec_info *aec);
+
+#endif /* _MCPARSER_H */
--
1.7.9.5
More information about the Alsa-devel
mailing list