[alsa-devel] [PATCH 05/19] ALSA: ymu831: add C-DSP driver
Yoichi Yuasa
yuasa at linux-mips.org
Wed Jan 16 09:31:03 CET 2013
Signed-off-by: Yoichi Yuasa <yuasa at linux-mips.org>
---
sound/soc/codecs/ymu831/Makefile | 3 +-
sound/soc/codecs/ymu831/mccdspdrv.c | 5119 +++++++++++++++++++++++++++++++++++
sound/soc/codecs/ymu831/mccdspdrv.h | 57 +
3 files changed, 5178 insertions(+), 1 deletion(-)
create mode 100644 sound/soc/codecs/ymu831/mccdspdrv.c
create mode 100644 sound/soc/codecs/ymu831/mccdspdrv.h
diff --git a/sound/soc/codecs/ymu831/Makefile b/sound/soc/codecs/ymu831/Makefile
index e74a60f..b42881e 100644
--- a/sound/soc/codecs/ymu831/Makefile
+++ b/sound/soc/codecs/ymu831/Makefile
@@ -1,4 +1,5 @@
snd-soc-ymu831-objs := \
- mcbdspdrv.o
+ mcbdspdrv.o \
+ mccdspdrv.o
obj-$(CONFIG_SND_SOC_YMU831) += snd-soc-ymu831.o
diff --git a/sound/soc/codecs/ymu831/mccdspdrv.c b/sound/soc/codecs/ymu831/mccdspdrv.c
new file mode 100644
index 0000000..c1c9e83
--- /dev/null
+++ b/sound/soc/codecs/ymu831/mccdspdrv.c
@@ -0,0 +1,5119 @@
+/****************************************************************************
+ *
+ * Copyright(c) 2012 Yamaha Corporation. All rights reserved.
+ *
+ * Module : mccdspdrv.c
+ * Description : MC C-DSP driver
+ * 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/string.h>
+#include <linux/types.h>
+
+#include <asm/byteorder.h>
+
+#include "mccdspdrv.h"
+#include "mccdspos.h"
+#include "mcdefs.h"
+#include "mcdevif.h"
+#include "mcresctrl.h"
+
+#undef LOW_BYTE
+#define LOW_BYTE(w) ((u8)((u16)(w) & 0xff))
+
+#undef HIGH_BYTE
+#define HIGH_BYTE(w) ((u8)((u16)(w) >> 8))
+
+#undef MAKE_HALFWORD
+#define MAKE_HALFWORD(l, h) (((u16)(l) & 0xff) | (((u16)(h) & 0xff) << 8))
+
+#define CODER_DEC 0 /* FuncA */
+#define CODER_ENC 1 /* FuncB */
+
+/* state */
+#define STATE_NOTINIT 0
+#define STATE_INIT 1
+#define STATE_READY_SETUP 2
+#define STATE_READY 3
+#define STATE_PLAYING 4
+
+/* call back */
+
+#define CALLBACK_HOSTCOMMAND 0 /* Host command */
+#define CALLBACK_END_OF_SEQUENCE 1 /* End */
+#define CALLBACK_DFIFOPOINT 2 /* DEC_FIFO IRQ point */
+#define CALLBACK_RFIFOPOINT 3 /* REC_FIFO IRQ point */
+#define CALLBACK_DFIFOEMPTY 4 /* DEC_FIFO empty */
+#define CALLBACK_RECBUF_OVF 5 /* Record buffer over flow */
+#define CALLBACK_TIMER 6 /* Timer */
+#define CALLBACK_PLAY_ERROR1 7 /* Play error */
+#define CALLBACK_PLAY_ERROR2 8 /* Play error */
+#define CALLBACK_HW_ERROR 9 /* Hardware error */
+#define CALLBACK_COUNT 10
+
+/* callback position */
+#define CBPOS_DFIFO_NONE -1
+#define CBPOS_DFIFO_DEF 2048
+#define CBPOS_DFIFO_MIN 0
+#define CBPOS_DFIFO_MAX 4096
+
+#define CBPOS_RFIFO_NONE -1
+#define CBPOS_RFIFO_DEF 2048
+#define CBPOS_RFIFO_MIN 0
+#define CBPOS_RFIFO_MAX 4096
+
+/* Program parameter */
+#define PRG_DESC_VENDER_ID 0
+#define PRG_DESC_FUNCTION_ID 2
+#define PRG_DESC_PRG_TYPE 4
+#define PRG_DESC_OUTPUT_TYPE 6
+#define PRG_DESC_PRG_SCRAMBLE 8
+#define PRG_DESC_DATA_SCRAMBLE 10
+#define PRG_DESC_ENTRY_ADR 12
+#define PRG_DESC_PRG_LOAD_ADR 14
+#define PRG_DESC_PRG_SIZE 16
+#define PRG_DESC_DATA_LOAD_ADR 18
+#define PRG_DESC_DATA_SIZE 20
+#define PRG_DESC_WORK_BEGIN_ADR 22
+#define PRG_DESC_WORK_SIZE 24
+#define PRG_DESC_STACK_BEGIN_ADR 26
+#define PRG_DESC_STACK_SIZE 28
+#define PRG_DESC_OUTSTARTMODE 30
+#define PRG_DESC_RESOURCE_FLAG 32
+#define PRG_DESC_MAX_LOAD 34
+#define PRG_DESC_PROGRAM 36
+
+/* Program data parameter */
+#define PRG_PRM_TYPE_TASK0 0x0001
+#define PRG_PRM_TYPE_TASK1 0x0002
+#define PRG_PRM_SCRMBL_DISABLE 0x0000
+#define PRG_PRM_SCRMBL_ENABLE 0x0001
+#define PRG_PRM_IOTYPE_IN_MASK 0xff00
+#define PRG_PRM_IOTYPE_IN_PCM 0x0000
+#define PRG_PRM_IOTYPE_IN_NOPCM 0x0100
+#define PRG_PRM_IOTYPE_OUT_MASK 0x00ff
+#define PRG_PRM_IOTYPE_OUT_PCM 0x0000
+#define PRG_PRM_IOTYPE_OUT_NOPCM 0x0001
+
+/* OS parameter */
+#define ADR_OS_PROG_L 0x00
+#define ADR_OS_PROG_H 0x00
+#define ADR_OS_DATA_L 0x00
+#define ADR_OS_DATA_H 0x00
+
+/* CDSP MSEL */
+#define MSEL_PROG 0x00
+#define MSEL_DATA 0x01
+
+/* FIFO size */
+#define FIFOSIZE_DFIFO 4096
+#define FIFOSIZE_OFIFO 8192
+#define FIFOSIZE_EFIFO 8192
+#define FIFOSIZE_RFIFO 4096
+#define FIFOSIZE_FFIFO 1024
+
+#define DFIFO_DUMMY_SPACE 2
+
+/* FIFO ID */
+#define FIFO_NONE 0x00000000L
+#define FIFO_DFIFO_MASK 0x000000ffL
+#define FIFO_DFIFO 0x00000001L
+#define FIFO_EFIFO_MASK 0x0000ff00L
+#define FIFO_EFIFO 0x00000100L
+#define FIFO_OFIFO_MASK 0x00ff0000L
+#define FIFO_OFIFO 0x00010000L
+#define FIFO_RFIFO_MASK 0xff000000L
+#define FIFO_RFIFO 0x01000000L
+
+#define PORT_SEL_NONE 0
+#define PORT_SEL_NORMAL 1
+#define PORT_SEL_REF 2
+
+#define RFIFO_CH_NUM 2
+#define RFIFO_BIT_WIDTH 16
+
+/* format */
+#define CODER_FMT_FS_48000 0
+#define CODER_FMT_FS_44100 1
+#define CODER_FMT_FS_32000 2
+#define CODER_FMT_FS_24000 4
+#define CODER_FMT_FS_22050 5
+#define CODER_FMT_FS_16000 6
+#define CODER_FMT_FS_12000 8
+#define CODER_FMT_FS_11025 9
+#define CODER_FMT_FS_8000 10
+
+#define CODER_FMT_ETOBUF_LRMIX 0
+#define CODER_FMT_ETOBUF_LCH 1
+#define CODER_FMT_ETOBUF_RCH 2
+
+#define CODER_FMT_BUFTOO_NONE 0
+#define CODER_FMT_BUFTOO_CONV 1
+
+/* InputDataEnd Command */
+#define INPUTDATAEND_EMPTY 0
+#define INPUTDATAEND_WRITE 1
+
+/* TimerReste Command */
+#define TIMERRESET_RESET 0
+#define TIMERRESET_OFF 1
+
+/* dual mono */
+#define CODER_DUALMONO_LR 0
+#define CODER_DUALMONO_L 1
+#define CODER_DUALMONO_R 2
+
+/* Fs */
+#define OUTPUT_FS_8000 8000
+#define OUTPUT_FS_11025 11025
+#define OUTPUT_FS_12000 12000
+#define OUTPUT_FS_16000 16000
+#define OUTPUT_FS_22050 22050
+#define OUTPUT_FS_24000 24000
+#define OUTPUT_FS_32000 32000
+#define OUTPUT_FS_44100 44100
+#define OUTPUT_FS_48000 48000
+#define OUTPUT_FS_MIN OUTPUT_FS_8000
+#define OUTPUT_FS_MAX OUTPUT_FS_48000
+#define OUTPUT_FS_DEF OUTPUT_FS_48000
+
+/* Start Sample */
+#define OFIFO_BUF_SAMPLE_MIN 0
+#define OFIFO_BUF_SAMPLE_MAX 1024
+#define OFIFO_BUF_SAMPLE_DEF 500
+
+#define RFIFO_BUF_SAMPLE_MIN 0
+#define RFIFO_BUF_SAMPLE_MAX 512
+#define RFIFO_BUF_SAMPLE_DEF 500
+
+/* Stop: verify stop completion */
+#define MADEVCDSP_VERIFY_COMP_OFF 0
+#define MADEVCDSP_VERIFY_COMP_ON 1
+
+/* EVT */
+#define EVENT_TIMER 0x01
+#define EVENT_CLEAR 0x00
+
+/* Error code: CDSP */
+#define CDSP_ERR_NO_ERROR 0x0000
+#define CDSP_ERR_MEM_PROTECTION 0xfff1
+#define CDSP_ERR_WDT 0xfff2
+#define CDSP_ERR_PROG_DOWNLOAD 0xffff
+
+/* Error code: DEC/ENC */
+#define DEC_ERR_NO_ERROR 0x00
+#define DEC_ERR_PROG_SPECIFIC_MIN 0x01
+#define DEC_ERR_PROG_SPECIFIC_MAX 0xef
+#define DEC_ERR_NOT_READY 0xf0
+#define DEC_ERR_MEM_PROTECTION 0xf1
+#define DEC_ERR_WDT 0xf2
+
+/* c-dsp chunk */
+#define CHUNK_SIZE 8
+
+#define CDSP_FUNC_NUMBER 0
+
+#define AEC_CDSP_TAG_PROG 0x00001000
+#define PROG_FIX_SIZE 4
+#define AEC_CDSP_TAG_PRM 0x00001100
+#define PRM_FIX_SIZE 4
+#define PRM_UNIT_SIZE 17
+#define AEC_CDSP_TAG_FIFO 0x00001200
+#define FIFO_FIX_SIZE 26
+#define AEC_CDSP_TAG_EXT 0x00001300
+#define EXT_FIX_SIZE 5
+
+#define ROUTE_OUT0L_SEL 0
+#define ROUTE_OUT0R_SEL 1
+#define ROUTE_OUT1L_SEL 2
+#define ROUTE_OUT1R_SEL 3
+#define ROUTE_OUT2L_SEL 4
+#define ROUTE_OUT2R_SEL 5
+#define ROUTE_EFIFO0_SEL 6
+#define ROUTE_EFIFO1_SEL 7
+#define ROUTE_EFIFO2_SEL 8
+#define ROUTE_EFIFO3_SEL 9
+#define CDSP_EFIFO_CH 10
+#define CDSP_EFIFO_BIT_WIDTH 11
+#define CDSP_EFIFO_E2BUF_MODE 12
+#define CDSP_OFIFO_CH 13
+#define CDSP_OFIFO_BIT_WIDTH 14
+#define CDSP_DFIFO_BIT_WIDTH 15
+#define CDSP_RFIFO_BIT_WIDTH 16
+#define CDSP_USE_FIFO 17
+#define CDSP_DFIFO_CB_POINT 18 /* 2Byte */
+#define CDSP_RFIFO_CB_POINT 20 /* 2Byte */
+#define CDSP_OFIFO_BUFFERING 22 /* 2Byte */
+#define CDSP_RFIFO_BUFFERING 24 /* 2Byte */
+
+#define OUT_LOOPBACK_L 4
+#define OUT_LOOPBACK_R 5
+
+#define CDSP_FIFO_MASK 0x0f
+#define CDSP_FIFO_EFIFO_BIT 0x01
+#define CDSP_FIFO_OFIFO_BIT 0x02
+#define CDSP_FIFO_DFIFO_BIT 0x04
+#define CDSP_FIFO_RFIFO_BIT 0x08
+#define CDSP_FIFO_OTHER_MASK 0xf0
+#define CDSP_FIFO_OTHER_OUTBUF_BIT 0x10
+#define CDSP_FIFO_OTHER_INBUF_BIT 0x20
+
+#define CDSP_FIFO_DONTCARE 0xff
+#define CDSP_FIFO_DONTCARE_W 0xffff
+#define CDSP_FIFO_DONTCARE_CB 0xfffe
+#define CDSP_FIFO_NOT_CB 0xffff
+
+#define CDSP_PRM_CMD 0
+#define CDSP_PRM_PRM0 1
+
+#define AEC_FUNC_INFO_A 0
+#define AEC_FUNC_INFO_B 1
+#define AEC_FUNC_INFO_NUM 2
+
+#define EXT_COMMAND 0
+#define EXT_COMMAND_CLEAR 1
+
+/* Command (Host -> OS) */
+#define CDSP_CMD_HOST2OS_CMN_NONE 0x00
+#define CDSP_CMD_HOST2OS_CMN_RESET 0x01
+#define CDSP_CMD_HOST2OS_CMN_CLEAR 0x02
+#define CDSP_CMD_HOST2OS_CMN_STANDBY 0x03
+#define CDSP_CMD_HOST2OS_CMN_GET_PRG_VER 0x04
+#define CDSP_CMD_HOST2OS_SYS_GET_OS_VER 0x20
+#define CDSP_CMD_HOST2OS_SYS_SET_PRG_INFO 0x21
+#define CDSP_CMD_HOST2OS_SYS_SET_FORMAT 0x22
+#define CDSP_CMD_HOST2OS_SYS_SET_CONNECTION 0x23
+#define CDSP_CMD_HOST2OS_SYS_VERIFY_STOP_COMP 0x24
+#define CDSP_CMD_HOST2OS_SYS_INPUT_DATA_END 0x25
+#define CDSP_CMD_HOST2OS_SYS_CLEAR_INPUT_DATA_END 0x26
+#define CDSP_CMD_HOST2OS_SYS_SET_TIMER 0x27
+#define CDSP_CMD_HOST2OS_SYS_TIMER_RESET 0x28
+#define CDSP_CMD_HOST2OS_SYS_TERMINATE 0x29
+#define CDSP_CMD_HOST2OS_SYS_SET_DUAL_MONO 0x2a
+#define CDSP_CMD_HOST2OS_SYS_GET_INPUT_POS 0x2b
+#define CDSP_CMD_HOST2OS_SYS_RESET_INPUT_POS 0x2c
+#define CDSP_CMD_HOST2OS_SYS_HALT 0x2d
+#define CDSP_CMD_HOST2OS_SYS_SET_CLOCK_SOURCE 0x2e
+#define CDSP_CMD_DRV_SYS_SET_CONNECTION_EX 0x3e
+#define CDSP_CMD_DRV_SYS_SET_BIT_WIDTH 0x3f
+#define CDSP_CMD_HOST2OS_PRG_MIN 0x40
+#define CDSP_CMD_HOST2OS_PRG_MAX 0x6f
+
+/* Command (OS -> Host) */
+#define CDSP_CMD_OS2HOST_CMN_NONE 0x00
+#define CDSP_CMD_OS2HOST_CMN_MIN 0x01
+#define CDSP_CMD_OS2HOST_CMN_MAX 0x3f
+#define CDSP_CMD_OS2HOST_PRG_MIN 0x40
+#define CDSP_CMD_OS2HOST_PRG_MAX 0x6f
+#define CDSP_CMD_OS2HOST_DISABLE_MIN 0x70
+#define CDSP_CMD_OS2HOST_DISABLE_MAX 0x7f
+#define CDSP_CMD_OS2HOST_READY_MIN 0x80
+#define CDSP_CMD_OS2HOST_READY_MAX 0xff
+#define CDSP_CMD_OS2HOST_CMN_NOTIFY_OUT_FORMAT 0x01
+
+/* Command parameter */
+#define CDSP_CMD_PARAM_ARGUMENT_00 0
+#define CDSP_CMD_PARAM_ARGUMENT_01 1
+#define CDSP_CMD_PARAM_ARGUMENT_02 2
+#define CDSP_CMD_PARAM_ARGUMENT_03 3
+#define CDSP_CMD_PARAM_ARGUMENT_04 4
+#define CDSP_CMD_PARAM_ARGUMENT_05 5
+#define CDSP_CMD_PARAM_ARGUMENT_06 6
+#define CDSP_CMD_PARAM_ARGUMENT_07 7
+#define CDSP_CMD_PARAM_ARGUMENT_08 8
+#define CDSP_CMD_PARAM_ARGUMENT_09 9
+#define CDSP_CMD_PARAM_ARGUMENT_10 10
+#define CDSP_CMD_PARAM_ARGUMENT_11 11
+#define CDSP_CMD_PARAM_ARGUMENT_NUM 12
+#define CDSP_CMD_PARAM_RESULT_00 12
+#define CDSP_CMD_PARAM_RESULT_01 13
+#define CDSP_CMD_PARAM_RESULT_02 14
+#define CDSP_CMD_PARAM_RESULT_03 15
+#define CDSP_CMD_PARAM_RESULT_NUM 4
+#define CDSP_CMD_PARAM_NUM \
+ (CDSP_CMD_PARAM_ARGUMENT_NUM + CDSP_CMD_PARAM_RESULT_NUM)
+
+/* Command Completion */
+#define CDSP_CMD_COMPLETION 0x80
+
+/* Connect FIFO */
+#define CDSP_IN_SOURCE_DFIFO 0
+#define CDSP_IN_SOURCE_EFIFO 1
+#define CDSP_IN_SOURCE_OTHER_OUTBUF 2
+#define CDSP_IN_SOURCE_NONE 3
+#define CDSP_IN_SOURCE_DFIFO_EFIFO 4
+
+#define CDSP_OUT_DEST_OFIFO 0
+#define CDSP_OUT_DEST_RFIFO 1
+#define CDSP_OUT_DEST_OTHER_INBUF 2
+#define CDSP_OUT_DEST_NONE 3
+#define CDSP_OUT_DEST_OFIFO_RFIFO 4
+
+struct coder_firmware {
+ u8 *firmware;
+ u32 size;
+};
+
+struct coder_version {
+ u32 id;
+ u16 prog_ver_h;
+ u16 prog_ver_m;
+ u16 prog_ver_l;
+ u16 os_ver_h;
+ u16 os_ver_m;
+ u16 os_ver_l;
+};
+
+struct fsq_data_info {
+ u8 *data;
+ u16 size;
+ u16 load_addr;
+ u16 scramble;
+ u8 msel;
+};
+
+struct fifo_info {
+ int dfifo_cb_pos;
+ int rfifo_cb_pos;
+ u32 ofifo_buf_sample;
+ bool ofifo_output_start;
+ u32 dfifo_write_size;
+ u32 rfifo_buf_sample;
+ bool rfifo_output_start;
+
+ u8 out0_sel;
+ u8 out1_sel;
+ u8 out2_sel;
+ u8 rdfifo_bit_sel;
+ u8 efifo01_sel;
+ u8 efifo23_sel;
+};
+
+struct version_info {
+ u16 version_h;
+ u16 version_l;
+};
+
+struct callback_info {
+ bool on[CALLBACK_COUNT];
+ u32 ex_info[CALLBACK_COUNT];
+};
+
+struct program_info {
+ u16 vendor_id;
+ u16 function_id;
+ u16 prog_type;
+ u16 inout_type;
+ u16 prog_scramble;
+ u16 data_scramble;
+ u16 entry_addr;
+ u16 prog_loadaddr;
+ u16 prog_size;
+ u16 data_loadaddr;
+ u16 data_size;
+ u16 work_begin;
+ u16 work_size;
+ u16 stack_begin;
+ u16 stack_size;
+ u16 output_start_mode;
+ u16 resource_flag;
+ u16 max_load;
+};
+
+struct format_info {
+ u8 fs;
+ u8 etobuf;
+};
+
+struct connection_info {
+ u8 src;
+ u8 dest;
+};
+
+struct connection_ex_info {
+ u8 efifo_ch;
+ u8 ofifo_ch;
+};
+
+struct bit_width_info {
+ u8 efifo;
+ u8 ofifo;
+};
+
+struct coder_params {
+ u8 command;
+ u8 params[16];
+};
+
+struct coder_info {
+ u8 state;
+ bool preinput_dataend_set;
+ bool input_dataend_set;
+ bool change_output_fs;
+ bool format_propagate;
+ u32 input_pos;
+ u8 error_code;
+ struct callback_info callback;
+ struct version_info program;
+ struct program_info prog_info;
+ struct format_info format;
+ struct connection_info conn_info;
+ struct connection_ex_info conn_ex_info;
+ struct bit_width_info bit_width;
+ struct coder_params coder;
+};
+
+struct cdsp_info {
+ u16 hw_error_code;
+ struct version_info os;
+};
+
+struct aec_cdsp_func_info {
+ enum mc_cdsp_id id;
+ bool func_on;
+ u8 *data;
+ u32 data_size;
+ u8 *fifo_data;
+ u8 *prog_data;
+ u32 prog_size;
+ u8 *param_data;
+ u32 param_num;
+ u8 *ext;
+
+ struct format_info format;
+ struct connection_info conn_info;
+ struct connection_ex_info conn_ex_info;
+ struct bit_width_info bit_width;
+};
+
+struct aec_cdsp_info {
+ struct aec_cdsp_func_info func_info[AEC_FUNC_INFO_NUM];
+
+ int dfifo_cb_pos;
+ int rfifo_cb_pos;
+ u32 ofifo_buf_sample;
+ u32 rfifo_buf_sample;
+ u8 out0_sel;
+ u8 out1_sel;
+ u8 out2_sel;
+ u8 rdfifo_bit_sel;
+ u8 efifo01_sel;
+ u8 efifo23_sel;
+};
+
+static struct cdsp_info mc_cdsp_info = {
+ .hw_error_code = CDSP_ERR_NO_ERROR,
+};
+
+static struct fifo_info mc_fifo_info;
+
+static struct coder_info mc_dec_info = {
+ .state = STATE_NOTINIT,
+ .format = {
+ .fs = CODER_FMT_FS_48000,
+ .etobuf = CODER_FMT_ETOBUF_LRMIX,
+ },
+ .conn_info = {
+ .src = CDSP_IN_SOURCE_NONE,
+ .dest = CDSP_OUT_DEST_NONE,
+ },
+ .conn_ex_info = {
+ .efifo_ch = 2,
+ .ofifo_ch = 2,
+ },
+ .bit_width = {
+ .efifo = 16,
+ .ofifo = 16,
+ },
+};
+
+static struct coder_info mc_enc_info = {
+ .state = STATE_NOTINIT,
+ .format = {
+ .fs = CODER_FMT_FS_48000,
+ .etobuf = CODER_FMT_ETOBUF_LRMIX,
+ },
+ .conn_info = {
+ .src = CDSP_IN_SOURCE_NONE,
+ .dest = CDSP_OUT_DEST_NONE,
+ },
+ .conn_ex_info = {
+ .efifo_ch = 2,
+ .ofifo_ch = 2,
+ },
+ .bit_width = {
+ .efifo = 16,
+ .ofifo = 16,
+ },
+};
+
+static int cdsp_coder_start(enum mc_cdsp_id id);
+
+static void cdsp_registers_init(void)
+{
+ int i;
+
+ mc_packet_add_force_write_c(MCI_CDSP_RESET,
+ MCB_CDSP_DMODE | MCB_CDSP_FSQ_SRST |
+ MCB_CDSP_SRST);
+
+ /* Disable interrupt */
+ mc_packet_add_force_write_c(MCI_DEC_ENABLE, 0);
+ mc_packet_add_force_write_c(MCI_ENC_ENABLE, 0);
+ mc_packet_add_force_write_c(MCI_DFIFO_ENABLE, 0);
+ mc_packet_add_force_write_c(MCI_OFIFO_ENABLE, 0);
+ mc_packet_add_force_write_c(MCI_EFIFO_ENABLE, 0);
+ mc_packet_add_force_write_c(MCI_RFIFO_ENABLE, 0);
+ mc_packet_add_force_write_c(MCI_FFIFO_ENABLE, 0);
+ mc_packet_add_force_write_c(MCI_CDSP_ENABLE, 0);
+ mc_packet_add_force_write_if(MCI_ECDSP, 0);
+
+ /* Clear interrupt flag */
+ mc_packet_add_force_write_c(MCI_DEC_FLG, MCB_DEC_FLG_ALL);
+ mc_packet_add_force_write_c(MCI_ENC_FLG, MCB_ENC_FLG_ALL);
+ mc_packet_add_force_write_c(MCI_DFIFO_FLG, MCB_DFIFO_FLG_ALL);
+ mc_packet_add_force_write_c(MCI_OFIFO_FLG, MCB_OFIFO_FLG_ALL);
+ mc_packet_add_force_write_c(MCI_EFIFO_FLG, MCB_EFIFO_FLG_ALL);
+ mc_packet_add_force_write_c(MCI_RFIFO_FLG, MCB_RFIFO_FLG_ALL);
+ mc_packet_add_force_write_c(MCI_FFIFO_FLG, MCB_FFIFO_FLG_ALL);
+ mc_packet_add_force_write_c(MCI_CDSP_FLG, MCB_CDSP_FLG_ALL);
+ mc_packet_add_force_write_if(MCI_CDSP, MCB_IRQFLAG_CDSP_ALL);
+
+ /* Other registers */
+ mc_packet_add_force_write_c(MCI_DEC_START, 0);
+ mc_packet_add_force_write_c(MCI_DEC_START2, 0);
+ mc_packet_add_force_write_c(MCI_DEC_FIFO_RST, 0);
+
+ mc_packet_add_force_write_c(MCI_PWM_DIGITAL_CDSP, 0);
+
+ mc_packet_add_force_write_c(MCI_DEC_POS4, 0);
+ mc_packet_add_force_write_c(MCI_ENC_POS4, 0);
+ mc_packet_add_force_write_c(MCI_DFIFO_IRQ_PNT_H, 0);
+ mc_packet_add_force_write_c(MCI_DFIFO_IRQ_PNT_L, 0);
+ mc_packet_add_force_write_c(MCI_OFIFO_IRQ_PNT_H, 0);
+ mc_packet_add_force_write_c(MCI_OFIFO_IRQ_PNT_L, 0);
+ mc_packet_add_force_write_c(MCI_EFIFO_IRQ_PNT_H, 0);
+ mc_packet_add_force_write_c(MCI_EFIFO_IRQ_PNT_L, 0);
+ mc_packet_add_force_write_c(MCI_RFIFO_IRQ_PNT_H, 0);
+ mc_packet_add_force_write_c(MCI_RFIFO_IRQ_PNT_L, 0);
+ mc_packet_add_force_write_c(MCI_FFIFO_IRQ_PNT_H, 0);
+ mc_packet_add_force_write_c(MCI_FFIFO_IRQ_PNT_L, 0);
+ mc_packet_add_force_write_c(MCI_CDSP_MAR_H, 0);
+ mc_packet_add_force_write_c(MCI_CDSP_MAR_L, 0);
+ mc_packet_add_force_write_c(MCI_DEC_GPR_ENABLE, 0);
+ mc_packet_add_force_write_c(MCI_DEC_SFR1, 0);
+ mc_packet_add_force_write_c(MCI_DEC_SFR0, 0);
+ mc_packet_add_force_write_c(MCI_ENC_GPR_ENABLE, 0);
+ mc_packet_add_force_write_c(MCI_ENC_SFR1, 0);
+ mc_packet_add_force_write_c(MCI_ENC_SFR0, 0);
+ mc_packet_add_force_write_c(MCI_DEC_EVT, 0);
+ mc_packet_add_force_write_c(MCI_ENC_EVT, 0);
+ mc_packet_add_force_write_c(MCI_DEC_FIFO_CH, 0);
+ mc_packet_add_force_write_c(MCI_RDFIFO_BIT_SEL, 0);
+ mc_packet_add_force_write_c(MCI_OUT0_SEL, MCI_OUT0_SEL_DEF);
+ mc_packet_add_force_write_c(MCI_OUT1_SEL, MCI_OUT1_SEL_DEF);
+ mc_packet_add_force_write_c(MCI_OUT2_SEL, MCI_OUT2_SEL_DEF);
+ mc_packet_add_force_write_c(MCI_EFIFO01_SEL, MCI_EFIFO01_SEL_DEF);
+ mc_packet_add_force_write_c(MCI_EFIFO23_SEL, MCI_EFIFO23_SEL_DEF);
+
+ for (i = 0; i < CDSP_CMD_PARAM_NUM; i++) {
+ mc_packet_add_force_write_c((MCI_DEC_GPR15 + i), 0);
+ mc_packet_add_force_write_c((MCI_ENC_GPR15 + i), 0);
+ mc_packet_add_force_write_c((MCI_DEC_CTL15 + i), 0);
+ mc_packet_add_force_write_c((MCI_ENC_CTL15 + i), 0);
+ }
+
+ mc_packet_execute();
+}
+
+static inline void cdsp_os_download(const u8 *firmware)
+{
+ u8 data, msel[2];
+ u8 addr_h[2], addr_l[2];
+ u32 os_size[2], i, j;
+ const u8 *os_prog[2];
+
+ msel[0] = MCB_CDSP_MSEL_PROG;
+ addr_h[0] = ADR_OS_PROG_H;
+ addr_l[0] = ADR_OS_PROG_L;
+ os_size[0] = MAKE_HALFWORD(firmware[0], firmware[1]) * 2;
+ os_prog[0] = &firmware[4];
+
+ msel[1] = MCB_CDSP_MSEL_DATA;
+ addr_h[1] = ADR_OS_DATA_H;
+ addr_l[1] = ADR_OS_DATA_L;
+ os_size[1] = MAKE_HALFWORD(firmware[2], firmware[3]) * 2;
+ os_prog[1] = &os_prog[0][os_size[0]];
+
+ mc_read_c(MCI_CDSP_RESET, &data, 1);
+
+ /* CDSP_SRST Set : CDSP OS stop */
+ data &= ~MCB_CDSP_FMODE;
+ data |= MCB_CDSP_SRST;
+ mc_packet_add_force_write_c(MCI_CDSP_RESET, data);
+
+ /* Program & Data Write */
+ for (i = 0; i < 2; i++) {
+ /* CDSP_MSEL Set */
+ data &= ~MCB_CDSP_MSEL;
+ data |= msel[i];
+ mc_packet_add_force_write_c(MCI_CDSP_RESET, data);
+
+ /* CDSP_MAR Set */
+ mc_packet_add_force_write_c(MCI_CDSP_MAR_H, addr_h[i]);
+ mc_packet_add_force_write_c(MCI_CDSP_MAR_L, addr_l[i]);
+
+ mc_packet_execute();
+
+ /* FSQ_FIFO Write */
+ for (j = 0; j < os_size[i]; ++j)
+ mc_packet_add_force_write_if(MCI_FSQ_FFIFO,
+ os_prog[i][j]);
+
+ mc_packet_execute();
+
+ }
+
+ /* CDSP_SRST Release : CDSP OS start */
+ data &= ~MCB_CDSP_SRST;
+ mc_packet_add_force_write_c(MCI_CDSP_RESET, data);
+ /* 100 ns wait */
+ mc_packet_add_wait(1);
+
+ mc_packet_execute();
+}
+
+static void cdsp_command_write_complete(enum mc_cdsp_id id,
+ struct coder_params *coder)
+{
+ u32 sfr, ctl, base, i;
+
+ if (id == CDSP_DECODER) {
+ sfr = MCI_DEC_SFR1;
+ ctl = MCI_DEC_CTL0;
+ } else {
+ sfr = MCI_ENC_SFR1;
+ ctl = MCI_ENC_CTL0;
+ }
+
+ /* Write result */
+ base = CDSP_CMD_PARAM_RESULT_00;
+ for (i = base; i < base + CDSP_CMD_PARAM_RESULT_NUM; i++)
+ mc_packet_add_write_c(ctl - i, coder->params[i]);
+
+ /* Write complete command */
+ mc_packet_add_force_write_c(sfr, coder->command | CDSP_CMD_COMPLETION);
+
+ mc_packet_execute();
+}
+
+static int cdsp_command_wait_complete(enum mc_cdsp_id id)
+{
+ u32 sfr;
+ int ret;
+
+ if (id == CDSP_DECODER)
+ sfr = MCI_DEC_SFR0;
+ else
+ sfr = MCI_ENC_SFR0;
+
+ /* Polling */
+ mc_packet_add_wait_event(MCDRV_EVT_C_REG_FLAG_SET | (sfr << 8) |
+ CDSP_CMD_COMPLETION);
+
+ ret = mc_packet_execute();
+ if (ret < 0) {
+ /* Time out */
+ mc_packet_add_force_write_c(sfr, CDSP_CMD_COMPLETION);
+
+ mc_packet_execute();
+ }
+
+ return ret;
+}
+
+static int cdsp_command_init(enum mc_cdsp_id id)
+{
+ struct coder_params coder;
+
+ coder.command = CDSP_CMD_OS2HOST_CMN_NONE;
+ coder.params[CDSP_CMD_PARAM_RESULT_00] = 0;
+ coder.params[CDSP_CMD_PARAM_RESULT_01] = 0;
+ coder.params[CDSP_CMD_PARAM_RESULT_02] = 0;
+ coder.params[CDSP_CMD_PARAM_RESULT_03] = 0;
+
+ cdsp_command_write_complete(id, &coder);
+
+ return cdsp_command_wait_complete(id);
+}
+
+static int cdsp_command_write_host2os(enum mc_cdsp_id id,
+ struct coder_params *coder)
+{
+ u32 sfr, ctl, gpr;
+ u8 data;
+ int count, i, ret;
+
+ if (id == CDSP_DECODER) {
+ sfr = MCI_DEC_SFR0;
+ ctl = MCI_DEC_CTL0;
+ gpr = MCI_DEC_GPR0;
+ } else {
+ sfr = MCI_ENC_SFR0;
+ ctl = MCI_ENC_CTL0;
+ gpr = MCI_ENC_GPR0;
+ }
+
+ /* Polling */
+ ret = cdsp_command_wait_complete(id);
+ if (ret < 0)
+ return ret;
+
+ /* Write parameter */
+ switch (coder->command) {
+ case CDSP_CMD_HOST2OS_CMN_NONE:
+ case CDSP_CMD_HOST2OS_CMN_RESET:
+ case CDSP_CMD_HOST2OS_CMN_CLEAR:
+ case CDSP_CMD_HOST2OS_CMN_STANDBY:
+ case CDSP_CMD_HOST2OS_CMN_GET_PRG_VER:
+ case CDSP_CMD_HOST2OS_SYS_GET_OS_VER:
+ case CDSP_CMD_HOST2OS_SYS_VERIFY_STOP_COMP:
+ case CDSP_CMD_HOST2OS_SYS_CLEAR_INPUT_DATA_END:
+ case CDSP_CMD_HOST2OS_SYS_TERMINATE:
+ case CDSP_CMD_HOST2OS_SYS_GET_INPUT_POS:
+ case CDSP_CMD_HOST2OS_SYS_RESET_INPUT_POS:
+ case CDSP_CMD_HOST2OS_SYS_HALT:
+ count = 0;
+ break;
+ case CDSP_CMD_HOST2OS_SYS_INPUT_DATA_END:
+ case CDSP_CMD_HOST2OS_SYS_TIMER_RESET:
+ case CDSP_CMD_HOST2OS_SYS_SET_DUAL_MONO:
+ case CDSP_CMD_HOST2OS_SYS_SET_CLOCK_SOURCE:
+ count = 1;
+ break;
+ case CDSP_CMD_HOST2OS_SYS_SET_PRG_INFO:
+ count = 11;
+ break;
+ case CDSP_CMD_HOST2OS_SYS_SET_FORMAT:
+ count = 2;
+ break;
+ case CDSP_CMD_HOST2OS_SYS_SET_CONNECTION:
+ count = 2;
+ break;
+ case CDSP_CMD_HOST2OS_SYS_SET_TIMER:
+ count = 4;
+ break;
+ default:
+ /* Program dependence command */
+ count = CDSP_CMD_PARAM_ARGUMENT_NUM;
+ break;
+ }
+
+ for (i = 0; i < count; i++)
+ mc_packet_add_write_c(ctl - i, coder->params[i]);
+
+ /* Write command */
+ mc_packet_add_force_write_c(sfr, coder->command);
+
+ mc_packet_execute();
+
+ /* Polling */
+ ret = cdsp_command_wait_complete(id);
+ if (ret < 0)
+ return ret;
+
+ /* Error check */
+ mc_read_c(sfr, &data, 1);
+ if (data >= 0xF0) {
+ if (data == 0xF7)
+ return -EBUSY;
+ if (data >= 0xF3 && data <= 0xF6)
+ return -EINVAL;
+ return -EIO;
+ }
+
+ /* Get result */
+ count = CDSP_CMD_PARAM_RESULT_00;
+ for (i = count; i < count + CDSP_CMD_PARAM_RESULT_NUM; i++) {
+ mc_read_c((gpr - i), &data, 1);
+ coder->params[i] = data;
+ }
+
+ return data;
+}
+
+static int cdsp_os_init(void)
+{
+ struct coder_params coder;
+ int ret;
+
+ /* CDSP_ERR/WDT_FLG Flag clear */
+ mc_packet_add_force_write_c(MCI_CDSP_FLG, MCB_CDSP_FLG_ALL);
+
+ /* IRQ Flag clear */
+ mc_packet_add_force_write_if(MCI_CDSP, MCB_IRQFLAG_CDSP_ALL);
+
+ /* ECDSP_ERR/WDT Enable */
+ mc_packet_add_force_write_c(MCI_CDSP_ENABLE, MCB_CDSP_ENABLE_ALL);
+
+ /* IRQ: ECDSP=Enable, other=Disable */
+ mc_packet_add_force_write_if(MCI_ECDSP, MCB_ECDSP);
+
+ mc_packet_execute();
+
+ /* Command register Initialize */
+ ret = cdsp_command_init(CODER_DEC);
+ if (ret < 0)
+ return ret;
+
+ ret = cdsp_command_init(CODER_ENC);
+ if (ret < 0)
+ return ret;
+
+ /* READY Polling */
+ mc_packet_add_wait_event(MCDRV_EVT_C_REG_FLAG_SET |
+ (MCI_CDSP_POWER_MODE << 8) | MCB_CDSP_SLEEP);
+
+ ret = mc_packet_execute();
+ if (ret < 0)
+ return ret;
+
+ /* GetOsVersion command */
+ coder.command = CDSP_CMD_HOST2OS_SYS_GET_OS_VER;
+ ret = cdsp_command_write_host2os(CODER_DEC, &coder);
+ if (ret < 0)
+ return ret;
+
+ mc_cdsp_info.os.version_h =
+ MAKE_HALFWORD(coder.params[CDSP_CMD_PARAM_RESULT_00],
+ coder.params[CDSP_CMD_PARAM_RESULT_01]);
+ mc_cdsp_info.os.version_l =
+ MAKE_HALFWORD(coder.params[CDSP_CMD_PARAM_RESULT_02],
+ coder.params[CDSP_CMD_PARAM_RESULT_03]);
+
+ return 0;
+}
+
+static void cdsp_coder_info_init(struct coder_info *info)
+{
+ memset(info, 0, sizeof(struct coder_info));
+
+ info->state = STATE_INIT;
+
+ info->prog_info.inout_type =
+ PRG_PRM_IOTYPE_IN_PCM | PRG_PRM_IOTYPE_OUT_PCM;
+
+ info->format.fs = CODER_FMT_FS_48000;
+ info->format.etobuf = CODER_FMT_ETOBUF_LRMIX;
+
+ info->conn_info.src = CDSP_IN_SOURCE_NONE;
+ info->conn_info.dest = CDSP_OUT_DEST_NONE;
+
+ info->conn_ex_info.efifo_ch = 2;
+ info->conn_ex_info.ofifo_ch = 2;
+
+ info->bit_width.efifo = 16;
+ info->bit_width.ofifo = 16;
+}
+
+static inline struct coder_info *cdsp_coder_info_get(enum mc_cdsp_id id)
+{
+ if (id == CDSP_DECODER)
+ return &mc_dec_info;
+
+ return &mc_enc_info;
+}
+
+static inline enum mc_cdsp_id cdsp_another_id_get(enum mc_cdsp_id id)
+{
+ if (id == CDSP_DECODER)
+ return CDSP_ENCODER;
+
+ return CDSP_DECODER;
+}
+
+static void cdsp_command_read_os2host(enum mc_cdsp_id id,
+ struct coder_params *coder)
+{
+ u32 sfr, gpr, count, i;
+ u8 data;
+
+ if (id == CDSP_DECODER) {
+ sfr = MCI_DEC_SFR1;
+ gpr = MCI_DEC_GPR0;
+ } else {
+ sfr = MCI_ENC_SFR1;
+ gpr = MCI_ENC_GPR0;
+ }
+
+ mc_read_c(sfr, &data, 1);
+
+ coder->command = data;
+ switch (coder->command) {
+ case CDSP_CMD_OS2HOST_CMN_NONE:
+ count = 0;
+ break;
+ case CDSP_CMD_OS2HOST_CMN_NOTIFY_OUT_FORMAT:
+ count = 4;
+ break;
+ default:
+ /* Program dependence command */
+ count = CDSP_CMD_PARAM_ARGUMENT_NUM;
+ break;
+ }
+
+ for (i = 0; i < count; i++) {
+ mc_read_c((gpr - i), &data, 1);
+ coder->params[i] = data;
+ }
+}
+
+static int cdsp_command_inputdataend(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+ struct coder_params coder;
+ u8 src, dest;
+
+ info = cdsp_coder_info_get(id);
+
+ src = info->conn_info.src;
+ if (src == CDSP_IN_SOURCE_DFIFO || src == CDSP_IN_SOURCE_DFIFO_EFIFO) {
+ if (mc_fifo_info.dfifo_write_size & 0x01) {
+ mc_packet_add_force_write_if(MCI_DEC_FIFO, 0);
+
+ mc_fifo_info.dfifo_write_size = 0;
+ }
+ }
+
+ coder.params[CDSP_CMD_PARAM_ARGUMENT_00] = INPUTDATAEND_EMPTY;
+
+ dest = info->conn_info.dest;
+ if ((mc_fifo_info.rdfifo_bit_sel & MCB_RFIFO_SEL_HOST) &&
+ (dest == CDSP_OUT_DEST_RFIFO || dest == CDSP_OUT_DEST_OFIFO_RFIFO))
+ coder.params[CDSP_CMD_PARAM_ARGUMENT_00] = INPUTDATAEND_WRITE;
+
+ /* InputDataEnd command */
+ coder.command = CDSP_CMD_HOST2OS_SYS_INPUT_DATA_END;
+
+ return cdsp_command_write_host2os(id, &coder);
+}
+
+static void cdsp_ofifo_start_real(void)
+{
+ u8 data;
+
+ mc_read_c(MCI_DEC_START, &data, 1);
+ data |= MCB_DEC_OUT_START;
+ mc_packet_add_write_c(MCI_DEC_START, data);
+
+ mc_packet_execute();
+}
+
+static void cdsp_rfifo_start_real(void)
+{
+ u8 data;
+
+ mc_read_c(MCI_DEC_START2, &data, 1);
+ data |= MCB_RFIFO_START;
+ mc_packet_add_write_c(MCI_DEC_START2, data);
+
+ mc_packet_execute();
+}
+
+static u32 cdsp_fifoid_get(struct connection_info *conn_info)
+{
+ u32 id = 0;
+
+ switch (conn_info->src) {
+ case CDSP_IN_SOURCE_DFIFO:
+ id |= FIFO_DFIFO;
+ break;
+ case CDSP_IN_SOURCE_EFIFO:
+ id |= FIFO_EFIFO;
+ break;
+ case CDSP_IN_SOURCE_DFIFO_EFIFO:
+ id |= FIFO_DFIFO | FIFO_EFIFO;
+ break;
+ default:
+ break;
+ }
+
+ switch (conn_info->dest) {
+ case CDSP_OUT_DEST_OFIFO:
+ id |= FIFO_OFIFO;
+ break;
+ case CDSP_OUT_DEST_RFIFO:
+ id |= FIFO_RFIFO;
+ break;
+ case CDSP_OUT_DEST_OFIFO_RFIFO:
+ id |= FIFO_OFIFO | FIFO_RFIFO;
+ break;
+ default:
+ break;
+ }
+
+ return id;
+}
+
+static u32 cdsp_fifoid_get_from_coderid(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+
+ info = cdsp_coder_info_get(id);
+
+ return cdsp_fifoid_get(&info->conn_info);
+}
+
+static inline void cdsp_output_format_notify_os2host(enum mc_cdsp_id id)
+{
+ struct coder_info *info, *another_info;
+ enum mc_cdsp_id another_id;
+ u32 fifo_id, another_fifo_id;
+
+ info = cdsp_coder_info_get(id);
+
+ another_id = cdsp_another_id_get(id);
+ another_info = cdsp_coder_info_get(another_id);
+
+ info->format.fs = info->coder.params[CDSP_CMD_PARAM_ARGUMENT_00];
+
+ another_fifo_id = 0;
+ if (info->conn_info.dest == CDSP_OUT_DEST_OTHER_INBUF) {
+ fifo_id = cdsp_fifoid_get(&another_info->conn_info);
+ if (fifo_id & FIFO_OFIFO_MASK)
+ another_fifo_id |= FIFO_OFIFO;
+ if ((fifo_id & FIFO_RFIFO_MASK) &&
+ !(mc_fifo_info.rdfifo_bit_sel & MCB_RFIFO_SEL_HOST))
+ another_fifo_id |= FIFO_RFIFO;
+ } else {
+ fifo_id = cdsp_fifoid_get(&info->conn_info);
+ fifo_id &= ~(FIFO_DFIFO_MASK | FIFO_EFIFO_MASK);
+ if (mc_fifo_info.rdfifo_bit_sel & MCB_RFIFO_SEL_HOST)
+ fifo_id &= ~FIFO_RFIFO_MASK;
+ if (fifo_id != FIFO_NONE) {
+ if (fifo_id & FIFO_OFIFO_MASK)
+ /* Wait OFIFO_EMPTY */
+ mc_packet_add_force_write_c(MCI_OFIFO_FLG,
+ MCB_OFIFO_FLG_OEMP);
+ if (fifo_id & FIFO_RFIFO_MASK)
+ /* Wait RFIFO_EMPTY */
+ mc_packet_add_force_write_c(MCI_RFIFO_FLG,
+ MCB_RFIFO_FLG_REMP);
+ if (fifo_id & FIFO_OFIFO_MASK)
+ mc_packet_add_wait_event
+ (MCDRV_EVT_C_REG_FLAG_SET |
+ (MCI_OFIFO_FLG << 8) | MCB_OFIFO_FLG_OEMP);
+
+ if (fifo_id & FIFO_RFIFO_MASK)
+ mc_packet_add_wait_event
+ (MCDRV_EVT_C_REG_FLAG_SET |
+ (MCI_RFIFO_FLG << 8) | MCB_RFIFO_FLG_REMP);
+
+ mc_packet_execute();
+
+ if (fifo_id & FIFO_OFIFO_MASK)
+ /* Clear OFIFO_EMPTY */
+ mc_packet_add_force_write_c(MCI_OFIFO_FLG,
+ MCB_OFIFO_FLG_ALL);
+
+ if (fifo_id & FIFO_RFIFO_MASK)
+ /* Clear RFIFO_EMPTY */
+ mc_packet_add_force_write_c(MCI_RFIFO_FLG,
+ MCB_RFIFO_FLG_ALL);
+
+ mc_packet_execute();
+ }
+ }
+
+ if (another_fifo_id && !another_info->input_dataend_set) {
+ another_info->preinput_dataend_set = false;
+
+ cdsp_command_inputdataend(another_id);
+
+ another_info->format_propagate = true;
+
+ if (another_fifo_id & FIFO_OFIFO_MASK)
+ cdsp_ofifo_start_real();
+ if (another_fifo_id & FIFO_RFIFO_MASK)
+ cdsp_rfifo_start_real();
+
+ } else
+ info->callback.on[CALLBACK_HOSTCOMMAND] = true;
+}
+
+static void cdsp_interrupt_proc_coder_sfr(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+ u8 command;
+
+ info = cdsp_coder_info_get(id);
+
+ /* Read SFR data */
+ cdsp_command_read_os2host(id, &info->coder);
+ command = info->coder.command;
+
+ if (command >= CDSP_CMD_OS2HOST_READY_MIN)
+ return; /* ready */
+
+ if (command <= CDSP_CMD_OS2HOST_CMN_MAX)
+ /* Common Command */
+ switch (command) {
+ case CDSP_CMD_OS2HOST_CMN_NOTIFY_OUT_FORMAT:
+ cdsp_output_format_notify_os2host(id);
+ break;
+ default:
+ /* DEC/ENC_SFR1 Write complete */
+ info->coder.params[CDSP_CMD_PARAM_RESULT_00] = 0;
+ info->coder.params[CDSP_CMD_PARAM_RESULT_01] = 0;
+ info->coder.params[CDSP_CMD_PARAM_RESULT_02] = 0;
+ info->coder.params[CDSP_CMD_PARAM_RESULT_03] = 0;
+ cdsp_command_write_complete(id, &info->coder);
+ break;
+ } else if (command <= CDSP_CMD_OS2HOST_PRG_MAX)
+ /* Callback (HOST COMMAND) */
+ info->callback.on[CALLBACK_HOSTCOMMAND] = true;
+}
+
+static void cdsp_interrupt_proc_coder_event(enum mc_cdsp_id id)
+{
+ u8 add, event;
+
+ /* Read EVT data */
+ if (id == CDSP_DECODER)
+ add = MCI_DEC_EVT;
+ else
+ add = MCI_ENC_EVT;
+
+ mc_read_c(add, &event, 1);
+ mc_packet_add_force_write_c(add, 0);
+
+ mc_packet_execute();
+
+ /* Timer Event */
+ if (event & EVENT_TIMER) {
+ /* Callback (TIMER) */
+ struct coder_info *info;
+ info = cdsp_coder_info_get(id);
+ info->callback.on[CALLBACK_TIMER] = true;
+ }
+}
+
+static int cdsp_coder_stop(enum mc_cdsp_id id, u8 verify)
+{
+ struct coder_info *info;
+ struct coder_params coder;
+ u32 fifo_id;
+ u8 data, addint;
+ int ret = 0;
+
+ info = cdsp_coder_info_get(id);
+
+ /* State check */
+ if (info->state != STATE_PLAYING)
+ return -EBUSY;
+
+ fifo_id = cdsp_fifoid_get(&info->conn_info);
+ if (fifo_id & FIFO_EFIFO) {
+ mc_read_c(MCI_DEC_FIFO_CH, &data, 1);
+ data &= ~MCB_DEC_EFIFO_START;
+ mc_packet_add_force_write_c(MCI_DEC_FIFO_CH, data);
+
+ mc_packet_execute();
+ }
+ if ((fifo_id & FIFO_DFIFO) &&
+ !(mc_fifo_info.rdfifo_bit_sel & MCB_DFIFO_SEL_HOST)) {
+ mc_read_c(MCI_RDFIFO_BIT_SEL, &data, 1);
+ data &= ~MCB_RDFIFO_DFIFO_START;
+ mc_packet_add_force_write_c(MCI_RDFIFO_BIT_SEL, data);
+
+ mc_packet_execute();
+ }
+
+ /* DEC/ENC Stop */
+ mc_read_c(MCI_DEC_START, &data, 1);
+ if (id == CDSP_DECODER) {
+ data &= ~MCB_DEC_DEC_START;
+ addint = MCI_DEC_ENABLE;
+ } else {
+ data &= ~MCB_DEC_ENC_START;
+ addint = MCI_ENC_ENABLE;
+ }
+ mc_packet_add_force_write_c(MCI_DEC_START, data);
+
+ mc_packet_execute();
+
+ /* VerifyStopCompletion command */
+ if (verify == MADEVCDSP_VERIFY_COMP_ON) {
+ coder.command = CDSP_CMD_HOST2OS_SYS_VERIFY_STOP_COMP;
+ ret = cdsp_command_write_host2os(id, &coder);
+ }
+
+ /* DEC/ENC END,ERR Interrupt Disable */
+ mc_read_c(addint, &data, 1);
+ data &= ~(MCB_EDEC_END | MCB_EDEC_ERR);
+ mc_packet_add_force_write_c(addint, data);
+
+ mc_packet_execute();
+
+ return ret;
+}
+
+static void cdsp_fifo_stop(enum mc_cdsp_id id)
+{
+ u32 fifo_id;
+ u8 data;
+
+ fifo_id = cdsp_fifoid_get_from_coderid(id);
+
+ if (fifo_id & FIFO_DFIFO_MASK) {
+ /* xFIFO/xPNT/xEMP/xUDF/xOVF Interrupt Disable */
+ mc_packet_add_force_write_c(MCI_DFIFO_ENABLE, 0);
+
+ mc_packet_execute();
+
+ mc_read_digital(MCI_ECDSP, &data, 1);
+ data &= ~MCB_EDFIFO;
+ mc_packet_add_force_write_if(MCI_ECDSP, data);
+
+ mc_packet_execute();
+ }
+
+ if (fifo_id & FIFO_EFIFO_MASK) {
+ /* xFIFO/xPNT/xEMP/xUDF/xOVF Interrupt Disable */
+ mc_packet_add_force_write_c(MCI_EFIFO_ENABLE, 0);
+
+ mc_packet_execute();
+
+ mc_read_digital(MCI_ECDSP, &data, 1);
+ data &= ~MCB_EEFIFO;
+ mc_packet_add_force_write_if(MCI_ECDSP, data);
+
+ mc_packet_execute();
+ }
+
+ if (fifo_id & FIFO_OFIFO_MASK) {
+ /* OUT Stop */
+ mc_read_c(MCI_DEC_START, &data, 1);
+
+ data &= ~MCB_DEC_OUT_START;
+ mc_packet_add_force_write_c(MCI_DEC_START, data);
+
+ /* xFIFO/xPNT/xEMP/xUDF/xOVF Interrupt Disable */
+ mc_packet_add_force_write_c(MCI_OFIFO_ENABLE, 0);
+
+ mc_packet_execute();
+
+ mc_read_digital(MCI_ECDSP, &data, 1);
+ data &= ~MCB_EOFIFO;
+ mc_packet_add_force_write_if(MCI_ECDSP, data);
+
+ mc_packet_execute();
+ }
+
+ if (fifo_id & FIFO_RFIFO_MASK) {
+ if (!(mc_fifo_info.rdfifo_bit_sel & MCB_RFIFO_SEL_HOST)) {
+ /* OUT Stop */
+ mc_read_c(MCI_DEC_START2, &data, 1);
+
+ data &= ~MCB_RFIFO_START;
+ mc_packet_add_force_write_c(MCI_DEC_START2, data);
+ }
+
+ /* xFIFO/xPNT/xEMP/xUDF/xOVF Interrupt Disable */
+ mc_packet_add_force_write_c(MCI_RFIFO_ENABLE, 0);
+
+ mc_packet_execute();
+
+ mc_read_digital(MCI_ECDSP, &data, 1);
+ data &= ~MCB_ERFIFO;
+ mc_packet_add_force_write_if(MCI_ECDSP, data);
+
+ mc_packet_execute();
+ }
+}
+
+static u32 cdsp_convert_sample_to_msec(u8 fs, u32 sample)
+{
+ u32 base, msec;
+
+ if (!sample)
+ return 0;
+
+ switch (fs) {
+ case CODER_FMT_FS_48000:
+ base = OUTPUT_FS_48000;
+ break;
+ case CODER_FMT_FS_44100:
+ base = OUTPUT_FS_44100;
+ break;
+ case CODER_FMT_FS_32000:
+ base = OUTPUT_FS_32000;
+ break;
+ case CODER_FMT_FS_24000:
+ base = OUTPUT_FS_24000;
+ break;
+ case CODER_FMT_FS_22050:
+ base = OUTPUT_FS_22050;
+ break;
+ case CODER_FMT_FS_16000:
+ base = OUTPUT_FS_16000;
+ break;
+ case CODER_FMT_FS_12000:
+ base = OUTPUT_FS_12000;
+ break;
+ case CODER_FMT_FS_11025:
+ base = OUTPUT_FS_11025;
+ break;
+ case CODER_FMT_FS_8000:
+ base = OUTPUT_FS_8000;
+ break;
+ default:
+ base = OUTPUT_FS_DEF;
+ break;
+ }
+
+ msec = (sample / base) * 1000;
+ msec += (((sample % base) * 1000) + (base - 1)) / base;
+
+ return msec;
+}
+
+static int cdsp_output_get_position(enum mc_cdsp_id id, u32 *pos)
+{
+ struct coder_info *info;
+ u32 output_pos;
+ u8 data[4];
+
+ info = cdsp_coder_info_get(id);
+
+ /* Path check */
+ switch (info->conn_info.dest) {
+ case CDSP_OUT_DEST_RFIFO:
+ case CDSP_OUT_DEST_OTHER_INBUF:
+ case CDSP_OUT_DEST_NONE:
+ return -EIO;
+ default:
+ break;
+ }
+
+ /* DEC_POS Read */
+ mc_read_c(MCI_DEC_POS1, &data[3], 1);
+ mc_read_c(MCI_DEC_POS2, &data[2], 1);
+ mc_read_c(MCI_DEC_POS3, &data[1], 1);
+ mc_read_c(MCI_DEC_POS4, &data[0], 1);
+
+ output_pos = (u32) data[3] << 24 | (u32) data[2] << 16 |
+ (u32) data[1] << 8 | (u32) data[0];
+
+ *pos = cdsp_convert_sample_to_msec(info->format.fs, output_pos);
+
+ return 0;
+}
+
+static void cdsp_interrupt_proc_coder_error(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+ struct coder_params coder;
+ u8 addr, data, error;
+ u32 pos = 0;
+ int ret;
+
+ info = cdsp_coder_info_get(id);
+
+ /* Read ERR data */
+ if (id == CDSP_DECODER)
+ addr = MCI_DEC_ERROR;
+ else
+ addr = MCI_ENC_ERROR;
+
+ mc_read_c(addr, &error, 1);
+
+ info->error_code = error;
+
+ ret = cdsp_output_get_position(id, &pos);
+ if (ret)
+ return;
+
+ if (error > DEC_ERR_PROG_SPECIFIC_MAX) {
+ /* Stop */
+ cdsp_fifo_stop(id);
+ ret = cdsp_coder_stop(id, MADEVCDSP_VERIFY_COMP_OFF);
+
+ /* Reset command */
+ coder.command = CDSP_CMD_HOST2OS_CMN_RESET;
+ ret = cdsp_command_write_host2os(id, &coder);
+
+ /* Command register Initialize */
+ cdsp_command_init(id);
+
+ /* EDEC/EENC_SFR Disable */
+ if (id == CDSP_DECODER) {
+ mc_read_c(MCI_DEC_ENABLE, &data, 1);
+ data &= ~MCB_EDEC_SFR;
+ mc_packet_add_force_write_c(MCI_DEC_ENABLE, data);
+ } else {
+ mc_read_c(MCI_ENC_ENABLE, &data, 1);
+ data &= ~MCB_EENC_SFR;
+ mc_packet_add_force_write_c(MCI_ENC_ENABLE, data);
+ }
+ mc_packet_execute();
+
+ /* EDEC/EENC Disable */
+ mc_read_digital(MCI_ECDSP, &data, 1);
+ if (id == CDSP_DECODER)
+ data &= ~MCB_EDEC;
+ else
+ data &= ~MCB_EENC;
+
+ mc_packet_add_force_write_if(MCI_ECDSP, data);
+ mc_packet_execute();
+
+ /* Parameter Initialize */
+ info->prog_info.vendor_id = 0;
+ info->prog_info.function_id = 0;
+
+ info->state = STATE_READY_SETUP;
+
+ /* Callback (ERROR) */
+ info->callback.on[CALLBACK_PLAY_ERROR2] = true;
+ info->callback.ex_info[CALLBACK_PLAY_ERROR2] =
+ (pos << 8) | (error & 0xFF);
+ } else {
+ cdsp_fifo_stop(id);
+ cdsp_coder_stop(id, MADEVCDSP_VERIFY_COMP_OFF);
+
+ info->state = STATE_READY;
+
+ /* Callback (ERROR) */
+ info->callback.on[CALLBACK_PLAY_ERROR1] = true;
+ info->callback.ex_info[CALLBACK_PLAY_ERROR1] =
+ (pos << 8) | (error & 0xFF);
+ }
+}
+
+static void cdsp_output_start(struct coder_info *info)
+{
+ u8 dest;
+
+ dest = info->conn_info.dest;
+ switch (dest) {
+ case CDSP_OUT_DEST_OFIFO:
+ break;
+ case CDSP_OUT_DEST_OFIFO_RFIFO:
+ if (mc_fifo_info.rdfifo_bit_sel & MCB_RFIFO_SEL_HOST)
+ dest = CDSP_OUT_DEST_OFIFO;
+ break;
+ case CDSP_OUT_DEST_RFIFO:
+ if (mc_fifo_info.rdfifo_bit_sel & MCB_RFIFO_SEL_HOST)
+ return;
+ break;
+ default:
+ return;
+ }
+
+ if (info->prog_info.output_start_mode && !info->change_output_fs)
+ return;
+
+ switch (dest) {
+ case CDSP_OUT_DEST_OFIFO:
+ if (!mc_fifo_info.ofifo_output_start)
+ return;
+
+ cdsp_ofifo_start_real();
+ break;
+ case CDSP_OUT_DEST_OFIFO_RFIFO:
+ if (!mc_fifo_info.ofifo_output_start ||
+ !mc_fifo_info.rfifo_output_start)
+ return;
+
+ cdsp_ofifo_start_real();
+ cdsp_rfifo_start_real();
+ break;
+ case CDSP_OUT_DEST_RFIFO:
+ if (!mc_fifo_info.rfifo_output_start)
+ return;
+
+ cdsp_rfifo_start_real();
+ break;
+ default:
+ break;
+ }
+}
+
+static void cdsp_interrupt_proc_coder_end(enum mc_cdsp_id id)
+{
+ struct coder_info *info, *another_info;
+ struct coder_params coder;
+ enum mc_cdsp_id another_id;
+ u8 data;
+
+ info = cdsp_coder_info_get(id);
+
+ another_id = cdsp_another_id_get(id);
+ another_info = cdsp_coder_info_get(another_id);
+
+ if (info->format_propagate) {
+ info->format.fs = another_info->format.fs;
+
+ /* DEC/ENC Stop */
+ mc_read_c(MCI_DEC_START, &data, 1);
+ if (id == CDSP_DECODER)
+ data &= ~MCB_DEC_DEC_START;
+ else
+ data &= ~MCB_DEC_ENC_START;
+
+ mc_packet_add_force_write_c(MCI_DEC_START, data);
+ mc_packet_execute();
+
+ /* VerifyStopCompletion command */
+ coder.command = CDSP_CMD_HOST2OS_SYS_VERIFY_STOP_COMP;
+ cdsp_command_write_host2os(id, &coder);
+
+ /* GetInputPos command */
+ coder.command = CDSP_CMD_HOST2OS_SYS_GET_INPUT_POS;
+ cdsp_command_write_host2os(id, &coder);
+
+ /* InputPos */
+ info->input_pos +=
+ *(u32 *) (coder.params + CDSP_CMD_PARAM_RESULT_00);
+
+ /* Clear command */
+ coder.command = CDSP_CMD_HOST2OS_CMN_CLEAR;
+ cdsp_command_write_host2os(id, &coder);
+
+ /* DEC/ENC Start */
+ mc_read_c(MCI_DEC_START, &data, 1);
+ if (id == CDSP_DECODER)
+ data |= MCB_DEC_DEC_START;
+ else
+ data |= MCB_DEC_ENC_START;
+
+ mc_packet_add_force_write_c(MCI_DEC_START, data);
+
+ mc_packet_execute();
+
+ info->format_propagate = false;
+
+ /* Callback (HOST Command) */
+ another_info->callback.on[CALLBACK_HOSTCOMMAND] = true;
+ } else {
+ switch (another_info->state) {
+ case STATE_READY_SETUP:
+ another_info->preinput_dataend_set = true;
+ break;
+ case STATE_READY:
+ case STATE_PLAYING:
+ if (another_info->conn_info.src ==
+ CDSP_IN_SOURCE_OTHER_OUTBUF) {
+ /* InputDataEnd command */
+ cdsp_command_inputdataend(another_id);
+ /* Input data end flag - set */
+ another_info->input_dataend_set = true;
+ cdsp_output_start(another_info);
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* ClearInputDataEnd command */
+ coder.command = CDSP_CMD_HOST2OS_SYS_CLEAR_INPUT_DATA_END;
+ cdsp_command_write_host2os(id, &coder);
+
+ /* Input data end flag - release */
+ info->input_dataend_set = false;
+
+ cdsp_fifo_stop(id);
+ cdsp_coder_stop(id, MADEVCDSP_VERIFY_COMP_ON);
+
+ info->state = STATE_READY;
+
+ /* Callback (DEC/ENC END) */
+ info->callback.on[CALLBACK_END_OF_SEQUENCE] = true;
+ }
+}
+
+static void cdsp_interrupt_proc_coder(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+ u8 addr, data, clear = 0;
+
+ info = cdsp_coder_info_get(id);
+
+ /* Read interrupt flag */
+ if (id == CDSP_DECODER)
+ addr = MCI_DEC_FLG;
+ else
+ addr = MCI_ENC_FLG;
+ mc_read_c(addr, &data, 1);
+
+ if (id == CODER_DEC) {
+ if (data & MCB_DEC_FLG_SFR) {
+ cdsp_interrupt_proc_coder_sfr(id);
+ clear |= MCB_DEC_FLG_SFR;
+ }
+ if (data & MCB_DEC_FLG_ERR) {
+ cdsp_interrupt_proc_coder_error(id);
+ clear |= MCB_DEC_FLG_ERR;
+ }
+ if ((data & MCB_DEC_FLG_END) && info->state == STATE_PLAYING) {
+ cdsp_interrupt_proc_coder_end(id);
+ clear |= MCB_DEC_FLG_END;
+ }
+ if (data & MCB_DEC_EVT_FLG) {
+ cdsp_interrupt_proc_coder_event(id);
+ clear |= MCB_DEC_EVT_FLG;
+ }
+ } else {
+ if (data & MCB_ENC_FLG_SFR) {
+ cdsp_interrupt_proc_coder_sfr(id);
+ clear |= MCB_ENC_FLG_SFR;
+ }
+ if (data & MCB_ENC_FLG_ERR) {
+ cdsp_interrupt_proc_coder_error(id);
+ clear |= MCB_ENC_FLG_ERR;
+ }
+ if ((data & MCB_ENC_FLG_END) && info->state == STATE_PLAYING) {
+ cdsp_interrupt_proc_coder_end(id);
+ clear |= MCB_ENC_FLG_END;
+ }
+ if (data & MCB_ENC_EVT_FLG) {
+ cdsp_interrupt_proc_coder_event(id);
+ clear |= MCB_ENC_EVT_FLG;
+ }
+ }
+
+ mc_packet_add_force_write_c(addr, clear);
+
+ mc_packet_execute();
+}
+
+static void cdsp_interrupt_proc_dfifo(void)
+{
+ struct coder_info *info;
+ u8 flag, ctrl;
+
+ /* Read interrupt flag */
+ mc_read_c(MCI_DFIFO_FLG, &flag, 1);
+
+ /* Interrupt process */
+ /* EDPNT, EDEMP Read */
+ mc_read_c(MCI_DFIFO_ENABLE, &ctrl, 1);
+
+ info = cdsp_coder_info_get(CODER_DEC);
+ if (!((info->conn_info.src == CDSP_IN_SOURCE_DFIFO ||
+ info->conn_info.src == CDSP_IN_SOURCE_DFIFO_EFIFO) &&
+ info->state > STATE_INIT)) {
+ info = cdsp_coder_info_get(CODER_ENC);
+ if (!((info->conn_info.src == CDSP_IN_SOURCE_DFIFO ||
+ info->conn_info.src == CDSP_IN_SOURCE_DFIFO_EFIFO) &&
+ info->state > STATE_INIT))
+ info = NULL;
+ }
+
+ /* DPNT */
+ if ((flag & MCB_DFIFO_FLG_DPNT) && (ctrl & MCB_DFIFO_EDPNT)) {
+ /* EDPNT Disable */
+ ctrl &= ~MCB_DFIFO_EDPNT;
+
+ /* Callback (DFIFO POINT) */
+ if (info)
+ info->callback.on[CALLBACK_DFIFOPOINT] = true;
+ }
+
+ /* DEMP */
+ if ((flag & MCB_DFIFO_FLG_DEMP) && (ctrl & MCB_DFIFO_EDEMP)) {
+ /* EDEMP Disable */
+ ctrl &= ~MCB_DFIFO_EDEMP;
+
+ /* Callback (DFIFO EMPTY) */
+ if (info)
+ info->callback.on[CALLBACK_DFIFOEMPTY] = true;
+ }
+
+ mc_packet_add_force_write_c(MCI_DFIFO_ENABLE, ctrl);
+
+ /* Clear interrupt flag */
+ mc_packet_add_force_write_c(MCI_DFIFO_FLG, flag);
+
+ mc_packet_execute();
+}
+
+static void cdsp_interrupt_proc_ofifo_core(void)
+{
+ struct coder_info *info;
+ u8 data;
+
+ /* EOPNT Disable */
+ mc_read_c(MCI_OFIFO_ENABLE, &data, 1);
+ data &= ~MCB_OFIFO_EOPNT;
+ mc_packet_add_force_write_c(MCI_OFIFO_ENABLE, data);
+
+ /* EOFIFO Disable */
+ mc_read_digital(MCI_ECDSP, &data, 1);
+ data &= ~MCB_EOFIFO;
+ mc_packet_add_force_write_if(MCI_ECDSP, data);
+
+ mc_packet_execute();
+
+ /* OUT START */
+ mc_fifo_info.ofifo_output_start = true;
+
+ info = cdsp_coder_info_get(CODER_DEC);
+ if (!((info->conn_info.dest == CDSP_OUT_DEST_OFIFO ||
+ info->conn_info.dest == CDSP_OUT_DEST_OFIFO_RFIFO) &&
+ info->state > STATE_INIT)) {
+ info = cdsp_coder_info_get(CODER_ENC);
+ if (!((info->conn_info.dest == CDSP_OUT_DEST_OFIFO ||
+ info->conn_info.dest == CDSP_OUT_DEST_OFIFO_RFIFO) &&
+ info->state > STATE_INIT))
+ info = NULL;
+ }
+
+ /* OUT_START Set */
+ if (info)
+ cdsp_output_start(info);
+}
+
+static inline void cdsp_interrupt_proc_ofifo(void)
+{
+ u8 flag;
+
+ /* Read interrupt flag */
+ mc_read_c(MCI_OFIFO_FLG, &flag, 1);
+
+ /* Interrupt process */
+ if (flag & MCB_OFIFO_FLG_OPNT)
+ cdsp_interrupt_proc_ofifo_core();
+
+ /* Clear interrupt flag */
+ mc_packet_add_force_write_c(MCI_OFIFO_FLG, flag);
+
+ mc_packet_execute();
+}
+
+static void cdsp_interrupt_proc_rfifo_core(void)
+{
+ struct coder_info *info;
+ u8 data;
+
+ /* ERPNT Disable */
+ mc_read_c(MCI_RFIFO_ENABLE, &data, 1);
+ data &= ~MCB_RFIFO_ERPNT;
+ mc_packet_add_force_write_c(MCI_RFIFO_ENABLE, data);
+
+ /* ERFIFO Disable */
+ mc_read_digital(MCI_ECDSP, &data, 1);
+ data &= ~MCB_ERFIFO;
+ mc_packet_add_force_write_if(MCI_ECDSP, data);
+
+ mc_packet_execute();
+
+ /* OUT START */
+ mc_fifo_info.rfifo_output_start = true;
+
+ info = cdsp_coder_info_get(CODER_DEC);
+ if (!((info->conn_info.dest == CDSP_OUT_DEST_RFIFO ||
+ info->conn_info.dest == CDSP_OUT_DEST_OFIFO_RFIFO) &&
+ info->state > STATE_INIT)) {
+ info = cdsp_coder_info_get(CODER_ENC);
+ if (!((info->conn_info.dest == CDSP_OUT_DEST_RFIFO ||
+ info->conn_info.dest == CDSP_OUT_DEST_OFIFO_RFIFO) &&
+ info->state > STATE_INIT))
+ info = NULL;
+ }
+
+ /* OUT_START Set */
+ if (info)
+ cdsp_output_start(info);
+}
+
+static inline void cdsp_interrupt_proc_rfifo_port(void)
+{
+ u8 flag;
+
+ /* Read interrupt flag */
+ mc_read_c(MCI_RFIFO_FLG, &flag, 1);
+
+ /* Interrupt process */
+ if (flag & MCB_OFIFO_FLG_OPNT)
+ cdsp_interrupt_proc_rfifo_core();
+
+ /* Clear interrupt flag */
+ mc_packet_add_force_write_c(MCI_RFIFO_FLG, flag);
+
+ mc_packet_execute();
+}
+
+static inline void cdsp_interrupt_proc_rfifo_host(void)
+{
+ struct coder_info *info;
+ u8 flag, ctrl;
+
+ /* Read interrupt flag */
+ mc_read_c(MCI_RFIFO_FLG, &flag, 1);
+
+ /* ERxxx Read */
+ mc_read_c(MCI_RFIFO_ENABLE, &ctrl, 1);
+
+ if (flag & MCB_RFIFO_FLG_RPNT) {
+ info = cdsp_coder_info_get(CODER_DEC);
+ if (!((info->conn_info.dest == CDSP_OUT_DEST_RFIFO ||
+ info->conn_info.dest == CDSP_OUT_DEST_OFIFO_RFIFO) &&
+ info->state > STATE_INIT)) {
+ info = cdsp_coder_info_get(CODER_ENC);
+ if (!((info->conn_info.dest == CDSP_OUT_DEST_RFIFO ||
+ info->conn_info.dest ==
+ CDSP_OUT_DEST_OFIFO_RFIFO)
+ && info->state > STATE_INIT))
+ info = NULL;
+ }
+
+ if (ctrl & MCB_RFIFO_ERPNT) {
+ /* ERPNT Disable */
+ ctrl &= ~MCB_RFIFO_ERPNT;
+
+ /* Callback (RFIFO POINT) */
+ if (info)
+ info->callback.on[CALLBACK_RFIFOPOINT] = true;
+ }
+
+ if ((flag & MCB_RFIFO_FLG_ROVF) && (ctrl & MCB_RFIFO_EROVF)) {
+ /* EROVF Disable */
+ ctrl &= ~MCB_RFIFO_EROVF;
+
+ /* Callback (RecBuf Overflow) */
+ if (info)
+ info->callback.on[CALLBACK_RECBUF_OVF] = true;
+ }
+
+ mc_packet_add_force_write_c(MCI_RFIFO_ENABLE, ctrl);
+ }
+
+ /* Clear interrupt flag */
+ mc_packet_add_force_write_c(MCI_RFIFO_FLG, flag);
+
+ mc_packet_execute();
+}
+
+static inline void cdsp_interrupt_proc_rfifo(void)
+{
+ if (mc_fifo_info.rdfifo_bit_sel & MCB_RFIFO_SEL_HOST)
+ cdsp_interrupt_proc_rfifo_host();
+ else
+ cdsp_interrupt_proc_rfifo_port();
+}
+
+static inline void cdsp_interrupt_proc(void)
+{
+ u8 data, error;
+
+ /* Read interrupt flag */
+ mc_read_c(MCI_CDSP_FLG, &data, 1);
+
+ /* Interrupt process */
+ if (data & MCB_CDSP_FLG_ERR) {
+ mc_read_c(MCI_CDSP_ERR, &error, 1);
+
+ mc_cdsp_info.hw_error_code = error;
+ } else if (data & MCB_CDSP_FLG_WDT)
+ mc_cdsp_info.hw_error_code = CDSP_ERR_WDT;
+
+ /* Interrupt ALL disable */
+ mc_packet_add_force_write_c(MCI_DEC_ENABLE, 0);
+ mc_packet_add_force_write_c(MCI_ENC_ENABLE, 0);
+ mc_packet_add_force_write_c(MCI_DFIFO_ENABLE, 0);
+ mc_packet_add_force_write_c(MCI_OFIFO_ENABLE, 0);
+ mc_packet_add_force_write_c(MCI_EFIFO_ENABLE, 0);
+ mc_packet_add_force_write_c(MCI_RFIFO_ENABLE, 0);
+ mc_packet_add_force_write_c(MCI_FFIFO_ENABLE, 0);
+ mc_packet_add_force_write_c(MCI_CDSP_ENABLE, 0);
+ mc_packet_add_force_write_if(MCI_ECDSP, 0);
+
+ /* State update */
+ mc_dec_info.state = STATE_NOTINIT;
+ mc_enc_info.state = STATE_NOTINIT;
+
+ /* Callback (HW ERROR) */
+ mc_dec_info.callback.on[CALLBACK_HW_ERROR] = true;
+ mc_dec_info.callback.ex_info[CALLBACK_HW_ERROR] =
+ mc_cdsp_info.hw_error_code & 0xFF;
+ mc_enc_info.callback.on[CALLBACK_HW_ERROR] = true;
+ mc_enc_info.callback.ex_info[CALLBACK_HW_ERROR] =
+ mc_cdsp_info.hw_error_code & 0xFF;
+
+ /* Clear interrupt flag */
+ mc_packet_add_force_write_c(MCI_CDSP_FLG, data);
+
+ mc_packet_execute();
+}
+
+static inline void cdsp_callback_proc_core(struct callback_info *callback,
+ int handle)
+{
+ callback->on[CALLBACK_HOSTCOMMAND] = false;
+ callback->on[CALLBACK_END_OF_SEQUENCE] = false;
+ callback->on[CALLBACK_DFIFOPOINT] = false;
+ callback->on[CALLBACK_RFIFOPOINT] = false;
+ callback->on[CALLBACK_DFIFOEMPTY] = false;
+ callback->on[CALLBACK_RECBUF_OVF] = false;
+ callback->on[CALLBACK_TIMER] = false;
+ callback->on[CALLBACK_PLAY_ERROR1] = false;
+ callback->ex_info[CALLBACK_PLAY_ERROR1] = 0;
+ callback->on[CALLBACK_PLAY_ERROR2] = false;
+ callback->ex_info[CALLBACK_PLAY_ERROR2] = 0;
+ callback->on[CALLBACK_HW_ERROR] = false;
+ callback->ex_info[CALLBACK_HW_ERROR] = 0;
+}
+
+static inline void cdsp_callback_proc(void)
+{
+ cdsp_callback_proc_core(&mc_dec_info.callback, 0);
+ cdsp_callback_proc_core(&mc_enc_info.callback, 1);
+}
+
+static void cdsp_get_data(struct mcdrv_aec_info *aec_info,
+ struct aec_cdsp_info *cdsp_info)
+{
+ struct aec_cdsp_func_info *finfo_a;
+ struct aec_cdsp_func_info *finfo_b;
+
+ finfo_a = &cdsp_info->func_info[AEC_FUNC_INFO_A];
+ finfo_b = &cdsp_info->func_info[AEC_FUNC_INFO_B];
+
+ finfo_a->id = CDSP_DECODER;
+ finfo_a->func_on = false;
+ finfo_a->data = NULL;
+ finfo_a->data_size = 0;
+
+ finfo_b->id = CDSP_ENCODER;
+ finfo_b->func_on = false;
+ finfo_b->data = NULL;
+ finfo_b->data_size = 0;
+
+ if (aec_info->vbox.enable) {
+ finfo_a->func_on = aec_info->vbox.cdsp_func_a_on;
+ finfo_b->func_on = aec_info->vbox.cdsp_func_b_on;
+
+ if (!finfo_a->func_on && !finfo_b->func_on)
+ return;
+
+ if (finfo_a->func_on) {
+ finfo_a->data = aec_info->vbox.cdsp_a.data;
+ finfo_a->data_size = aec_info->vbox.cdsp_a.data_size;
+ }
+
+ if (finfo_b->func_on) {
+ finfo_b->data = aec_info->vbox.cdsp_b.data;
+ finfo_b->data_size = aec_info->vbox.cdsp_b.data_size;
+ }
+ }
+
+ if (finfo_a->data)
+ finfo_a->data = &finfo_a->data[CHUNK_SIZE];
+
+ if (finfo_b->data)
+ finfo_b->data = &finfo_b->data[CHUNK_SIZE];
+}
+
+static inline int cdsp_fifo_check(enum mc_cdsp_id id,
+ struct aec_cdsp_info *cdsp_info)
+{
+ struct aec_cdsp_func_info *finfo;
+ u32 pos, sample, fifo_id;
+ u8 sel, fifo, src, dest, bit, ch, etobuf, tmp;
+ u8 *data;
+
+ if (id == CDSP_DECODER)
+ finfo = &cdsp_info->func_info[AEC_FUNC_INFO_A];
+ else
+ finfo = &cdsp_info->func_info[AEC_FUNC_INFO_B];
+
+ data = finfo->fifo_data;
+
+ fifo = data[CDSP_USE_FIFO];
+ if (fifo != CDSP_FIFO_DONTCARE) {
+ if ((fifo & CDSP_FIFO_OTHER_OUTBUF_BIT) &&
+ ((fifo & CDSP_FIFO_EFIFO_BIT) ||
+ (fifo & CDSP_FIFO_DFIFO_BIT)))
+ return -EINVAL;
+
+ if ((fifo & CDSP_FIFO_OTHER_INBUF_BIT) &&
+ ((fifo & CDSP_FIFO_OFIFO_BIT) ||
+ (fifo & CDSP_FIFO_RFIFO_BIT)))
+ return -EINVAL;
+
+ if (fifo & CDSP_FIFO_OTHER_OUTBUF_BIT)
+ src = CDSP_IN_SOURCE_OTHER_OUTBUF;
+ else if ((fifo & CDSP_FIFO_EFIFO_BIT) &&
+ (fifo & CDSP_FIFO_DFIFO_BIT))
+ src = CDSP_IN_SOURCE_DFIFO_EFIFO;
+ else if (fifo & CDSP_FIFO_DFIFO_BIT)
+ src = CDSP_IN_SOURCE_DFIFO;
+ else if (fifo & CDSP_FIFO_EFIFO_BIT)
+ src = CDSP_IN_SOURCE_EFIFO;
+ else
+ src = CDSP_IN_SOURCE_NONE;
+
+ finfo->conn_info.src = src;
+
+ if (fifo & CDSP_FIFO_OTHER_INBUF_BIT)
+ dest = CDSP_OUT_DEST_OTHER_INBUF;
+ else if ((fifo & CDSP_FIFO_OFIFO_BIT) &&
+ (fifo & CDSP_FIFO_RFIFO_BIT))
+ dest = CDSP_OUT_DEST_OFIFO_RFIFO;
+ else if (fifo & CDSP_FIFO_OFIFO_BIT)
+ dest = CDSP_OUT_DEST_OFIFO;
+ else if (fifo & CDSP_FIFO_RFIFO_BIT)
+ dest = CDSP_OUT_DEST_RFIFO;
+ else
+ dest = CDSP_OUT_DEST_NONE;
+
+ finfo->conn_info.dest = dest;
+ }
+
+ fifo_id = cdsp_fifoid_get(&finfo->conn_info);
+
+ /* EFIFO */
+ if (fifo_id & FIFO_EFIFO) {
+ tmp = data[ROUTE_EFIFO0_SEL];
+ if (tmp != CDSP_FIFO_DONTCARE) {
+ sel = cdsp_info->efifo01_sel & ~MCB_EFIFO0_SEL;
+ sel |= tmp & MCB_EFIFO0_SEL;
+ cdsp_info->efifo01_sel = sel;
+ }
+
+ tmp = data[ROUTE_EFIFO1_SEL];
+ if (tmp != CDSP_FIFO_DONTCARE) {
+ sel = cdsp_info->efifo01_sel & ~MCB_EFIFO1_SEL;
+ sel |= (tmp << 4) & MCB_EFIFO1_SEL;
+ cdsp_info->efifo01_sel = sel;
+ }
+
+ tmp = data[ROUTE_EFIFO2_SEL];
+ if (tmp != CDSP_FIFO_DONTCARE) {
+ sel = cdsp_info->efifo23_sel & ~MCB_EFIFO2_SEL;
+ sel |= tmp & MCB_EFIFO2_SEL;
+ cdsp_info->efifo23_sel = sel;
+ }
+
+ tmp = data[ROUTE_EFIFO3_SEL];
+ if (tmp != CDSP_FIFO_DONTCARE) {
+ sel = cdsp_info->efifo23_sel & ~MCB_EFIFO3_SEL;
+ sel |= (tmp << 4) & MCB_EFIFO3_SEL;
+ cdsp_info->efifo23_sel = sel;
+ }
+
+ /* 0: 2ch 16bit */
+ /* 1: 4ch 16bit */
+ /* 2: 2ch 32bit */
+ /* 3: 4ch 32bit */
+ ch = finfo->conn_ex_info.efifo_ch;
+ bit = finfo->bit_width.efifo;
+ etobuf = finfo->format.etobuf;
+
+ tmp = data[CDSP_EFIFO_CH];
+ switch (tmp) {
+ case 2:
+ case 4:
+ ch = tmp;
+ break;
+ case CDSP_FIFO_DONTCARE:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ tmp = data[CDSP_EFIFO_BIT_WIDTH];
+ switch (tmp) {
+ case 16:
+ case 32:
+ bit = tmp;
+ break;
+ case CDSP_FIFO_DONTCARE:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ tmp = data[CDSP_EFIFO_E2BUF_MODE];
+ switch (tmp) {
+ case CODER_FMT_ETOBUF_LRMIX:
+ case CODER_FMT_ETOBUF_LCH:
+ case CODER_FMT_ETOBUF_RCH:
+ etobuf = tmp;
+ break;
+ case CDSP_FIFO_DONTCARE:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ finfo->conn_ex_info.efifo_ch = ch;
+ finfo->bit_width.efifo = bit;
+ finfo->format.etobuf = etobuf;
+ }
+
+ /* OFIFO */
+ tmp = data[ROUTE_OUT0L_SEL];
+ if (tmp != CDSP_FIFO_DONTCARE) {
+ if ((fifo_id & FIFO_OFIFO) ||
+ (tmp == OUT_LOOPBACK_L) || (tmp == OUT_LOOPBACK_R)) {
+ sel = cdsp_info->out0_sel & ~MCB_OUT0L_SEL;
+ sel |= tmp & MCB_OUT0L_SEL;
+ cdsp_info->out0_sel = sel;
+ }
+ }
+
+ tmp = data[ROUTE_OUT0R_SEL];
+ if (tmp != CDSP_FIFO_DONTCARE) {
+ if ((fifo_id & FIFO_OFIFO) ||
+ (tmp == OUT_LOOPBACK_L) || (tmp == OUT_LOOPBACK_R)) {
+ sel = cdsp_info->out0_sel & ~MCB_OUT0R_SEL;
+ sel |= (tmp << 4) & MCB_OUT0R_SEL;
+ cdsp_info->out0_sel = sel;
+ }
+ }
+
+ tmp = data[ROUTE_OUT1L_SEL];
+ if (tmp != CDSP_FIFO_DONTCARE) {
+ if ((fifo_id & FIFO_OFIFO) ||
+ (tmp == OUT_LOOPBACK_L) || (tmp == OUT_LOOPBACK_R)) {
+ sel = cdsp_info->out1_sel & ~MCB_OUT1L_SEL;
+ sel |= tmp & MCB_OUT1L_SEL;
+ cdsp_info->out1_sel = sel;
+ }
+ }
+
+ tmp = data[ROUTE_OUT1R_SEL];
+ if (tmp != CDSP_FIFO_DONTCARE) {
+ if ((fifo_id & FIFO_OFIFO) ||
+ (tmp == OUT_LOOPBACK_L) || (tmp == OUT_LOOPBACK_R)) {
+ sel = cdsp_info->out1_sel & ~MCB_OUT1R_SEL;
+ sel |= (tmp << 4) & MCB_OUT1R_SEL;
+ cdsp_info->out1_sel = sel;
+ }
+ }
+
+ tmp = data[ROUTE_OUT2L_SEL];
+ if (tmp != CDSP_FIFO_DONTCARE) {
+ if ((fifo_id & FIFO_OFIFO) ||
+ (tmp == OUT_LOOPBACK_L) || (tmp == OUT_LOOPBACK_R)) {
+ sel = cdsp_info->out2_sel & ~MCB_OUT2L_SEL;
+ sel |= tmp & MCB_OUT2L_SEL;
+ cdsp_info->out2_sel = sel;
+ }
+ }
+
+ tmp = data[ROUTE_OUT2R_SEL];
+ if (tmp != CDSP_FIFO_DONTCARE) {
+ if ((fifo_id & FIFO_OFIFO) ||
+ (tmp == OUT_LOOPBACK_L) || (tmp == OUT_LOOPBACK_R)) {
+ sel = cdsp_info->out2_sel & ~MCB_OUT2R_SEL;
+ sel |= (tmp << 4) & MCB_OUT2R_SEL;
+ cdsp_info->out2_sel = sel;
+ }
+ }
+
+ if (fifo_id & FIFO_OFIFO) {
+ /* 0: 2ch 16bit) */
+ /* 1: 4ch 16bit */
+ /* 2: 2ch 32bit */
+ /* 3: 4ch 32bit */
+ ch = finfo->conn_ex_info.ofifo_ch;
+ bit = finfo->bit_width.ofifo;
+
+ tmp = data[CDSP_OFIFO_CH];
+ switch (tmp) {
+ case 2:
+ case 4:
+ ch = tmp;
+ break;
+ case CDSP_FIFO_DONTCARE:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ tmp = data[CDSP_OFIFO_BIT_WIDTH];
+ switch (tmp) {
+ case 16:
+ case 32:
+ bit = tmp;
+ break;
+ case CDSP_FIFO_DONTCARE:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ finfo->conn_ex_info.ofifo_ch = ch;
+ finfo->bit_width.ofifo = bit;
+
+ sample = ((u32) data[CDSP_OFIFO_BUFFERING + 0] << 8) |
+ (u32) data[CDSP_OFIFO_BUFFERING + 1];
+ if (sample != CDSP_FIFO_DONTCARE_W) {
+ if (sample > OFIFO_BUF_SAMPLE_MAX)
+ return -EINVAL;
+ cdsp_info->ofifo_buf_sample = sample;
+ }
+ }
+
+ /* DFIFO */
+ if (fifo_id & FIFO_DFIFO) {
+ tmp = data[CDSP_DFIFO_BIT_WIDTH];
+ if (tmp != CDSP_FIFO_DONTCARE) {
+ sel = cdsp_info->rdfifo_bit_sel & ~MCB_DFIFO_BIT;
+ if (tmp == 32)
+ sel |= MCB_DFIFO_BIT;
+ cdsp_info->rdfifo_bit_sel = sel;
+ }
+
+ pos = ((u32) data[CDSP_DFIFO_CB_POINT + 0] << 8) |
+ (u32) data[CDSP_DFIFO_CB_POINT + 1];
+ switch (pos) {
+ case CDSP_FIFO_DONTCARE_CB:
+ break;
+ case CDSP_FIFO_NOT_CB:
+ cdsp_info->dfifo_cb_pos = CBPOS_DFIFO_NONE;
+ break;
+ default:
+ if (pos > CBPOS_DFIFO_MAX)
+ return -EINVAL;
+
+ cdsp_info->dfifo_cb_pos = pos;
+ break;
+ }
+ }
+
+ /* RFIFO */
+ if (fifo_id & FIFO_RFIFO) {
+ tmp = data[CDSP_RFIFO_BIT_WIDTH];
+ if (tmp != CDSP_FIFO_DONTCARE) {
+ sel = cdsp_info->rdfifo_bit_sel & ~MCB_RFIFO_BIT;
+ if (tmp == 32)
+ sel |= MCB_RFIFO_BIT;
+ cdsp_info->rdfifo_bit_sel = sel;
+ }
+
+ pos = ((u32) data[CDSP_RFIFO_CB_POINT + 0] << 8) |
+ (u32) data[CDSP_RFIFO_CB_POINT + 1];
+ switch (pos) {
+ case CDSP_FIFO_DONTCARE_CB:
+ break;
+ case CDSP_FIFO_NOT_CB:
+ cdsp_info->rfifo_cb_pos = CBPOS_RFIFO_NONE;
+ break;
+ default:
+ if (pos > CBPOS_RFIFO_MAX)
+ return -EINVAL;
+
+ cdsp_info->rfifo_cb_pos = pos;
+ break;
+ }
+
+ sample = ((u32) data[CDSP_RFIFO_BUFFERING + 0] << 8) |
+ (u32) data[CDSP_RFIFO_BUFFERING + 1];
+ if (sample != CDSP_FIFO_DONTCARE_W) {
+ if (sample > RFIFO_BUF_SAMPLE_MAX)
+ return -EINVAL;
+
+ cdsp_info->rfifo_buf_sample = sample;
+ }
+ }
+
+ return 0;
+}
+
+static int cdsp_memoryrange_check(u16 start1, u16 size1, u16 start2, u16 size2)
+{
+ u16 end1, end2;
+
+ end1 = start1 + size1 - 1;
+ end2 = start2 + size2 - 1;
+
+ if (start2 >= start1 && start2 <= end1)
+ return -EINVAL;
+
+ if (end2 >= start1 && end2 <= end1)
+ return -EINVAL;
+
+ if (start1 >= start2 && start1 <= end2)
+ return -EINVAL;
+
+ if (end1 >= start2 && end1 <= end2)
+ return -EINVAL;
+
+ return 0;
+}
+
+static inline int cdsp_program_check(enum mc_cdsp_id id,
+ struct coder_firmware *coder)
+{
+ struct coder_info *info;
+ struct coder_info *another_info;
+ struct program_info *another_pinfo;
+ u16 prog_loadaddr, prog_size;
+ u16 data_loadaddr, data_size;
+ u16 work_begin, work_size;
+ u16 stack_begin, stack_size;
+ u16 prog_type;
+ u32 total_size;
+ int ret;
+
+ info = cdsp_coder_info_get(id);
+ another_info = cdsp_coder_info_get(cdsp_another_id_get(id));
+
+ /* Size Check */
+ if (coder->size < PRG_DESC_PROGRAM)
+ return -EINVAL;
+
+ total_size = MAKE_HALFWORD(coder->firmware[PRG_DESC_PRG_SIZE],
+ coder->firmware[PRG_DESC_PRG_SIZE + 1]);
+ total_size += MAKE_HALFWORD(coder->firmware[PRG_DESC_DATA_SIZE],
+ coder->firmware[PRG_DESC_DATA_SIZE + 1]);
+ total_size += PRG_DESC_PROGRAM / 2;
+ if (coder->size != (total_size * 2))
+ return -EINVAL;
+
+ /* Program Type Check */
+ prog_type = MAKE_HALFWORD(coder->firmware[PRG_DESC_PRG_TYPE],
+ coder->firmware[PRG_DESC_PRG_TYPE + 1]);
+ if (id == CDSP_DECODER && prog_type != PRG_PRM_TYPE_TASK0)
+ return -EINVAL;
+
+ if (id == CDSP_ENCODER && prog_type != PRG_PRM_TYPE_TASK1)
+ return -EINVAL;
+
+ if (another_info->state == STATE_NOTINIT ||
+ another_info->state == STATE_INIT)
+ return 0;
+
+ /* RAM Check */
+ prog_loadaddr = MAKE_HALFWORD(coder->firmware[PRG_DESC_PRG_LOAD_ADR],
+ coder->firmware[PRG_DESC_PRG_LOAD_ADR +
+ 1]);
+ prog_size =
+ MAKE_HALFWORD(coder->firmware[PRG_DESC_PRG_SIZE],
+ coder->firmware[PRG_DESC_PRG_SIZE + 1]);
+ data_loadaddr =
+ MAKE_HALFWORD(coder->firmware[PRG_DESC_DATA_LOAD_ADR],
+ coder->firmware[PRG_DESC_DATA_LOAD_ADR + 1]);
+ data_size =
+ MAKE_HALFWORD(coder->firmware[PRG_DESC_DATA_SIZE],
+ coder->firmware[PRG_DESC_DATA_SIZE + 1]);
+ work_begin =
+ MAKE_HALFWORD(coder->firmware[PRG_DESC_WORK_BEGIN_ADR],
+ coder->firmware[PRG_DESC_WORK_BEGIN_ADR + 1]);
+ work_size =
+ MAKE_HALFWORD(coder->firmware[PRG_DESC_WORK_SIZE],
+ coder->firmware[PRG_DESC_WORK_SIZE + 1]);
+ stack_begin =
+ MAKE_HALFWORD(coder->firmware[PRG_DESC_STACK_BEGIN_ADR],
+ coder->firmware[PRG_DESC_STACK_BEGIN_ADR + 1]);
+ stack_size =
+ MAKE_HALFWORD(coder->firmware[PRG_DESC_STACK_SIZE],
+ coder->firmware[PRG_DESC_STACK_SIZE + 1]);
+ another_pinfo = &another_info->prog_info;
+
+ /* Program & Program */
+ ret = cdsp_memoryrange_check(prog_loadaddr, prog_size,
+ another_pinfo->prog_loadaddr,
+ another_pinfo->prog_size);
+ if (ret < 0)
+ return ret;
+
+ /* Data & Data */
+ ret = cdsp_memoryrange_check(data_loadaddr, data_size,
+ another_pinfo->data_loadaddr,
+ another_pinfo->data_size);
+ if (ret < 0)
+ return ret;
+
+ /* Data & Stack */
+ ret = cdsp_memoryrange_check(data_loadaddr, data_size,
+ another_pinfo->stack_begin,
+ another_pinfo->stack_size);
+ if (ret < 0)
+ return ret;
+
+ ret = cdsp_memoryrange_check(stack_begin, stack_size,
+ another_pinfo->data_loadaddr,
+ another_pinfo->data_size);
+ if (ret < 0)
+ return ret;
+
+ /* Work & Work */
+ ret = cdsp_memoryrange_check(work_begin, work_size,
+ another_pinfo->work_begin,
+ another_pinfo->work_size);
+ if (ret < 0)
+ return ret;
+
+ /* Work & Stack */
+ ret = cdsp_memoryrange_check(work_begin, work_size,
+ another_pinfo->stack_begin,
+ another_pinfo->stack_size);
+ if (ret < 0)
+ return ret;
+
+ return cdsp_memoryrange_check(stack_begin, stack_size,
+ another_pinfo->work_begin,
+ another_pinfo->work_size);
+}
+
+static inline int cdsp_aec_program_check(struct coder_firmware *coder_a,
+ struct coder_firmware *coder_b)
+{
+ u16 prog_loadaddr_a, prog_size_a;
+ u16 data_loadaddr_a, data_size_a;
+ u16 work_begin_a, work_size_a;
+ u16 stack_begin_a, stack_size_a;
+ u32 total_size_a;
+ u16 prog_loadaddr_b, prog_size_b;
+ u16 data_loadaddr_b, data_size_b;
+ u16 work_begin_b, work_size_b;
+ u16 stack_begin_b, stack_size_b;
+ u32 total_size_b;
+ int ret;
+
+ total_size_a = MAKE_HALFWORD(coder_a->firmware[PRG_DESC_PRG_SIZE],
+ coder_a->firmware[PRG_DESC_PRG_SIZE + 1]);
+ total_size_a += MAKE_HALFWORD(coder_a->firmware[PRG_DESC_DATA_SIZE],
+ coder_a->firmware[PRG_DESC_DATA_SIZE +
+ 1]);
+ total_size_a += PRG_DESC_PROGRAM / 2;
+
+ total_size_b = MAKE_HALFWORD(coder_b->firmware[PRG_DESC_PRG_SIZE],
+ coder_b->firmware[PRG_DESC_PRG_SIZE + 1]);
+ total_size_b += MAKE_HALFWORD(coder_b->firmware[PRG_DESC_DATA_SIZE],
+ coder_b->firmware[PRG_DESC_DATA_SIZE +
+ 1]);
+ total_size_b += PRG_DESC_PROGRAM / 2;
+
+ /* RAM Check */
+ prog_loadaddr_a =
+ MAKE_HALFWORD(coder_a->firmware[PRG_DESC_PRG_LOAD_ADR],
+ coder_a->firmware[PRG_DESC_PRG_LOAD_ADR + 1]);
+ prog_loadaddr_b =
+ MAKE_HALFWORD(coder_b->firmware[PRG_DESC_PRG_LOAD_ADR],
+ coder_b->firmware[PRG_DESC_PRG_LOAD_ADR + 1]);
+
+ prog_size_a = MAKE_HALFWORD(coder_a->firmware[PRG_DESC_PRG_SIZE],
+ coder_a->firmware[PRG_DESC_PRG_SIZE + 1]);
+ prog_size_b = MAKE_HALFWORD(coder_b->firmware[PRG_DESC_PRG_SIZE],
+ coder_b->firmware[PRG_DESC_PRG_SIZE + 1]);
+
+ data_loadaddr_a =
+ MAKE_HALFWORD(coder_a->firmware[PRG_DESC_DATA_LOAD_ADR],
+ coder_a->firmware[PRG_DESC_DATA_LOAD_ADR + 1]);
+ data_loadaddr_b =
+ MAKE_HALFWORD(coder_b->firmware[PRG_DESC_DATA_LOAD_ADR],
+ coder_b->firmware[PRG_DESC_DATA_LOAD_ADR + 1]);
+
+ data_size_a = MAKE_HALFWORD(coder_a->firmware[PRG_DESC_DATA_SIZE],
+ coder_a->firmware[PRG_DESC_DATA_SIZE + 1]);
+ data_size_b = MAKE_HALFWORD(coder_b->firmware[PRG_DESC_DATA_SIZE],
+ coder_b->firmware[PRG_DESC_DATA_SIZE + 1]);
+
+ work_begin_a = MAKE_HALFWORD(coder_a->firmware[PRG_DESC_WORK_BEGIN_ADR],
+ coder_a->firmware[PRG_DESC_WORK_BEGIN_ADR +
+ 1]);
+ work_begin_b =
+ MAKE_HALFWORD(coder_b->firmware[PRG_DESC_WORK_BEGIN_ADR],
+ coder_b->firmware[PRG_DESC_WORK_BEGIN_ADR + 1]);
+
+ work_size_a = MAKE_HALFWORD(coder_a->firmware[PRG_DESC_WORK_SIZE],
+ coder_a->firmware[PRG_DESC_WORK_SIZE + 1]);
+ work_size_b = MAKE_HALFWORD(coder_b->firmware[PRG_DESC_WORK_SIZE],
+ coder_b->firmware[PRG_DESC_WORK_SIZE + 1]);
+
+ stack_begin_a =
+ MAKE_HALFWORD(coder_a->firmware[PRG_DESC_STACK_BEGIN_ADR],
+ coder_a->firmware[PRG_DESC_STACK_BEGIN_ADR + 1]);
+ stack_begin_b =
+ MAKE_HALFWORD(coder_b->firmware[PRG_DESC_STACK_BEGIN_ADR],
+ coder_b->firmware[PRG_DESC_STACK_BEGIN_ADR + 1]);
+
+ stack_size_a = MAKE_HALFWORD(coder_a->firmware[PRG_DESC_STACK_SIZE],
+ coder_a->firmware[PRG_DESC_STACK_SIZE +
+ 1]);
+ stack_size_b =
+ MAKE_HALFWORD(coder_b->firmware[PRG_DESC_STACK_SIZE],
+ coder_b->firmware[PRG_DESC_STACK_SIZE + 1]);
+
+ /* Program & Program */
+ ret = cdsp_memoryrange_check(prog_loadaddr_a, prog_size_a,
+ prog_loadaddr_b, prog_size_b);
+ if (ret < 0)
+ return ret;
+
+ /* Data & Data */
+ ret = cdsp_memoryrange_check(data_loadaddr_a, data_size_a,
+ data_loadaddr_b, data_size_b);
+ if (ret < 0)
+ return ret;
+
+ /* Data & Stack */
+ ret = cdsp_memoryrange_check(data_loadaddr_a, data_size_a,
+ stack_begin_b, stack_size_b);
+ if (ret < 0)
+ return ret;
+
+ ret = cdsp_memoryrange_check(stack_begin_a, stack_size_a,
+ data_loadaddr_b, data_size_b);
+ if (ret < 0)
+ return ret;
+
+ /* Work & Work */
+ ret = cdsp_memoryrange_check(work_begin_a, work_size_a,
+ work_begin_b, work_size_b);
+ if (ret < 0)
+ return ret;
+
+ /* Work & Stack */
+ ret = cdsp_memoryrange_check(work_begin_a, work_size_a,
+ stack_begin_b, stack_size_b);
+ if (ret < 0)
+ return ret;
+
+ return cdsp_memoryrange_check(stack_begin_a, stack_size_a,
+ work_begin_b, work_size_b);
+}
+
+static int cdsp_inout_path_check(struct connection_info *conn,
+ struct connection_info *another_conn)
+{
+ /* Input */
+ switch (conn->src) {
+ case CDSP_IN_SOURCE_OTHER_OUTBUF:
+ case CDSP_IN_SOURCE_NONE:
+ break;
+ /* DFIFO */
+ case CDSP_IN_SOURCE_DFIFO:
+ switch (another_conn->src) {
+ case CDSP_IN_SOURCE_EFIFO:
+ case CDSP_IN_SOURCE_OTHER_OUTBUF:
+ case CDSP_IN_SOURCE_NONE:
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ /* EFIFO */
+ case CDSP_IN_SOURCE_EFIFO:
+ switch (another_conn->src) {
+ case CDSP_IN_SOURCE_DFIFO:
+ case CDSP_IN_SOURCE_OTHER_OUTBUF:
+ case CDSP_IN_SOURCE_NONE:
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ /* DFIFO & EFIFO */
+ case CDSP_IN_SOURCE_DFIFO_EFIFO:
+ switch (another_conn->src) {
+ case CDSP_IN_SOURCE_OTHER_OUTBUF:
+ case CDSP_IN_SOURCE_NONE:
+ break;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EIO;
+ }
+
+ /* output */
+ switch (conn->dest) {
+ case CDSP_OUT_DEST_OTHER_INBUF:
+ case CDSP_OUT_DEST_NONE:
+ break;
+ /* RFIFO */
+ case CDSP_OUT_DEST_RFIFO:
+ switch (another_conn->dest) {
+ case CDSP_OUT_DEST_OFIFO:
+ case CDSP_OUT_DEST_OTHER_INBUF:
+ case CDSP_OUT_DEST_NONE:
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ /* OFIFO */
+ case CDSP_OUT_DEST_OFIFO:
+ switch (another_conn->dest) {
+ case CDSP_OUT_DEST_RFIFO:
+ case CDSP_OUT_DEST_OTHER_INBUF:
+ case CDSP_OUT_DEST_NONE:
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ /* RFIFO & OFIFO */
+ case CDSP_OUT_DEST_OFIFO_RFIFO:
+ switch (another_conn->dest) {
+ case CDSP_OUT_DEST_OTHER_INBUF:
+ case CDSP_OUT_DEST_NONE:
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static inline int cdsp_inout_type_check(struct connection_info *conn_info,
+ u16 inout_type)
+{
+ u16 in_type, out_type;
+
+ in_type = inout_type & PRG_PRM_IOTYPE_IN_MASK;
+ out_type = inout_type & PRG_PRM_IOTYPE_OUT_MASK;
+
+ /* Input type check */
+ if (in_type == PRG_PRM_IOTYPE_IN_NOPCM) {
+ switch (conn_info->src) {
+ case CDSP_IN_SOURCE_NONE:
+ case CDSP_IN_SOURCE_DFIFO:
+ break;
+ default:
+ return -EIO;
+ }
+ }
+
+ /* Output type check */
+ if (out_type == PRG_PRM_IOTYPE_OUT_NOPCM) {
+ switch (conn_info->dest) {
+ case CDSP_OUT_DEST_NONE:
+ case CDSP_OUT_DEST_RFIFO:
+ break;
+ default:
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static inline int cdsp_path_check(enum mc_cdsp_id id, u16 inout_type,
+ struct connection_info *conn_info)
+{
+ struct coder_info *another_info;
+ u8 state;
+ int ret;
+
+ another_info = cdsp_coder_info_get(cdsp_another_id_get(id));
+
+ state = another_info->state;
+ if (state == STATE_READY_SETUP || state == STATE_READY ||
+ state == STATE_PLAYING) {
+ /* Check Input/Output path */
+ ret =
+ cdsp_inout_path_check(conn_info, &another_info->conn_info);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* Check Input/Output Type */
+ return cdsp_inout_type_check(conn_info, inout_type);
+}
+
+static int cdsp_data_analyze_coder(enum mc_cdsp_id id,
+ struct aec_cdsp_info *cdsp_info)
+{
+ struct aec_cdsp_func_info *finfo;
+ struct coder_info *cinfo;
+ struct coder_firmware coder;
+ u8 *data;
+ u32 data_size;
+ u32 top, tag, size, tmp;
+ int ret;
+
+ if (id == CDSP_DECODER)
+ finfo = &cdsp_info->func_info[AEC_FUNC_INFO_A];
+ else
+ finfo = &cdsp_info->func_info[AEC_FUNC_INFO_B];
+
+ data = finfo->data;
+ data_size = finfo->data_size;
+ finfo->fifo_data = NULL;
+ finfo->prog_data = NULL;
+ finfo->prog_size = 0;
+ finfo->param_data = NULL;
+ finfo->param_num = 0;
+ finfo->ext = NULL;
+
+ cinfo = cdsp_coder_info_get(id);
+ finfo->conn_info.src = cinfo->conn_info.src;
+ finfo->conn_info.dest = cinfo->conn_info.dest;
+ finfo->conn_ex_info.efifo_ch = cinfo->conn_ex_info.efifo_ch;
+ finfo->conn_ex_info.ofifo_ch = cinfo->conn_ex_info.ofifo_ch;
+ finfo->bit_width.efifo = cinfo->bit_width.efifo;
+ finfo->bit_width.ofifo = cinfo->bit_width.ofifo;
+ finfo->format.fs = cinfo->format.fs;
+ finfo->format.etobuf = cinfo->format.etobuf;
+
+ if (!data || !data_size)
+ return 0;
+
+ top = 0;
+ while (top < data_size) {
+ if (top + CHUNK_SIZE > data_size)
+ return -EINVAL;
+
+ tag = htonl(*(u32 *) (data + top));
+ size = htonl(*(u32 *) (data + top + 4));
+ if (top + CHUNK_SIZE + size > data_size)
+ return -EINVAL;
+
+ top += CHUNK_SIZE;
+ switch (tag) {
+ case AEC_CDSP_TAG_PROG:
+ if (size < PROG_FIX_SIZE)
+ return -EINVAL;
+
+ tmp = htonl(*(u32 *) (data + top));
+ if (!tmp)
+ return 0;
+ if (tmp + PROG_FIX_SIZE > size)
+ return -EINVAL;
+ if (finfo->prog_data)
+ return -EINVAL;
+
+ finfo->prog_data = &data[top + PROG_FIX_SIZE];
+ finfo->prog_size = tmp;
+ break;
+ case AEC_CDSP_TAG_PRM:
+ if (size < PRM_FIX_SIZE)
+ return -EINVAL;
+
+ tmp = htonl(*(u32 *) (data + top));
+ if (!tmp)
+ return 0;
+ if (tmp % PRM_UNIT_SIZE)
+ return -EINVAL;
+ if (tmp + PRM_FIX_SIZE > size)
+ return -EINVAL;
+ if (finfo->param_data)
+ return -EINVAL;
+
+ finfo->param_data = &data[top + PRM_FIX_SIZE];
+ finfo->param_num = tmp / PRM_UNIT_SIZE;
+ break;
+ case AEC_CDSP_TAG_FIFO:
+ if (size < FIFO_FIX_SIZE)
+ return -EINVAL;
+ if (finfo->fifo_data)
+ return -EINVAL;
+
+ finfo->fifo_data = &data[top];
+ break;
+ case AEC_CDSP_TAG_EXT:
+ if (size < EXT_FIX_SIZE)
+ return -EINVAL;
+
+ if (finfo->ext)
+ return -EINVAL;
+
+ finfo->ext = &data[top];
+ break;
+ default:
+ break;
+ }
+
+ top += size;
+ }
+
+ /* FIFO Check */
+ if (finfo->fifo_data) {
+ ret = cdsp_fifo_check(id, cdsp_info);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* Program Check */
+ if (finfo->prog_size && finfo->prog_data) {
+ coder.firmware = finfo->prog_data;
+ coder.size = finfo->prog_size;
+
+ ret = cdsp_program_check(id, &coder);
+ if (ret < 0)
+ return ret;
+
+ cinfo->prog_info.inout_type =
+ MAKE_HALFWORD(coder.firmware[PRG_DESC_OUTPUT_TYPE],
+ coder.firmware[PRG_DESC_OUTPUT_TYPE + 1]);
+ }
+
+ return cdsp_path_check(id, cinfo->prog_info.inout_type,
+ &finfo->conn_info);
+}
+
+static int cdsp_data_analyze(struct aec_cdsp_info *cdsp_info)
+{
+ struct aec_cdsp_func_info *finfo_a;
+ struct aec_cdsp_func_info *finfo_b;
+ struct coder_firmware coder_a;
+ struct coder_firmware coder_b;
+ int ret;
+
+ finfo_a = &cdsp_info->func_info[AEC_FUNC_INFO_A];
+ finfo_b = &cdsp_info->func_info[AEC_FUNC_INFO_B];
+ cdsp_info->dfifo_cb_pos = mc_fifo_info.dfifo_cb_pos;
+ cdsp_info->rfifo_cb_pos = mc_fifo_info.rfifo_cb_pos;
+ cdsp_info->ofifo_buf_sample = mc_fifo_info.ofifo_buf_sample;
+ cdsp_info->rfifo_buf_sample = mc_fifo_info.rfifo_buf_sample;
+ cdsp_info->out0_sel = mc_fifo_info.out0_sel;
+ cdsp_info->out1_sel = mc_fifo_info.out1_sel;
+ cdsp_info->out2_sel = mc_fifo_info.out2_sel;
+ cdsp_info->rdfifo_bit_sel = mc_fifo_info.rdfifo_bit_sel;
+ cdsp_info->efifo01_sel = mc_fifo_info.efifo01_sel;
+ cdsp_info->efifo23_sel = mc_fifo_info.efifo23_sel;
+
+ ret = cdsp_data_analyze_coder(CODER_DEC, cdsp_info);
+ if (ret < 0)
+ return ret;
+
+ ret = cdsp_data_analyze_coder(CODER_ENC, cdsp_info);
+ if (ret < 0)
+ return ret;
+
+ if (finfo_a->fifo_data && finfo_b->fifo_data) {
+ ret = cdsp_inout_path_check(&finfo_a->conn_info,
+ &finfo_b->conn_info);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (finfo_a->prog_size && finfo_a->prog_data &&
+ finfo_b->prog_size && finfo_b->prog_data) {
+ coder_a.firmware = finfo_a->prog_data;
+ coder_a.size = finfo_a->prog_size;
+ coder_b.firmware = finfo_b->prog_data;
+ coder_b.size = finfo_b->prog_size;
+ ret = cdsp_aec_program_check(&coder_a, &coder_b);
+ }
+
+ return ret;
+}
+
+static inline void cdsp_output_format_notify_complete(enum mc_cdsp_id id)
+{
+ struct coder_info *another_info;
+ struct coder_params coder;
+
+ another_info = cdsp_coder_info_get(cdsp_another_id_get(id));
+
+ /* Complete NotifyOutFormat */
+ if (another_info->format_propagate) {
+ coder.command = CDSP_CMD_OS2HOST_CMN_NOTIFY_OUT_FORMAT;
+ coder.params[CDSP_CMD_PARAM_RESULT_00] = 0;
+ coder.params[CDSP_CMD_PARAM_RESULT_01] = 0;
+ coder.params[CDSP_CMD_PARAM_RESULT_02] = 0;
+ coder.params[CDSP_CMD_PARAM_RESULT_03] = 0;
+ cdsp_command_write_complete(id, &coder);
+
+ another_info->format_propagate = false;
+ }
+}
+
+static void cdsp_coder_close(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+ struct coder_params coder;
+ u32 int_reg;
+ u8 ctl, int_data, ctl_data;
+ int ret;
+
+ info = cdsp_coder_info_get(id);
+
+ cdsp_output_format_notify_complete(id);
+
+ /* Reset command */
+ coder.command = CDSP_CMD_HOST2OS_CMN_RESET;
+ ret = cdsp_command_write_host2os(id, &coder);
+
+ /* Command register Initialize */
+ cdsp_command_init(id);
+
+ /* DEC/ENC SFR,EVT Disable */
+ if (id == CDSP_DECODER) {
+ int_reg = MCI_DEC_ENABLE;
+ ctl = MCB_EDEC;
+ } else {
+ int_reg = MCI_ENC_ENABLE;
+ ctl = MCB_EENC;
+ }
+
+ mc_read_c(int_reg, &int_data, 1);
+
+ int_data &= ~(MCB_EDEC_EVT | MCB_EDEC_SFR);
+
+ mc_read_digital(MCI_ECDSP, &ctl_data, 1);
+ ctl_data &= ~ctl;
+ mc_packet_add_force_write_if(MCI_ECDSP, ctl_data);
+
+ mc_packet_add_force_write_c(int_reg, int_data);
+
+ mc_packet_execute();
+
+ info->format.fs = CODER_FMT_FS_48000;
+
+}
+
+static void cdsp_program_terminate(enum mc_cdsp_id id)
+{
+ struct coder_params coder;
+ struct coder_info *info;
+
+ coder.command = CDSP_CMD_HOST2OS_SYS_TERMINATE;
+ cdsp_command_write_host2os(id, &coder);
+
+ info = cdsp_coder_info_get(id);
+ info->prog_info.vendor_id = 0;
+ info->prog_info.function_id = 0;
+}
+
+static int cdsp_program_write(struct fsq_data_info *fsq)
+{
+ u8 data;
+ u16 load_addr, remain;
+ u32 current, writes, i;
+ int ret = 0;
+
+ load_addr = fsq->load_addr;
+ current = 0;
+ remain = fsq->size;
+
+ /* CDSP_MSEL Set */
+ mc_read_c(MCI_CDSP_RESET, &data, 1);
+
+ if (fsq->scramble == PRG_PRM_SCRMBL_DISABLE)
+ data |= MCB_CDSP_FMODE;
+ else
+ data &= ~MCB_CDSP_FMODE;
+
+ data &= ~MCB_CDSP_MSEL;
+
+ if (fsq->msel == MSEL_PROG)
+ data |= MCB_CDSP_MSEL_PROG;
+ else
+ data |= MCB_CDSP_MSEL_DATA;
+
+ mc_packet_add_force_write_c(MCI_CDSP_RESET, data);
+
+ mc_packet_execute();
+
+ while (remain > 0 && !ret) {
+ /* CDSP_MAR Set */
+ mc_packet_add_force_write_c(MCI_CDSP_MAR_H,
+ HIGH_BYTE(load_addr));
+ mc_packet_add_force_write_c(MCI_CDSP_MAR_L,
+ LOW_BYTE(load_addr));
+
+ mc_packet_execute();
+
+ /* fill FFIFO */
+ writes = FIFOSIZE_FFIFO / sizeof(u16);
+ if (writes > remain)
+ writes = remain;
+
+ for (i = 0; i < writes * 2; ++i)
+ mc_packet_add_force_write_if(MCI_FSQ_FFIFO,
+ fsq->data[current * 2 +
+ i]);
+
+ mc_packet_execute();
+
+ load_addr += writes;
+ current += writes;
+ remain -= writes;
+
+ /* FFIFO_FLG Clear */
+ mc_packet_add_force_write_if(MCI_CDSP, MCB_IRQFLAG_FFIFO);
+
+ /* FSQ_END_FLG Clear */
+ mc_packet_add_force_write_c(MCI_FFIFO_FLG,
+ MCB_FFIFO_FLG_FSQ_END);
+
+ mc_packet_execute();
+
+ /* FSQ_START Set */
+ mc_read_c(MCI_DEC_START, &data, 1);
+ data |= MCB_DEC_FSQ_START;
+ mc_packet_add_force_write_c(MCI_DEC_START, data);
+
+ mc_packet_execute();
+
+ /* FSQ_END_FLG Polling */
+ mc_packet_add_wait_event(MCDRV_EVT_C_REG_FLAG_SET |
+ (MCI_FFIFO_FLG << 8) |
+ MCB_FFIFO_FLG_FSQ_END);
+
+ ret = mc_packet_execute();
+ if (ret < 0)
+ return ret;
+
+ /* FSQ_START Clear */
+ mc_read_c(MCI_DEC_START, &data, 1);
+ data &= ~MCB_DEC_FSQ_START;
+ mc_packet_add_force_write_c(MCI_DEC_START, data);
+
+ mc_packet_execute();
+ }
+
+ /* FFIFO_FLG Clear */
+ mc_packet_add_force_write_if(MCI_CDSP, MCB_IRQFLAG_FFIFO);
+
+ /* FSQ_END_FLG Clear */
+ mc_packet_add_force_write_c(MCI_FFIFO_FLG, MCB_FFIFO_FLG_FSQ_END);
+
+ mc_packet_execute();
+
+ return ret;
+}
+
+static inline int cdsp_program_download(u8 *firmware)
+{
+ struct fsq_data_info fsq[2];
+ u8 data;
+ int ret;
+
+ /* CDSP_SAVEOFF Set */
+ mc_packet_add_force_write_c(MCI_PWM_DIGITAL_CDSP, MCB_PWM_CDSP_SAVEOFF);
+
+ mc_packet_execute();
+
+ /* CDSP_HALT_MODE Check */
+ mc_packet_add_wait_event(MCDRV_EVT_C_REG_FLAG_RESET |
+ (MCI_CDSP_POWER_MODE << 8) |
+ MCB_CDSP_HLT_MODE_SLEEP_HALT);
+
+ ret = mc_packet_execute();
+ if (ret < 0) {
+ mc_packet_add_force_write_c(MCI_PWM_DIGITAL_CDSP, 0);
+
+ mc_packet_execute();
+
+ return ret;
+ }
+
+ /* FSQ_SRST */
+ mc_read_c(MCI_CDSP_RESET, &data, 1);
+ data |= MCB_CDSP_FSQ_SRST;
+ mc_packet_add_force_write_c(MCI_CDSP_RESET, data);
+ data &= ~MCB_CDSP_FSQ_SRST;
+ mc_packet_add_force_write_c(MCI_CDSP_RESET, data);
+
+ /* 150ns wait */
+ mc_packet_add_wait(1);
+
+ mc_packet_execute();
+
+ /* FFIFO_RST */
+ mc_read_c(MCI_DEC_FIFO_RST, &data, 1);
+ data |= MCB_DEC_FFIFO_RST;
+ mc_packet_add_force_write_c(MCI_DEC_FIFO_RST, data);
+ data &= ~MCB_DEC_FFIFO_RST;
+ mc_packet_add_force_write_c(MCI_DEC_FIFO_RST, data);
+
+ mc_packet_execute();
+
+ /* Transfer Program & Data */
+ fsq[0].data = &firmware[PRG_DESC_PROGRAM];
+ fsq[0].size = MAKE_HALFWORD(firmware[PRG_DESC_PRG_SIZE],
+ firmware[PRG_DESC_PRG_SIZE + 1]);
+ fsq[0].load_addr = MAKE_HALFWORD(firmware[PRG_DESC_PRG_LOAD_ADR],
+ firmware[PRG_DESC_PRG_LOAD_ADR + 1]);
+ fsq[0].scramble = MAKE_HALFWORD(firmware[PRG_DESC_PRG_SCRAMBLE],
+ firmware[PRG_DESC_PRG_SCRAMBLE + 1]);
+ fsq[0].msel = MSEL_PROG;
+
+ fsq[1].data = &fsq[0].data[(u32) fsq[0].size * 2];
+ fsq[1].size = MAKE_HALFWORD(firmware[PRG_DESC_DATA_SIZE],
+ firmware[PRG_DESC_DATA_SIZE + 1]);
+ fsq[1].load_addr = MAKE_HALFWORD(firmware[PRG_DESC_DATA_LOAD_ADR],
+ firmware[PRG_DESC_DATA_LOAD_ADR + 1]);
+ fsq[1].scramble = MAKE_HALFWORD(firmware[PRG_DESC_DATA_SCRAMBLE],
+ firmware[PRG_DESC_DATA_SCRAMBLE + 1]);
+ fsq[1].msel = MSEL_DATA;
+
+ ret = cdsp_program_write(&fsq[0]);
+ if (!ret)
+ ret = cdsp_program_write(&fsq[1]);
+
+ /* CDSP_SAVEOFF Clear */
+ mc_packet_add_force_write_c(MCI_PWM_DIGITAL_CDSP, 0);
+
+ mc_packet_execute();
+
+ return ret;
+}
+
+static inline int cdsp_program_init(enum mc_cdsp_id id,
+ struct coder_firmware *coderf)
+{
+ struct coder_info *info;
+ struct coder_params coderp;
+ u16 data_loadaddr;
+ u16 work_begin;
+ u16 data_addr;
+ u16 data_size;
+ u8 *firmware;
+ int ret;
+
+ firmware = coderf->firmware;
+ data_loadaddr = MAKE_HALFWORD(firmware[PRG_DESC_DATA_LOAD_ADR],
+ firmware[PRG_DESC_DATA_LOAD_ADR + 1]);
+ work_begin = MAKE_HALFWORD(firmware[PRG_DESC_WORK_BEGIN_ADR],
+ firmware[PRG_DESC_WORK_BEGIN_ADR + 1]);
+ if (data_loadaddr < work_begin)
+ data_addr = data_loadaddr;
+ else
+ data_addr = work_begin;
+ data_size = MAKE_HALFWORD(firmware[PRG_DESC_DATA_SIZE],
+ firmware[PRG_DESC_DATA_SIZE + 1]);
+ data_size = data_size + MAKE_HALFWORD(firmware[PRG_DESC_WORK_SIZE],
+ firmware[PRG_DESC_WORK_SIZE + 1]);
+
+ /* SetProgramInfo command */
+ coderp.command = CDSP_CMD_HOST2OS_SYS_SET_PRG_INFO;
+ coderp.params[CDSP_CMD_PARAM_ARGUMENT_00] = LOW_BYTE(data_addr);
+ coderp.params[CDSP_CMD_PARAM_ARGUMENT_01] = HIGH_BYTE(data_addr);
+ coderp.params[CDSP_CMD_PARAM_ARGUMENT_02] = LOW_BYTE(data_size);
+ coderp.params[CDSP_CMD_PARAM_ARGUMENT_03] = HIGH_BYTE(data_size);
+ coderp.params[CDSP_CMD_PARAM_ARGUMENT_04] =
+ firmware[PRG_DESC_ENTRY_ADR];
+ coderp.params[CDSP_CMD_PARAM_ARGUMENT_05] =
+ firmware[PRG_DESC_ENTRY_ADR + 1];
+ coderp.params[CDSP_CMD_PARAM_ARGUMENT_06] =
+ firmware[PRG_DESC_STACK_BEGIN_ADR];
+ coderp.params[CDSP_CMD_PARAM_ARGUMENT_07] =
+ firmware[PRG_DESC_STACK_BEGIN_ADR + 1];
+ coderp.params[CDSP_CMD_PARAM_ARGUMENT_08] =
+ firmware[PRG_DESC_STACK_SIZE];
+ coderp.params[CDSP_CMD_PARAM_ARGUMENT_09] =
+ firmware[PRG_DESC_STACK_SIZE + 1];
+ coderp.params[CDSP_CMD_PARAM_ARGUMENT_10] =
+ firmware[PRG_DESC_RESOURCE_FLAG];
+ ret = cdsp_command_write_host2os(id, &coderp);
+ if (ret < 0)
+ return ret;
+
+ /* Reset command */
+ coderp.command = CDSP_CMD_HOST2OS_CMN_RESET;
+ ret = cdsp_command_write_host2os(id, &coderp);
+ if (ret < 0)
+ return ret;
+
+ /* GetProgramVersion command */
+ coderp.command = CDSP_CMD_HOST2OS_CMN_GET_PRG_VER;
+ ret = cdsp_command_write_host2os(id, &coderp);
+ if (ret < 0)
+ return ret;
+
+ info = cdsp_coder_info_get(id);
+ info->program.version_h =
+ MAKE_HALFWORD(coderp.params[CDSP_CMD_PARAM_RESULT_00],
+ coderp.params[CDSP_CMD_PARAM_RESULT_01]);
+ info->program.version_l =
+ MAKE_HALFWORD(coderp.params[CDSP_CMD_PARAM_RESULT_02],
+ coderp.params[CDSP_CMD_PARAM_RESULT_03]);
+
+ info->prog_info.vendor_id = MAKE_HALFWORD(firmware[PRG_DESC_VENDER_ID],
+ firmware[PRG_DESC_VENDER_ID +
+ 1]);
+ info->prog_info.function_id =
+ MAKE_HALFWORD(firmware[PRG_DESC_FUNCTION_ID],
+ firmware[PRG_DESC_FUNCTION_ID + 1]);
+ info->prog_info.prog_type =
+ MAKE_HALFWORD(firmware[PRG_DESC_PRG_TYPE],
+ firmware[PRG_DESC_PRG_TYPE + 1]);
+ info->prog_info.inout_type =
+ MAKE_HALFWORD(firmware[PRG_DESC_OUTPUT_TYPE],
+ firmware[PRG_DESC_OUTPUT_TYPE + 1]);
+ info->prog_info.prog_scramble =
+ MAKE_HALFWORD(firmware[PRG_DESC_PRG_SCRAMBLE],
+ firmware[PRG_DESC_PRG_SCRAMBLE + 1]);
+ info->prog_info.data_scramble =
+ MAKE_HALFWORD(firmware[PRG_DESC_DATA_SCRAMBLE],
+ firmware[PRG_DESC_DATA_SCRAMBLE + 1]);
+ info->prog_info.entry_addr =
+ MAKE_HALFWORD(firmware[PRG_DESC_ENTRY_ADR],
+ firmware[PRG_DESC_ENTRY_ADR + 1]);
+ info->prog_info.prog_loadaddr =
+ MAKE_HALFWORD(firmware[PRG_DESC_PRG_LOAD_ADR],
+ firmware[PRG_DESC_PRG_LOAD_ADR + 1]);
+ info->prog_info.prog_size =
+ MAKE_HALFWORD(firmware[PRG_DESC_PRG_SIZE],
+ firmware[PRG_DESC_PRG_SIZE + 1]);
+ info->prog_info.data_loadaddr =
+ MAKE_HALFWORD(firmware[PRG_DESC_DATA_LOAD_ADR],
+ firmware[PRG_DESC_DATA_LOAD_ADR + 1]);
+ info->prog_info.data_size =
+ MAKE_HALFWORD(firmware[PRG_DESC_DATA_SIZE],
+ firmware[PRG_DESC_DATA_SIZE + 1]);
+ info->prog_info.work_begin =
+ MAKE_HALFWORD(firmware[PRG_DESC_WORK_BEGIN_ADR],
+ firmware[PRG_DESC_WORK_BEGIN_ADR + 1]);
+ info->prog_info.work_size =
+ MAKE_HALFWORD(firmware[PRG_DESC_WORK_SIZE],
+ firmware[PRG_DESC_WORK_SIZE + 1]);
+ info->prog_info.stack_begin =
+ MAKE_HALFWORD(firmware[PRG_DESC_STACK_BEGIN_ADR],
+ firmware[PRG_DESC_STACK_BEGIN_ADR + 1]);
+ info->prog_info.stack_size =
+ MAKE_HALFWORD(firmware[PRG_DESC_STACK_SIZE],
+ firmware[PRG_DESC_STACK_SIZE + 1]);
+ info->prog_info.output_start_mode =
+ MAKE_HALFWORD(firmware[PRG_DESC_OUTSTARTMODE],
+ firmware[PRG_DESC_OUTSTARTMODE + 1]);
+ info->prog_info.resource_flag =
+ MAKE_HALFWORD(firmware[PRG_DESC_RESOURCE_FLAG],
+ firmware[PRG_DESC_RESOURCE_FLAG + 1]);
+ info->prog_info.max_load =
+ MAKE_HALFWORD(firmware[PRG_DESC_MAX_LOAD],
+ firmware[PRG_DESC_MAX_LOAD + 1]);
+
+ return 0;
+}
+
+static void cdsp_fifo_reset(enum mc_cdsp_id id, u32 fifo)
+{
+ u32 fifo_id;
+ u8 data;
+
+ fifo_id = cdsp_fifoid_get_from_coderid(id);
+ mc_read_c(MCI_DEC_FIFO_RST, &data, 1);
+
+ if ((fifo & FIFO_DFIFO_MASK) && (fifo_id & FIFO_DFIFO_MASK)) {
+ /* DFIFO Reset */
+ data |= MCB_DEC_DFIFO_RST;
+ mc_packet_add_force_write_c(MCI_DEC_FIFO_RST, data);
+ data &= ~MCB_DEC_DFIFO_RST;
+ mc_packet_add_force_write_c(MCI_DEC_FIFO_RST, data);
+
+ mc_fifo_info.dfifo_write_size = 0;
+ }
+
+ if ((fifo & FIFO_EFIFO_MASK) && (fifo_id & FIFO_EFIFO_MASK)) {
+ /* EFIFO Reset */
+ data |= MCB_DEC_EFIFO_RST;
+ mc_packet_add_force_write_c(MCI_DEC_FIFO_RST, data);
+ data &= ~MCB_DEC_EFIFO_RST;
+ mc_packet_add_force_write_c(MCI_DEC_FIFO_RST, data);
+ }
+
+ if ((fifo & FIFO_OFIFO_MASK) && (fifo_id & FIFO_OFIFO_MASK)) {
+ /* OFIFO Reset */
+ data |= MCB_DEC_OFIFO_RST;
+ mc_packet_add_force_write_c(MCI_DEC_FIFO_RST, data);
+ data &= ~MCB_DEC_OFIFO_RST;
+ mc_packet_add_force_write_c(MCI_DEC_FIFO_RST, data);
+ }
+
+ if ((fifo & FIFO_RFIFO_MASK) && (fifo_id & FIFO_RFIFO_MASK)) {
+ /* RFIFO Reset */
+ data |= MCB_DEC_RFIFO_RST;
+ mc_packet_add_force_write_c(MCI_DEC_FIFO_RST, data);
+ data &= ~MCB_DEC_RFIFO_RST;
+ mc_packet_add_force_write_c(MCI_DEC_FIFO_RST, data);
+ }
+
+ mc_packet_execute();
+}
+
+static void cdsp_fifo_init(enum mc_cdsp_id id, u32 fifo)
+{
+ u32 fifo_id;
+
+ fifo_id = cdsp_fifoid_get_from_coderid(id);
+
+ if ((fifo & FIFO_DFIFO_MASK) && (fifo_id & FIFO_DFIFO_MASK)) {
+ mc_fifo_info.dfifo_cb_pos = CBPOS_DFIFO_DEF;
+ mc_fifo_info.dfifo_write_size = 0;
+ }
+
+ if ((fifo & FIFO_OFIFO_MASK) && (fifo_id & FIFO_OFIFO_MASK))
+ mc_fifo_info.ofifo_buf_sample = OFIFO_BUF_SAMPLE_DEF;
+
+ if ((fifo & FIFO_RFIFO_MASK) && (fifo_id & FIFO_RFIFO_MASK)) {
+ mc_fifo_info.rfifo_cb_pos = CBPOS_RFIFO_DEF;
+ mc_fifo_info.rfifo_buf_sample = RFIFO_BUF_SAMPLE_DEF;
+ }
+
+ cdsp_fifo_reset(id, fifo);
+}
+
+static u8 cdsp_fifo_set_ch(u32 fifo, u8 ch)
+{
+ u8 data, old_ch = 0;
+
+ mc_read_c(MCI_DEC_FIFO_CH, &data, 1);
+
+ if (fifo & FIFO_EFIFO_MASK) {
+ old_ch |= data & MCB_DEC_EFIFO_CH;
+ data &= ~MCB_DEC_EFIFO_CH;
+ data |= ch & MCB_DEC_EFIFO_CH;
+ }
+
+ if (fifo & FIFO_OFIFO_MASK) {
+ old_ch |= data & MCB_DEC_OFIFO_CH;
+ data &= ~MCB_DEC_OFIFO_CH;
+ data |= ch & MCB_DEC_OFIFO_CH;
+ }
+
+ mc_packet_add_write_c(MCI_DEC_FIFO_CH, data);
+
+ mc_packet_execute();
+
+ return old_ch;
+}
+
+static u8 cdsp_fifo_get_ch_bit(u32 fifo,
+ struct connection_ex_info *conn_ex_info,
+ struct bit_width_info *bit_width)
+{
+ u8 data = 0;
+
+ if (fifo & FIFO_EFIFO_MASK) {
+ if (conn_ex_info->efifo_ch == 4) {
+ if (bit_width->efifo == 32)
+ data |= MCB_DEC_EFIFO_CH_4_32;
+ else
+ data |= MCB_DEC_EFIFO_CH_4_16;
+ } else {
+ if (bit_width->efifo == 32)
+ data |= MCB_DEC_EFIFO_CH_2_32;
+ else
+ data |= MCB_DEC_EFIFO_CH_2_16;
+ }
+ }
+
+ if (fifo & FIFO_OFIFO_MASK) {
+ if (conn_ex_info->ofifo_ch == 4) {
+ if (bit_width->ofifo == 32)
+ data |= MCB_DEC_OFIFO_CH_4_32;
+ else
+ data |= MCB_DEC_OFIFO_CH_4_16;
+ } else {
+ if (bit_width->ofifo == 32)
+ data |= MCB_DEC_OFIFO_CH_2_32;
+ else
+ data |= MCB_DEC_OFIFO_CH_2_16;
+ }
+ }
+
+ return data;
+}
+
+static inline u8 cdsp_fifo_reset_ch(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+ u32 fifo_id;
+ u8 data;
+
+ info = cdsp_coder_info_get(id);
+
+ fifo_id = cdsp_fifoid_get_from_coderid(id);
+ data =
+ cdsp_fifo_get_ch_bit(fifo_id, &info->conn_ex_info,
+ &info->bit_width);
+
+ data = cdsp_fifo_set_ch(fifo_id, data);
+
+ return data;
+}
+
+static int cdsp_connection_reset(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+ struct coder_params coder;
+ int ret;
+
+ info = cdsp_coder_info_get(id);
+
+ coder.command = CDSP_CMD_HOST2OS_SYS_SET_CONNECTION;
+ coder.params[CDSP_CMD_PARAM_ARGUMENT_00] = info->conn_info.src;
+ coder.params[CDSP_CMD_PARAM_ARGUMENT_01] = info->conn_info.dest;
+ ret = cdsp_command_write_host2os(id, &coder);
+ if (ret < 0)
+ return ret;
+
+ cdsp_fifo_reset_ch(id);
+
+ return ret;
+}
+
+static int cdsp_coder_open(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+ struct coder_params coder;
+ u8 data;
+ int ret;
+
+ info = cdsp_coder_info_get(id);
+
+ /* Command register Initialize */
+ cdsp_command_init(id);
+
+ /* TimerReset command (Off) */
+ coder.command = CDSP_CMD_HOST2OS_SYS_TIMER_RESET;
+ coder.params[CDSP_CMD_PARAM_ARGUMENT_00] = TIMERRESET_OFF;
+ ret = cdsp_command_write_host2os(id, &coder);
+ if (ret < 0)
+ return ret;
+
+ /* DEC/ENC SFR,EVT Interrupt flag clear */
+ if (id == CDSP_DECODER) {
+ mc_read_c(MCI_DEC_FLG, &data, 1);
+ data |= MCB_ENC_FLG_SFR | MCB_DEC_EVT_FLG;
+ mc_packet_add_force_write_c(MCI_DEC_FLG, data);
+ } else {
+ mc_read_c(MCI_ENC_FLG, &data, 1);
+ data |= MCB_ENC_FLG_SFR | MCB_ENC_EVT_FLG;
+ mc_packet_add_force_write_c(MCI_ENC_FLG, data);
+ }
+
+ mc_packet_execute();
+
+ mc_read_digital(MCI_CDSP, &data, 1);
+ if (id == CDSP_DECODER)
+ data |= MCB_IRQFLAG_DEC;
+ else
+ data |= MCB_IRQFLAG_ENC;
+ mc_packet_add_force_write_if(MCI_CDSP, data);
+
+ mc_packet_execute();
+
+ /* DEC/ENC SFR,EVT Interrupt Enable */
+ if (id == CDSP_DECODER) {
+ mc_read_c(MCI_DEC_ENABLE, &data, 1);
+ data |= MCB_EDEC_SFR | MCB_EDEC_EVT;
+ mc_packet_add_force_write_c(MCI_DEC_ENABLE, data);
+ } else {
+ mc_read_c(MCI_ENC_ENABLE, &data, 1);
+ data |= MCB_EENC_SFR | MCB_EENC_EVT;
+ mc_packet_add_force_write_c(MCI_ENC_ENABLE, data);
+ }
+
+ mc_packet_execute();
+
+ mc_read_digital(MCI_ECDSP, &data, 1);
+ if (id == CDSP_DECODER)
+ data |= MCB_EDEC;
+ else
+ data |= MCB_EENC;
+ mc_packet_add_force_write_if(MCI_ECDSP, data);
+
+ mc_packet_execute();
+
+ /* Initialize */
+ memset(info, 0, sizeof(struct coder_info));
+ info->format.fs = CODER_FMT_FS_48000;
+ info->format.etobuf = CODER_FMT_ETOBUF_LRMIX;
+ info->conn_info.src = CDSP_IN_SOURCE_NONE;
+ info->conn_info.dest = CDSP_OUT_DEST_NONE;
+ info->conn_ex_info.efifo_ch = 2;
+ info->conn_ex_info.ofifo_ch = 2;
+ info->bit_width.efifo = 16;
+ info->bit_width.ofifo = 16;
+
+ cdsp_fifo_init(id, FIFO_DFIFO | FIFO_EFIFO | FIFO_OFIFO | FIFO_RFIFO);
+
+ return cdsp_connection_reset(id);
+}
+
+static int cdsp_coder_reset(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+ struct coder_params coder;
+ int ret;
+
+ info = cdsp_coder_info_get(id);
+
+ /* Reset command */
+ coder.command = CDSP_CMD_HOST2OS_CMN_RESET;
+ ret = cdsp_command_write_host2os(id, &coder);
+ if (ret < 0)
+ return ret;
+
+ cdsp_output_format_notify_complete(id);
+
+ /* Command register Initialize */
+ cdsp_command_init(id);
+
+ /* Input data end flag - release */
+ info->preinput_dataend_set = false;
+ info->input_dataend_set = false;
+
+ info->format.fs = CODER_FMT_FS_48000;
+ info->format.etobuf = CODER_FMT_ETOBUF_LRMIX;
+
+ return 0;
+}
+
+static void cdsp_input_position_clear(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+
+ info = cdsp_coder_info_get(id);
+
+ if (info->conn_info.src != CDSP_IN_SOURCE_EFIFO &&
+ info->conn_info.src != CDSP_IN_SOURCE_DFIFO_EFIFO)
+ return;
+
+ /* ENC_POS Write (Suitable value) */
+ mc_packet_add_force_write_c(MCI_ENC_POS4, 0);
+
+ mc_packet_execute();
+
+ info->input_pos = 0;
+}
+
+static void cdsp_input_position_reset(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+ struct coder_params coder;
+
+ info = cdsp_coder_info_get(id);
+
+ if (info->conn_info.src != CDSP_IN_SOURCE_OTHER_OUTBUF)
+ return;
+
+ coder.command = CDSP_CMD_HOST2OS_SYS_RESET_INPUT_POS;
+ cdsp_command_write_host2os(id, &coder);
+
+ info->input_pos = 0;
+}
+
+static void cdsp_output_position_clear(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+
+ info = cdsp_coder_info_get(id);
+
+ if (info->conn_info.dest != CDSP_OUT_DEST_OFIFO &&
+ info->conn_info.dest != CDSP_OUT_DEST_OFIFO_RFIFO)
+ return;
+
+ /* DEC_POS Write (Suitable value) */
+ mc_packet_add_force_write_c(MCI_DEC_POS4, 0);
+
+ mc_packet_execute();
+}
+
+static int cdsp_coder_clear(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+ struct coder_params coder;
+ int ret;
+
+ info = cdsp_coder_info_get(id);
+
+ /* State check */
+ if (info->state != STATE_READY_SETUP && info->state != STATE_READY)
+ return -EBUSY;
+
+ /* Clear command */
+ coder.command = CDSP_CMD_HOST2OS_CMN_CLEAR;
+ ret = cdsp_command_write_host2os(id, &coder);
+ if (ret < 0)
+ return ret;
+
+ cdsp_output_format_notify_complete(id);
+
+ /* TimerReset command (Reset) */
+ coder.command = CDSP_CMD_HOST2OS_SYS_TIMER_RESET;
+ coder.params[CDSP_CMD_PARAM_ARGUMENT_00] = TIMERRESET_RESET;
+ ret = cdsp_command_write_host2os(id, &coder);
+ if (ret < 0)
+ return ret;
+
+ /* ChangeOutSamplingRate - Not complete */
+ info->change_output_fs = false;
+
+ /* Input data end state - release */
+ info->preinput_dataend_set = false;
+ info->input_dataend_set = false;
+
+ /* Output Start - clear */
+ switch (info->conn_info.dest) {
+ case CDSP_OUT_DEST_OFIFO:
+ mc_fifo_info.ofifo_output_start = false;
+ break;
+ case CDSP_OUT_DEST_OFIFO_RFIFO:
+ mc_fifo_info.ofifo_output_start = false;
+ mc_fifo_info.rfifo_output_start = false;
+ break;
+ case CDSP_OUT_DEST_RFIFO:
+ mc_fifo_info.rfifo_output_start = false;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static inline int cdsp_format_set(enum mc_cdsp_id id,
+ struct coder_params *coder)
+{
+ struct coder_info *info;
+ struct coder_params tmp;
+ int ret;
+
+ info = cdsp_coder_info_get(id);
+
+ /* State check */
+ if (info->state != STATE_READY_SETUP)
+ return -EBUSY;
+
+ /* Argument check */
+ switch (coder->params[CDSP_CMD_PARAM_ARGUMENT_00]) {
+ case CODER_FMT_FS_48000:
+ case CODER_FMT_FS_44100:
+ case CODER_FMT_FS_32000:
+ case CODER_FMT_FS_24000:
+ case CODER_FMT_FS_22050:
+ case CODER_FMT_FS_16000:
+ case CODER_FMT_FS_12000:
+ case CODER_FMT_FS_11025:
+ case CODER_FMT_FS_8000:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (coder->params[CDSP_CMD_PARAM_ARGUMENT_01]) {
+ case CODER_FMT_ETOBUF_LRMIX:
+ case CODER_FMT_ETOBUF_LCH:
+ case CODER_FMT_ETOBUF_RCH:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ tmp.command = coder->command;
+ tmp.params[CDSP_CMD_PARAM_ARGUMENT_00] =
+ coder->params[CDSP_CMD_PARAM_ARGUMENT_00];
+ tmp.params[CDSP_CMD_PARAM_ARGUMENT_01] =
+ coder->params[CDSP_CMD_PARAM_ARGUMENT_01];
+ ret = cdsp_command_write_host2os(id, &tmp);
+ if (ret < 0)
+ return ret;
+
+ info->format.fs = tmp.params[CDSP_CMD_PARAM_ARGUMENT_00];
+ info->format.etobuf = tmp.params[CDSP_CMD_PARAM_ARGUMENT_01];
+
+ return 0;
+}
+
+static int cdsp_input_dataend_set(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+ u8 state, src;
+ int ret;
+
+ info = cdsp_coder_info_get(id);
+ state = info->state;
+
+ /* State check */
+ switch (state) {
+ case STATE_READY_SETUP:
+ case STATE_READY:
+ case STATE_PLAYING:
+ break;
+ default:
+ return -EBUSY;
+ }
+
+ /* Path check */
+ src = info->conn_info.src;
+ if (src != CDSP_IN_SOURCE_DFIFO && src != CDSP_IN_SOURCE_DFIFO_EFIFO)
+ return -EIO;
+
+ if (state == STATE_READY_SETUP) {
+ info->preinput_dataend_set = true;
+ return 0;
+ }
+
+ info->preinput_dataend_set = false;
+
+ /* FormatPropagate flag clear */
+ info->format_propagate = false;
+
+ /* InputDataEnd command */
+ ret = cdsp_command_inputdataend(id);
+ if (ret < 0)
+ return ret;
+
+ /* Input data end state - set */
+ info->input_dataend_set = true;
+
+ /* Output Start */
+ cdsp_output_start(info);
+
+ return 0;
+}
+
+static int cdsp_timer_set(enum mc_cdsp_id id, struct coder_params *coder)
+{
+ struct coder_info *info;
+ struct coder_params tmp;
+
+ info = cdsp_coder_info_get(id);
+
+ /* State check */
+ if (info->state != STATE_READY_SETUP && info->state != STATE_READY)
+ return -EBUSY;
+
+ /* SetTimer command */
+ tmp.command = coder->command;
+ tmp.params[CDSP_CMD_PARAM_ARGUMENT_00] =
+ coder->params[CDSP_CMD_PARAM_ARGUMENT_00];
+ tmp.params[CDSP_CMD_PARAM_ARGUMENT_01] =
+ coder->params[CDSP_CMD_PARAM_ARGUMENT_01];
+ tmp.params[CDSP_CMD_PARAM_ARGUMENT_02] =
+ coder->params[CDSP_CMD_PARAM_ARGUMENT_02];
+ tmp.params[CDSP_CMD_PARAM_ARGUMENT_03] =
+ coder->params[CDSP_CMD_PARAM_ARGUMENT_03];
+ return cdsp_command_write_host2os(id, &tmp);
+}
+
+static inline int cdsp_output_set_dualmono(enum mc_cdsp_id id,
+ struct coder_params *coder)
+{
+ struct coder_info *info;
+ struct coder_params tmp;
+
+ info = cdsp_coder_info_get(id);
+
+ /* State check */
+ switch (info->state) {
+ case STATE_READY_SETUP:
+ case STATE_READY:
+ case STATE_PLAYING:
+ break;
+ default:
+ return -EBUSY;
+ }
+
+ /* Argument check */
+ switch (coder->params[CDSP_CMD_PARAM_ARGUMENT_00]) {
+ case CODER_DUALMONO_LR:
+ case CODER_DUALMONO_L:
+ case CODER_DUALMONO_R:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Path check */
+ switch (info->conn_info.dest) {
+ case CDSP_OUT_DEST_OFIFO:
+ case CDSP_OUT_DEST_OFIFO_RFIFO:
+ break;
+ default:
+ return -EIO;
+ }
+
+ /* SetDualMono command */
+ tmp.command = coder->command;
+ tmp.params[CDSP_CMD_PARAM_ARGUMENT_00]
+ = coder->params[CDSP_CMD_PARAM_ARGUMENT_00];
+ return cdsp_command_write_host2os(id, &tmp);
+}
+
+static int cdsp_input_get_position_sample(enum mc_cdsp_id id,
+ struct coder_params *coder)
+{
+ struct coder_info *info;
+ struct coder_params tmp;
+ u32 pos;
+ int ret;
+
+ info = cdsp_coder_info_get(id);
+
+ /* State check */
+ switch (info->state) {
+ case STATE_READY_SETUP:
+ case STATE_READY:
+ case STATE_PLAYING:
+ break;
+ default:
+ return -EBUSY;
+ }
+
+ /* Path check */
+ if (info->conn_info.src != CDSP_IN_SOURCE_OTHER_OUTBUF)
+ return -EIO;
+
+ /* pcm input ? */
+ if ((info->prog_info.inout_type & PRG_PRM_IOTYPE_IN_MASK) !=
+ PRG_PRM_IOTYPE_IN_PCM)
+ return -EIO;
+
+ /* GetInputPos command */
+ tmp.command = coder->command;
+ ret = cdsp_command_write_host2os(id, &tmp);
+ if (ret < 0)
+ return ret;
+
+ /* InputPos */
+ pos = (u32) tmp.params[CDSP_CMD_PARAM_RESULT_03] << 24 |
+ (u32) tmp.params[CDSP_CMD_PARAM_RESULT_02] << 16 |
+ (u32) tmp.params[CDSP_CMD_PARAM_RESULT_01] << 8 |
+ (u32) tmp.params[CDSP_CMD_PARAM_RESULT_00];
+
+ pos += info->input_pos;
+
+ return pos;
+}
+
+static inline int cdsp_coder_standby(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+ struct coder_params coder;
+ u32 fifo_id;
+ int ret;
+
+ info = cdsp_coder_info_get(id);
+
+ /* TimerReset command (Reset) */
+ coder.command = CDSP_CMD_HOST2OS_SYS_TIMER_RESET;
+ coder.params[CDSP_CMD_PARAM_ARGUMENT_00] = TIMERRESET_RESET;
+ ret = cdsp_command_write_host2os(id, &coder);
+ if (ret < 0)
+ return ret;
+
+ /* Standby command */
+ coder.command = CDSP_CMD_HOST2OS_CMN_STANDBY;
+ ret = cdsp_command_write_host2os(id, &coder);
+ if (ret < 0)
+ return ret;
+
+ /* ChangeOutSamplingRate - Not complete */
+ info->change_output_fs = false;
+
+ fifo_id = cdsp_fifoid_get_from_coderid(id);
+ if (fifo_id & FIFO_OFIFO_MASK)
+ mc_fifo_info.ofifo_output_start = false;
+
+ if (fifo_id & FIFO_RFIFO_MASK)
+ mc_fifo_info.rfifo_output_start = false;
+
+ return 0;
+}
+
+static void cdsp_coder_term(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+ u32 fifo;
+
+ info = cdsp_coder_info_get(id);
+
+ /* State check */
+ switch (info->state) {
+ case STATE_PLAYING:
+ cdsp_coder_stop(id, MADEVCDSP_VERIFY_COMP_ON);
+ cdsp_fifo_stop(id);
+ case STATE_READY_SETUP:
+ case STATE_READY:
+ cdsp_coder_close(id);
+
+ /* Terminate current program */
+ cdsp_program_terminate(id);
+ break;
+ default:
+ return;
+ }
+
+ fifo = cdsp_fifoid_get_from_coderid(id);
+ if (fifo & FIFO_DFIFO_MASK)
+ mc_fifo_info.dfifo_cb_pos = CBPOS_DFIFO_DEF;
+
+ if (fifo & FIFO_OFIFO_MASK) {
+ mc_fifo_info.ofifo_buf_sample = OFIFO_BUF_SAMPLE_DEF;
+ mc_fifo_info.ofifo_output_start = false;
+ }
+
+ if (fifo & FIFO_RFIFO_MASK) {
+ mc_fifo_info.rfifo_cb_pos = CBPOS_RFIFO_DEF;
+ mc_fifo_info.rfifo_buf_sample = RFIFO_BUF_SAMPLE_DEF;
+ mc_fifo_info.rfifo_output_start = false;
+ }
+
+ cdsp_coder_info_init(info);
+}
+
+static int cdsp_firmware_setup(struct aec_cdsp_func_info *finfo)
+{
+ struct coder_info *info;
+ struct coder_firmware coder;
+ bool download = false;
+ int ret;
+
+ if (!finfo->prog_size || !finfo->prog_data)
+ return 0;
+
+ if (mc_cdsp_info.hw_error_code != CDSP_ERR_NO_ERROR)
+ return -EBUSY;
+
+ coder.firmware = finfo->prog_data;
+ coder.size = finfo->prog_size;
+ info = cdsp_coder_info_get(finfo->id);
+
+ /* State check */
+ switch (info->state) {
+ case STATE_INIT:
+ download = true;
+ break;
+ case STATE_READY_SETUP:
+ case STATE_READY:
+ /* Check Program ID */
+ if (info->prog_info.vendor_id !=
+ MAKE_HALFWORD(coder.firmware[PRG_DESC_VENDER_ID],
+ coder.firmware[PRG_DESC_VENDER_ID + 1]))
+ download = true;
+ else if (info->prog_info.function_id !=
+ MAKE_HALFWORD(coder.firmware[PRG_DESC_FUNCTION_ID],
+ coder.firmware[PRG_DESC_FUNCTION_ID +
+ 1]))
+ download = true;
+ break;
+ default:
+ return -EBUSY;
+ }
+
+ switch (info->state) {
+ case STATE_READY_SETUP:
+ case STATE_READY:
+ cdsp_coder_close(finfo->id);
+
+ /* Terminate current program */
+ cdsp_program_terminate(finfo->id);
+
+ info->state = STATE_INIT;
+ break;
+ default:
+ break;
+ }
+
+ if (download) {
+ /* Download */
+ ret = cdsp_program_download(coder.firmware);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* Initialize */
+ ret = cdsp_program_init(finfo->id, &coder);
+ if (ret < 0)
+ return ret;
+
+ ret = cdsp_coder_open(finfo->id);
+ if (ret < 0) {
+ /* Terminate current program */
+ cdsp_program_terminate(finfo->id);
+
+ return ret;
+ }
+
+ info->state = STATE_READY_SETUP;
+
+ return 0;
+}
+
+static int cdsp_connection_setup(struct aec_cdsp_func_info *finfo)
+{
+ struct coder_info *info;
+ struct coder_params coder;
+ struct connection_info conn_info;
+ struct connection_ex_info conn_ex_info;
+ struct bit_width_info bit_width;
+ u32 prev, fifo;
+ u8 data;
+ int ret;
+
+ info = cdsp_coder_info_get(finfo->id);
+
+ conn_info.src = finfo->conn_info.src;
+ conn_info.dest = finfo->conn_info.dest;
+
+ conn_ex_info.efifo_ch = finfo->conn_ex_info.efifo_ch;
+ conn_ex_info.ofifo_ch = finfo->conn_ex_info.ofifo_ch;
+ bit_width.efifo = finfo->bit_width.efifo;
+ bit_width.ofifo = finfo->bit_width.ofifo;
+
+ if (info->conn_info.src == conn_info.src &&
+ info->conn_info.dest == conn_info.dest &&
+ info->bit_width.efifo == bit_width.efifo &&
+ info->conn_ex_info.efifo_ch == conn_ex_info.efifo_ch &&
+ info->bit_width.ofifo == bit_width.ofifo &&
+ info->conn_ex_info.ofifo_ch == conn_ex_info.ofifo_ch)
+ return 0;
+
+ /* State check */
+ switch (info->state) {
+ case STATE_READY_SETUP:
+ case STATE_READY:
+ break;
+ default:
+ return -EBUSY;
+ }
+
+ prev = FIFO_NONE;
+ if (info->conn_info.src != conn_info.src ||
+ info->conn_info.dest != conn_info.dest) {
+ switch (info->state) {
+ case STATE_READY:
+ ret = cdsp_coder_reset(finfo->id);
+ if (ret < 0)
+ return ret;
+
+ cdsp_input_position_clear(finfo->id);
+ cdsp_input_position_reset(finfo->id);
+ cdsp_output_position_clear(finfo->id);
+
+ info->state = STATE_READY_SETUP;
+ break;
+ default:
+ break;
+ }
+
+ coder.command = CDSP_CMD_HOST2OS_SYS_SET_CONNECTION;
+ coder.params[CDSP_CMD_PARAM_ARGUMENT_00] = conn_info.src;
+ coder.params[CDSP_CMD_PARAM_ARGUMENT_01] = conn_info.dest;
+ ret = cdsp_command_write_host2os(finfo->id, &coder);
+ if (ret < 0)
+ return ret;
+
+ fifo = FIFO_NONE;
+ if (conn_info.src != info->conn_info.src) {
+ switch (conn_info.src) {
+ case CDSP_IN_SOURCE_DFIFO:
+ if (info->conn_info.src !=
+ CDSP_IN_SOURCE_DFIFO_EFIFO)
+ fifo |= FIFO_DFIFO;
+ break;
+ case CDSP_IN_SOURCE_EFIFO:
+ if (info->conn_info.src !=
+ CDSP_IN_SOURCE_DFIFO_EFIFO)
+ fifo |= FIFO_EFIFO;
+ break;
+ case CDSP_IN_SOURCE_DFIFO_EFIFO:
+ if (info->conn_info.src != CDSP_IN_SOURCE_DFIFO)
+ fifo |= FIFO_DFIFO;
+
+ if (info->conn_info.src != CDSP_IN_SOURCE_EFIFO)
+ fifo |= FIFO_EFIFO;
+ break;
+ default:
+ break;
+ }
+
+ info->conn_info.src = conn_info.src;
+ }
+
+ if (conn_info.dest != info->conn_info.dest) {
+ switch (conn_info.dest) {
+ case CDSP_OUT_DEST_OFIFO:
+ if (info->conn_info.dest !=
+ CDSP_OUT_DEST_OFIFO_RFIFO)
+ fifo |= FIFO_OFIFO;
+ break;
+ case CDSP_OUT_DEST_RFIFO:
+ if (info->conn_info.dest !=
+ CDSP_OUT_DEST_OFIFO_RFIFO)
+ fifo |= FIFO_RFIFO;
+ break;
+ case CDSP_OUT_DEST_OFIFO_RFIFO:
+ if (info->conn_info.dest != CDSP_OUT_DEST_OFIFO)
+ fifo |= FIFO_OFIFO;
+
+ if (info->conn_info.dest != CDSP_OUT_DEST_RFIFO)
+ fifo |= FIFO_RFIFO;
+ break;
+ default:
+ break;
+ }
+
+ info->conn_info.dest = conn_info.dest;
+ }
+
+ if (fifo != FIFO_NONE) {
+ cdsp_fifo_init(finfo->id, fifo);
+ prev = fifo;
+ }
+ }
+
+ fifo = cdsp_fifoid_get_from_coderid(finfo->id);
+ if (info->bit_width.efifo == bit_width.efifo &&
+ info->conn_ex_info.efifo_ch == conn_ex_info.efifo_ch)
+ fifo &= ~FIFO_EFIFO_MASK;
+
+ if (info->bit_width.ofifo == bit_width.ofifo &&
+ info->conn_ex_info.ofifo_ch == conn_ex_info.ofifo_ch)
+ fifo &= ~FIFO_OFIFO_MASK;
+
+ if (fifo & (FIFO_EFIFO_MASK | FIFO_OFIFO_MASK)) {
+ data = cdsp_fifo_get_ch_bit(fifo, &conn_ex_info, &bit_width);
+ if (fifo & FIFO_EFIFO_MASK) {
+ /* Clear position */
+ cdsp_input_position_clear(finfo->id);
+
+ info->conn_ex_info.efifo_ch = conn_ex_info.efifo_ch;
+ info->bit_width.efifo = bit_width.efifo;
+ }
+
+ if (fifo & FIFO_OFIFO_MASK) {
+ /* Clear position */
+ cdsp_output_position_clear(finfo->id);
+
+ info->conn_ex_info.ofifo_ch = conn_ex_info.ofifo_ch;
+ info->bit_width.ofifo = bit_width.ofifo;
+ }
+
+ /* Clear FIFO */
+ prev = fifo & ~prev;
+ if (prev)
+ cdsp_fifo_reset(finfo->id, prev);
+
+ cdsp_fifo_set_ch(fifo, data);
+ }
+
+ return 0;
+}
+
+static int cdsp_params_set_one(enum mc_cdsp_id id,
+ struct coder_params *coder)
+{
+ struct coder_info *info;
+ int ret;
+
+ info = cdsp_coder_info_get(id);
+
+ /* State check */
+ switch (info->state) {
+ case STATE_INIT:
+ if (coder->command != CDSP_CMD_HOST2OS_SYS_SET_CLOCK_SOURCE)
+ return -EBUSY;
+ break;
+ case STATE_READY_SETUP:
+ case STATE_READY:
+ case STATE_PLAYING:
+ break;
+ default:
+ return -EBUSY;
+ }
+
+ if (!(coder->command & CDSP_CMD_COMPLETION)) {
+ /* Command check */
+ switch (coder->command) {
+ case CDSP_CMD_HOST2OS_CMN_RESET:
+ /* reset */
+ ret = cdsp_coder_reset(id);
+ if (!ret) {
+ /* Clear position */
+ cdsp_input_position_clear(id);
+ cdsp_input_position_reset(id);
+ cdsp_output_position_clear(id);
+
+ /* Clear FIFO */
+ cdsp_fifo_reset(id,
+ (FIFO_DFIFO | FIFO_EFIFO |
+ FIFO_OFIFO | FIFO_RFIFO));
+
+ cdsp_connection_reset(id);
+
+ info->state = STATE_READY_SETUP;
+ }
+ break;
+ case CDSP_CMD_HOST2OS_CMN_CLEAR:
+ ret = cdsp_coder_clear(id);
+ if (!ret) {
+ /* Clear position */
+ cdsp_input_position_clear(id);
+ cdsp_input_position_reset(id);
+ cdsp_output_position_clear(id);
+
+ /* Clear FIFO */
+ cdsp_fifo_reset(id,
+ (FIFO_DFIFO | FIFO_EFIFO |
+ FIFO_OFIFO | FIFO_RFIFO));
+ }
+ break;
+ case CDSP_CMD_HOST2OS_SYS_INPUT_DATA_END:
+ ret = cdsp_input_dataend_set(id);
+ break;
+ case CDSP_CMD_HOST2OS_SYS_SET_TIMER:
+ ret = cdsp_timer_set(id, coder);
+ break;
+
+ case CDSP_CMD_HOST2OS_SYS_SET_DUAL_MONO:
+ ret = cdsp_output_set_dualmono(id, coder);
+ break;
+ case CDSP_CMD_HOST2OS_SYS_GET_INPUT_POS:
+ ret = cdsp_input_get_position_sample(id, coder);
+ break;
+ default:
+ if ((coder->command < CDSP_CMD_HOST2OS_PRG_MIN) ||
+ (coder->command > CDSP_CMD_HOST2OS_PRG_MAX))
+ return -EINVAL;
+
+ /* Program dependence command */
+ ret = cdsp_command_write_host2os(id, coder);
+ break;
+ }
+ } else {
+ /* Host command notify completion */
+ switch (info->coder.command) {
+ case CDSP_CMD_OS2HOST_CMN_NONE:
+ return -EIO;
+ case CDSP_CMD_OS2HOST_CMN_NOTIFY_OUT_FORMAT:
+ info->change_output_fs = true;
+ cdsp_output_start(info);
+ break;
+ default:
+ break;
+ }
+
+ /* Write complete command */
+ cdsp_command_write_complete(id, coder);
+
+ /* clear */
+ info->coder.command = CDSP_CMD_OS2HOST_CMN_NONE;
+ memset(info->coder.params, 0, CDSP_CMD_PARAM_ARGUMENT_NUM);
+
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static inline int cdsp_params_get_one(enum mc_cdsp_id id,
+ struct coder_params *coder)
+{
+ struct coder_info *info;
+ int count, i;
+
+ info = cdsp_coder_info_get(id);
+
+ /* State check */
+ switch (info->state) {
+ case STATE_READY_SETUP:
+ case STATE_READY:
+ case STATE_PLAYING:
+ break;
+ default:
+ return -EBUSY;
+ }
+
+ /* Command */
+ coder->command = info->coder.command;
+
+ /* Argument */
+ count = CDSP_CMD_PARAM_ARGUMENT_00;
+ for (i = count; i < count + CDSP_CMD_PARAM_ARGUMENT_NUM; i++)
+ coder->params[i] = info->coder.params[i];
+
+ /* Result */
+ count = CDSP_CMD_PARAM_RESULT_00;
+ for (i = count; i < count + CDSP_CMD_PARAM_RESULT_NUM; i++)
+ coder->params[i] = 0;
+
+ return 0;
+}
+
+static int cdsp_params_set(struct aec_cdsp_func_info *finfo)
+{
+ struct coder_params coder;
+ u8 *data;
+ int i, j, count, ret;
+
+ if (!finfo->param_data || !finfo->param_num)
+ return 0;
+
+ data = finfo->param_data;
+ count = CDSP_CMD_PARAM_ARGUMENT_00;
+
+ for (i = 0; i < finfo->param_num; i++) {
+ coder.command = data[CDSP_PRM_CMD];
+
+ for (j = count; j < count + CDSP_CMD_PARAM_ARGUMENT_NUM; j++)
+ coder.params[j] = data[CDSP_PRM_PRM0 + j];
+
+ ret = cdsp_params_set_one(finfo->id, &coder);
+ if (ret < 0)
+ return ret;
+
+ data += PRM_UNIT_SIZE;
+ }
+
+ return 0;
+}
+
+static void cdsp_callback_set_position(enum mc_cdsp_id id,
+ struct aec_cdsp_info *cdsp_info)
+{
+ struct coder_info *info;
+ u32 fifo_id;
+
+ if (mc_fifo_info.dfifo_cb_pos == cdsp_info->dfifo_cb_pos &&
+ mc_fifo_info.rfifo_cb_pos == cdsp_info->rfifo_cb_pos)
+ return;
+
+ info = cdsp_coder_info_get(id);
+
+ fifo_id = cdsp_fifoid_get(&info->conn_info);
+ if (fifo_id & FIFO_DFIFO_MASK)
+ mc_fifo_info.dfifo_cb_pos = cdsp_info->dfifo_cb_pos;
+
+ if (fifo_id & FIFO_RFIFO_MASK)
+ mc_fifo_info.rfifo_cb_pos = cdsp_info->rfifo_cb_pos;
+}
+
+static void cdsp_callback_set_buffering(enum mc_cdsp_id id,
+ struct aec_cdsp_info *cdsp_info)
+{
+ struct coder_info *info;
+ u32 fifo_id;
+
+ if ((mc_fifo_info.ofifo_buf_sample == cdsp_info->ofifo_buf_sample) &&
+ (mc_fifo_info.rfifo_buf_sample == cdsp_info->rfifo_buf_sample))
+ return;
+
+ info = cdsp_coder_info_get(id);
+ fifo_id = cdsp_fifoid_get(&info->conn_info);
+
+ if (fifo_id & FIFO_OFIFO_MASK)
+ mc_fifo_info.ofifo_buf_sample = cdsp_info->ofifo_buf_sample;
+
+ if (fifo_id & FIFO_RFIFO_MASK)
+ mc_fifo_info.rfifo_buf_sample = cdsp_info->rfifo_buf_sample;
+}
+
+static inline void cdsp_route_set(struct aec_cdsp_info *cdsp_info)
+{
+ if (!cdsp_info->func_info[AEC_FUNC_INFO_A].fifo_data &&
+ !cdsp_info->func_info[AEC_FUNC_INFO_B].fifo_data)
+ return;
+
+ /* OUT*R/L_SEL */
+ if (cdsp_info->out0_sel != mc_fifo_info.out0_sel) {
+ mc_packet_add_force_write_c(MCI_OUT0_SEL, cdsp_info->out0_sel);
+ mc_fifo_info.out0_sel = cdsp_info->out0_sel;
+ }
+
+ if (cdsp_info->out1_sel != mc_fifo_info.out1_sel) {
+ mc_packet_add_force_write_c(MCI_OUT1_SEL, cdsp_info->out1_sel);
+ mc_fifo_info.out1_sel = cdsp_info->out1_sel;
+ }
+
+ if (cdsp_info->out2_sel != mc_fifo_info.out2_sel) {
+ mc_packet_add_force_write_c(MCI_OUT2_SEL, cdsp_info->out2_sel);
+ mc_fifo_info.out2_sel = cdsp_info->out2_sel;
+ }
+
+ /* RFIFO_BIT/RFIFO_SEL/DFIFO_BIT/DFIFO_SEL */
+ if (cdsp_info->rdfifo_bit_sel != mc_fifo_info.rdfifo_bit_sel) {
+ mc_packet_add_force_write_c(MCI_RDFIFO_BIT_SEL,
+ cdsp_info->rdfifo_bit_sel);
+ mc_fifo_info.rdfifo_bit_sel = cdsp_info->rdfifo_bit_sel;
+ }
+
+ /* EFIFO0*_SEL */
+ if (cdsp_info->efifo01_sel != mc_fifo_info.efifo01_sel) {
+ mc_packet_add_force_write_c(MCI_EFIFO01_SEL,
+ cdsp_info->efifo01_sel);
+ mc_fifo_info.efifo01_sel = cdsp_info->efifo01_sel;
+ }
+
+ if (cdsp_info->efifo23_sel != mc_fifo_info.efifo23_sel) {
+ mc_packet_add_force_write_c(MCI_EFIFO23_SEL,
+ cdsp_info->efifo23_sel);
+ mc_fifo_info.efifo23_sel = cdsp_info->efifo23_sel;
+ }
+
+ mc_packet_execute();
+}
+
+static inline void cdsp_etobuf_set_mode(enum mc_cdsp_id coder_id,
+ struct aec_cdsp_func_info *finfo)
+{
+ struct coder_info *info;
+
+ info = cdsp_coder_info_get(coder_id);
+ info->format.etobuf = finfo->format.etobuf;
+}
+
+static int cdsp_ext_set(enum mc_cdsp_id coder_id,
+ struct aec_cdsp_func_info *finfo)
+{
+ struct coder_info *info;
+ struct coder_params coder;
+ int ret = 0;
+
+ if (!finfo->ext)
+ return ret;
+
+ if (finfo->ext[EXT_COMMAND] == EXT_COMMAND_CLEAR) {
+ coder.command = CDSP_CMD_HOST2OS_CMN_CLEAR;
+
+ info = cdsp_coder_info_get(coder_id);
+ switch (info->state) {
+ case STATE_PLAYING:
+ ret =
+ cdsp_coder_stop(coder_id, MADEVCDSP_VERIFY_COMP_ON);
+ if (ret < 0)
+ return ret;
+
+ cdsp_fifo_stop(coder_id);
+ info->state = STATE_READY;
+
+ ret = cdsp_params_set_one(coder_id, &coder);
+ if (ret < 0)
+ return ret;
+
+ ret = cdsp_coder_start(coder_id);
+ if (!ret)
+ info->state = STATE_PLAYING;
+ break;
+ case STATE_READY_SETUP:
+ case STATE_READY:
+ ret = cdsp_params_set_one(coder_id, &coder);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int cdsp_set_dsp(struct aec_cdsp_info *cdsp_info)
+{
+ struct aec_cdsp_func_info *finfo_a;
+ struct aec_cdsp_func_info *finfo_b;
+ int ret;
+
+ finfo_a = &cdsp_info->func_info[AEC_FUNC_INFO_A];
+ finfo_b = &cdsp_info->func_info[AEC_FUNC_INFO_B];
+
+ if (finfo_a->func_on) {
+ ret = cdsp_firmware_setup(finfo_a);
+ if (ret < 0)
+ return ret;
+
+ ret = cdsp_connection_setup(finfo_a);
+ if (ret < 0)
+ return ret;
+
+ ret = cdsp_params_set(finfo_a);
+ if (ret < 0)
+ return ret;
+
+ cdsp_etobuf_set_mode(CODER_DEC, finfo_a);
+ cdsp_callback_set_position(CODER_DEC, cdsp_info);
+ cdsp_callback_set_buffering(CODER_DEC, cdsp_info);
+
+ ret = cdsp_ext_set(CODER_DEC, finfo_a);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (finfo_b->func_on) {
+ ret = cdsp_firmware_setup(finfo_b);
+ if (ret < 0)
+ return ret;
+
+ ret = cdsp_connection_setup(finfo_b);
+ if (ret < 0)
+ return ret;
+
+ ret = cdsp_params_set(finfo_b);
+ if (ret < 0)
+ return ret;
+
+ cdsp_etobuf_set_mode(CODER_ENC, finfo_b);
+ cdsp_callback_set_position(CODER_ENC, cdsp_info);
+ cdsp_callback_set_buffering(CODER_ENC, cdsp_info);
+
+ ret = cdsp_ext_set(CODER_ENC, finfo_b);
+ if (ret < 0)
+ return ret;
+ }
+
+ cdsp_route_set(cdsp_info);
+
+ return 0;
+}
+
+static inline void cdsp_dfifo_start(void)
+{
+ u8 ptr_h, ptr_l, data;
+
+ mc_read_c(MCI_DFIFO_ENABLE, &data, 1);
+ mc_read_c(MCI_DFIFO_IRQ_PNT_H, &ptr_h, 1);
+ mc_read_c(MCI_DFIFO_IRQ_PNT_L, &ptr_l, 1);
+
+ if (!(mc_fifo_info.rdfifo_bit_sel & MCB_DFIFO_SEL_HOST) ||
+ mc_fifo_info.dfifo_cb_pos == CBPOS_DFIFO_NONE) {
+ ptr_h = ptr_l = 0;
+ data &= ~MCB_DFIFO_EDPNT;
+ } else {
+ ptr_h = (mc_fifo_info.dfifo_cb_pos >> 8) & MCB_DFIFO_IRQ_PNT_H;
+ ptr_l = mc_fifo_info.dfifo_cb_pos & MCB_DFIFO_IRQ_PNT_L;
+ data |= MCB_DFIFO_EDPNT;
+ }
+
+ data |= MCB_DFIFO_EDEMP;
+
+ /* xFIFO/xPNT/xEMP/xUDF/xOVF Interrupt flag clear */
+ mc_packet_add_force_write_c(MCI_DFIFO_FLG, MCB_DFIFO_FLG_ALL);
+ mc_packet_add_force_write_if(MCI_CDSP, MCB_IRQFLAG_DFIFO);
+
+ /* xFIFO_IRQ_PNT Set */
+ mc_packet_add_force_write_c(MCI_DFIFO_IRQ_PNT_H, ptr_h);
+ mc_packet_add_force_write_c(MCI_DFIFO_IRQ_PNT_L, ptr_l);
+
+ /* xFIFO/xPNT/xEMP/xUDF/xOVF Interrupt Enable */
+ mc_packet_add_force_write_c(MCI_DFIFO_ENABLE, data);
+
+ mc_packet_execute();
+
+ mc_read_digital(MCI_ECDSP, &data, 1);
+ data |= MCB_EDFIFO;
+ mc_packet_add_force_write_if(MCI_ECDSP, data);
+
+ mc_packet_execute();
+}
+
+static inline void cdsp_efifo_start(void)
+{
+ /* xFIFO/xPNT/xEMP/xUDF/xOVF Interrupt flag clear */
+ mc_packet_add_force_write_c(MCI_EFIFO_FLG, MCB_EFIFO_FLG_ALL);
+ mc_packet_add_force_write_if(MCI_CDSP, MCB_IRQFLAG_EFIFO);
+
+ mc_packet_execute();
+}
+
+static inline void cdsp_ofifo_start(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+ u32 sample;
+ u8 ptr_h, ptr_l, data;
+
+ info = cdsp_coder_info_get(id);
+
+ /* xFIFO/xPNT/xEMP/xUDF/xOVF Interrupt flag clear */
+ mc_packet_add_force_write_c(MCI_OFIFO_FLG, MCB_OFIFO_FLG_ALL);
+ mc_packet_add_force_write_if(MCI_CDSP, MCB_IRQFLAG_OFIFO);
+
+ /* xFIFO_IRQ_PNT Set */
+ sample = (mc_fifo_info.ofifo_buf_sample * info->conn_ex_info.ofifo_ch *
+ (info->bit_width.ofifo / 8)) / 4;
+ ptr_h = (sample >> 8) & MCB_OFIFO_IRQ_PNT_H;
+ ptr_l = sample & MCB_OFIFO_IRQ_PNT_L;
+
+ mc_packet_add_force_write_c(MCI_OFIFO_IRQ_PNT_H, ptr_h);
+ mc_packet_add_force_write_c(MCI_OFIFO_IRQ_PNT_L, ptr_l);
+
+ /* xFIFO/xPNT Interrupt Enable */
+ mc_packet_add_force_write_c(MCI_OFIFO_ENABLE, MCB_OFIFO_EOPNT);
+
+ mc_packet_execute();
+
+ mc_read_digital(MCI_ECDSP, &data, 1);
+ data |= MCB_EOFIFO;
+ mc_packet_add_force_write_if(MCI_ECDSP, data);
+
+ mc_packet_execute();
+
+ cdsp_output_start(info);
+}
+
+static inline void cdsp_rfifo_start_port(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+ u32 sample;
+ u8 ptr_h, ptr_l, data;
+
+ info = cdsp_coder_info_get(id);
+
+ /* xFIFO/xPNT/xEMP/xUDF/xOVF Interrupt flag clear */
+ mc_packet_add_force_write_c(MCI_RFIFO_FLG, MCB_RFIFO_FLG_ALL);
+ mc_packet_add_force_write_if(MCI_CDSP, MCB_IRQFLAG_RFIFO);
+
+ /* xFIFO_IRQ_PNT Set */
+ sample = (mc_fifo_info.rfifo_buf_sample * RFIFO_CH_NUM *
+ RFIFO_BIT_WIDTH / 8) / 4;
+ ptr_h = (sample >> 8) & MCB_RFIFO_IRQ_PNT_H;
+ ptr_l = sample & MCB_RFIFO_IRQ_PNT_L;
+
+ mc_packet_add_force_write_c(MCI_RFIFO_IRQ_PNT_H, ptr_h);
+ mc_packet_add_force_write_c(MCI_RFIFO_IRQ_PNT_L, ptr_l);
+
+ /* xFIFO/xPNT/xOVF Interrupt Enable */
+ mc_packet_add_force_write_c(MCI_RFIFO_ENABLE, MCB_RFIFO_ERPNT);
+
+ mc_packet_execute();
+
+ mc_read_digital(MCI_ECDSP, &data, 1);
+ data |= MCB_ERFIFO;
+ mc_packet_add_force_write_if(MCI_ECDSP, data);
+
+ mc_packet_execute();
+
+ cdsp_output_start(info);
+}
+
+static inline void cdsp_rfifo_start_host(void)
+{
+ u8 ptr_h, ptr_l, data, ctrl;
+
+ mc_read_c(MCI_RFIFO_ENABLE, &ctrl, 1);
+ ctrl |= MCB_RFIFO_EROVF;
+
+ if (mc_fifo_info.rfifo_cb_pos != CBPOS_RFIFO_NONE) {
+ ptr_h = (mc_fifo_info.rfifo_cb_pos >> 8) & MCB_RFIFO_IRQ_PNT_H;
+ ptr_l = mc_fifo_info.rfifo_cb_pos & MCB_RFIFO_IRQ_PNT_L;
+ ctrl |= MCB_RFIFO_ERPNT;
+ } else {
+ ptr_h = 0;
+ ptr_l = 0;
+ ctrl &= ~MCB_RFIFO_ERPNT;
+ }
+
+ /* xFIFO/xPNT/xEMP/xUDF/xOVF Interrupt flag clear */
+ mc_packet_add_force_write_c(MCI_RFIFO_FLG, MCB_RFIFO_FLG_ALL);
+ mc_packet_add_force_write_if(MCI_CDSP, MCB_IRQFLAG_RFIFO);
+
+ /* xFIFO_IRQ_PNT Set */
+ mc_packet_add_force_write_c(MCI_RFIFO_IRQ_PNT_H, ptr_h);
+ mc_packet_add_force_write_c(MCI_RFIFO_IRQ_PNT_L, ptr_l);
+
+ /* xFIFO/xPNT/xOVF Interrupt Enable */
+ mc_packet_add_force_write_c(MCI_RFIFO_ENABLE, ctrl);
+
+ mc_packet_execute();
+
+ mc_read_digital(MCI_ECDSP, &data, 1);
+ data |= MCB_ERFIFO;
+ mc_packet_add_force_write_if(MCI_ECDSP, data);
+
+ mc_packet_execute();
+}
+
+static inline void cdsp_rfifo_start(enum mc_cdsp_id id)
+{
+ if (mc_fifo_info.rdfifo_bit_sel & MCB_RFIFO_SEL_HOST)
+ cdsp_rfifo_start_host();
+ else
+ cdsp_rfifo_start_port(id);
+}
+
+static inline void cdsp_fifo_start(enum mc_cdsp_id id)
+{
+ u32 fifo_id;
+
+ fifo_id = cdsp_fifoid_get_from_coderid(id);
+ if (fifo_id & FIFO_DFIFO_MASK)
+ cdsp_dfifo_start();
+
+ if (fifo_id & FIFO_EFIFO_MASK)
+ cdsp_efifo_start();
+
+ if (fifo_id & FIFO_OFIFO_MASK)
+ cdsp_ofifo_start(id);
+
+ if (fifo_id & FIFO_RFIFO_MASK)
+ cdsp_rfifo_start(id);
+}
+
+static inline int cdsp_coder_start(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+ u32 fifo_id;
+ u8 data;
+
+ info = cdsp_coder_info_get(id);
+
+ /* Mutual output ? */
+ if (info->conn_info.dest == CDSP_OUT_DEST_OTHER_INBUF) {
+ struct coder_info *another_info;
+ another_info = cdsp_coder_info_get(cdsp_another_id_get(id));
+ switch (another_info->state) {
+ case STATE_READY_SETUP:
+ case STATE_READY:
+ case STATE_PLAYING:
+ break;
+ default:
+ return -EIO;
+ }
+ }
+
+ cdsp_fifo_start(id);
+
+ /* DEC/ENC ERR,END Interrupt flag clear */
+ if (id == CDSP_DECODER) {
+ mc_read_c(MCI_DEC_FLG, &data, 1);
+ data |= MCB_DEC_FLG_ERR | MCB_DEC_FLG_END;
+ mc_packet_add_force_write_c(MCI_DEC_FLG, data);
+ } else {
+ mc_read_c(MCI_ENC_FLG, &data, 1);
+ data |= MCB_ENC_FLG_ERR | MCB_ENC_FLG_END;
+ mc_packet_add_force_write_c(MCI_ENC_FLG, data);
+ }
+
+ mc_packet_execute();
+
+ mc_read_digital(MCI_CDSP, &data, 1);
+ if (id == CDSP_DECODER)
+ data |= MCB_IRQFLAG_DEC;
+ else
+ data |= MCB_IRQFLAG_ENC;
+ mc_packet_add_force_write_if(MCI_CDSP, data);
+
+ mc_packet_execute();
+
+ /* DEC/ENC END,ERR Interrupt Enable */
+ if (id == CDSP_DECODER) {
+ mc_read_c(MCI_DEC_ENABLE, &data, 1);
+ data |= MCB_EDEC_ERR | MCB_EDEC_END;
+ mc_packet_add_force_write_c(MCI_DEC_ENABLE, data);
+ } else {
+ mc_read_c(MCI_ENC_ENABLE, &data, 1);
+ data |= MCB_EENC_ERR | MCB_EENC_END;
+ mc_packet_add_force_write_c(MCI_ENC_ENABLE, data);
+ }
+
+ mc_packet_execute();
+
+ /* DEC/ENC Start */
+ mc_read_c(MCI_DEC_START, &data, 1);
+ if (id == CDSP_DECODER)
+ data |= MCB_DEC_DEC_START;
+ else
+ data |= MCB_DEC_ENC_START;
+ mc_packet_add_force_write_c(MCI_DEC_START, data);
+
+ mc_packet_execute();
+
+ fifo_id = cdsp_fifoid_get(&info->conn_info);
+ if (fifo_id & FIFO_EFIFO) {
+ mc_read_c(MCI_DEC_FIFO_CH, &data, 1);
+ data |= MCB_DEC_EFIFO_START;
+ mc_packet_add_force_write_c(MCI_DEC_FIFO_CH, data);
+
+ mc_packet_execute();
+ }
+
+ if ((fifo_id & FIFO_DFIFO) &&
+ !(mc_fifo_info.rdfifo_bit_sel & MCB_DFIFO_SEL_HOST)) {
+ mc_read_c(MCI_RDFIFO_BIT_SEL, &data, 1);
+ data |= MCB_RDFIFO_DFIFO_START;
+ mc_packet_add_force_write_c(MCI_RDFIFO_BIT_SEL, data);
+
+ mc_packet_execute();
+ }
+
+ if (!mc_fifo_info.ofifo_buf_sample && (fifo_id & FIFO_OFIFO))
+ cdsp_interrupt_proc_ofifo_core();
+
+ if (!mc_fifo_info.rfifo_buf_sample &&
+ (fifo_id & FIFO_RFIFO) &&
+ !(mc_fifo_info.rdfifo_bit_sel & MCB_RFIFO_SEL_HOST))
+ cdsp_interrupt_proc_rfifo_core();
+
+ return 0;
+}
+
+int mc_cdsp_init(void)
+{
+ if (mc_dec_info.state == STATE_PLAYING ||
+ mc_enc_info.state == STATE_PLAYING)
+ return -EBUSY;
+
+ /* Global Initialize */
+ mc_cdsp_info.hw_error_code = CDSP_ERR_NO_ERROR;
+ mc_cdsp_info.os.version_h = 0;
+ mc_cdsp_info.os.version_l = 0;
+
+ mc_fifo_info.dfifo_cb_pos = CBPOS_DFIFO_DEF;
+ mc_fifo_info.rfifo_cb_pos = CBPOS_RFIFO_DEF;
+ mc_fifo_info.ofifo_buf_sample = OFIFO_BUF_SAMPLE_DEF;
+ mc_fifo_info.ofifo_output_start = false;
+ mc_fifo_info.dfifo_write_size = 0;
+ mc_fifo_info.rfifo_buf_sample = RFIFO_BUF_SAMPLE_DEF;
+ mc_fifo_info.rfifo_output_start = false;
+ mc_fifo_info.out0_sel = MCI_OUT0_SEL_DEF;
+ mc_fifo_info.out1_sel = MCI_OUT1_SEL_DEF;
+ mc_fifo_info.out2_sel = MCI_OUT2_SEL_DEF;
+ mc_fifo_info.rdfifo_bit_sel = 0;
+ mc_fifo_info.efifo01_sel = MCI_EFIFO01_SEL_DEF;
+ mc_fifo_info.efifo23_sel = MCI_EFIFO23_SEL_DEF;
+
+ cdsp_coder_info_init(&mc_dec_info);
+ cdsp_coder_info_init(&mc_enc_info);
+
+ cdsp_registers_init();
+
+ /* CDSP OS Download */
+ cdsp_os_download(mc_cdsp_os);
+
+ /* CDSP OS initialize */
+ return cdsp_os_init();
+}
+
+void mc_cdsp_term(void)
+{
+ u8 data;
+
+ /* CDSP stop */
+ if (mc_dec_info.state != STATE_NOTINIT ||
+ mc_enc_info.state != STATE_NOTINIT) {
+ mc_read_c(MCI_CDSP_RESET, &data, 1);
+ data |= MCB_CDSP_SRST;
+ mc_packet_add_force_write_c(MCI_CDSP_RESET, data);
+
+ mc_packet_execute();
+ }
+
+ mc_dec_info.state = STATE_NOTINIT;
+ mc_enc_info.state = STATE_NOTINIT;
+}
+
+void mc_cdsp_irq(void)
+{
+ u8 flag;
+
+ if (mc_dec_info.state == STATE_NOTINIT ||
+ mc_enc_info.state == STATE_NOTINIT)
+ return;
+
+ /* Get interrupt flag */
+ mc_read_digital(MCI_CDSP, &flag, 1);
+
+ if (flag & MCB_IRQFLAG_DEC)
+ cdsp_interrupt_proc_coder(CODER_DEC);
+
+ if (flag & MCB_IRQFLAG_ENC)
+ cdsp_interrupt_proc_coder(CODER_ENC);
+
+ if (flag & MCB_IRQFLAG_DFIFO)
+ cdsp_interrupt_proc_dfifo();
+
+ if (flag & MCB_IRQFLAG_OFIFO)
+ cdsp_interrupt_proc_ofifo();
+
+ if (flag & MCB_IRQFLAG_RFIFO)
+ cdsp_interrupt_proc_rfifo();
+
+ if (flag & MCB_IRQFLAG_CDSP)
+ cdsp_interrupt_proc();
+
+ /* Clear interrupt flag */
+ mc_packet_add_force_write_if(MCI_CDSP, flag);
+
+ mc_packet_execute();
+
+ cdsp_callback_proc();
+}
+
+int mc_cdsp_set_dsp(struct mcdrv_aec_info *aec)
+{
+ struct aec_cdsp_info cdsp_info;
+ struct aec_cdsp_func_info *finfo_a;
+ struct aec_cdsp_func_info *finfo_b;
+ int ret;
+
+ finfo_a = &cdsp_info.func_info[AEC_FUNC_INFO_A];
+ finfo_b = &cdsp_info.func_info[AEC_FUNC_INFO_B];
+
+ if (!aec)
+ return -EINVAL;
+
+ cdsp_get_data(aec, &cdsp_info);
+
+ ret = cdsp_data_analyze(&cdsp_info);
+ if (ret < 0)
+ return ret;
+
+ if (aec->vbox.enable) {
+ if (!finfo_a->func_on)
+ cdsp_coder_term(CODER_DEC);
+
+ if (!finfo_b->func_on)
+ cdsp_coder_term(CODER_ENC);
+ }
+
+ if ((!finfo_a->data || !finfo_a->data_size) &&
+ (!finfo_b->data || !finfo_b->data_size))
+ return 0;
+
+ if (mc_dec_info.state == STATE_NOTINIT ||
+ mc_enc_info.state == STATE_NOTINIT)
+ return -EBUSY;
+
+ return cdsp_set_dsp(&cdsp_info);
+}
+
+int mc_cdsp_set_fs(enum mc_cdsp_id id, u8 fs)
+{
+ struct coder_info *info;
+ struct coder_params coder;
+
+ if (mc_dec_info.state == STATE_NOTINIT ||
+ mc_enc_info.state == STATE_NOTINIT)
+ return -EBUSY;
+
+ info = cdsp_coder_info_get(id);
+
+ coder.command = CDSP_CMD_HOST2OS_SYS_SET_FORMAT;
+ coder.params[CDSP_CMD_PARAM_ARGUMENT_00] = fs;
+ coder.params[CDSP_CMD_PARAM_ARGUMENT_01] = info->format.etobuf;
+
+ return cdsp_format_set(id, &coder);
+}
+
+int mc_cdsp_set_dfifo_sel(enum mc_cdsp_fifo_sel sel)
+{
+ u8 rdfifo_bit_sel;
+
+ if (sel != CDSP_FIFO_SEL_PORT && sel != CDSP_FIFO_SEL_HOST)
+ return -EINVAL;
+
+ if (mc_dec_info.state == STATE_NOTINIT ||
+ mc_enc_info.state == STATE_NOTINIT)
+ return -EBUSY;
+
+ rdfifo_bit_sel = mc_fifo_info.rdfifo_bit_sel;
+ rdfifo_bit_sel &= ~MCB_DFIFO_SEL;
+ if (sel == CDSP_FIFO_SEL_HOST)
+ rdfifo_bit_sel |= MCB_DFIFO_SEL_HOST;
+
+ if (rdfifo_bit_sel != mc_fifo_info.rdfifo_bit_sel) {
+ mc_packet_add_force_write_c(MCI_RDFIFO_BIT_SEL, rdfifo_bit_sel);
+
+ mc_packet_execute();
+
+ mc_fifo_info.rdfifo_bit_sel = rdfifo_bit_sel;
+ }
+
+ return 0;
+}
+
+int mc_cdsp_set_rfifo_sel(enum mc_cdsp_fifo_sel sel)
+{
+ u8 rdfifo_bit_sel;
+
+ if (sel != CDSP_FIFO_SEL_PORT && sel != CDSP_FIFO_SEL_HOST)
+ return -EINVAL;
+
+ if (mc_dec_info.state == STATE_NOTINIT ||
+ mc_enc_info.state == STATE_NOTINIT)
+ return -EBUSY;
+
+ rdfifo_bit_sel = mc_fifo_info.rdfifo_bit_sel;
+ rdfifo_bit_sel &= ~MCB_RFIFO_SEL;
+ if (sel == CDSP_FIFO_SEL_HOST)
+ rdfifo_bit_sel |= MCB_RFIFO_SEL_HOST;
+
+ if (rdfifo_bit_sel != mc_fifo_info.rdfifo_bit_sel) {
+ mc_packet_add_force_write_c(MCI_RDFIFO_BIT_SEL, rdfifo_bit_sel);
+
+ mc_packet_execute();
+
+ mc_fifo_info.rdfifo_bit_sel = rdfifo_bit_sel;
+ }
+
+ return 0;
+}
+
+int mc_cdsp_start(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+ int ret;
+
+ info = cdsp_coder_info_get(id);
+ switch (info->state) {
+ case STATE_READY_SETUP:
+ ret = cdsp_coder_standby(id);
+ if (ret < 0)
+ return ret;
+
+ cdsp_fifo_reset(id,
+ (FIFO_DFIFO | FIFO_EFIFO | FIFO_OFIFO |
+ FIFO_RFIFO));
+ info->state = STATE_READY;
+
+ if (info->preinput_dataend_set) {
+ ret = cdsp_input_dataend_set(id);
+ if (ret < 0)
+ return ret;
+ }
+ break;
+ case STATE_READY:
+ cdsp_fifo_reset(id, (FIFO_DFIFO | FIFO_EFIFO));
+ break;
+ default:
+ return -EBUSY;
+ }
+
+ ret = cdsp_coder_start(id);
+ if (!ret)
+ info->state = STATE_PLAYING;
+
+ return ret;
+}
+
+int mc_cdsp_stop(enum mc_cdsp_id id)
+{
+ struct coder_info *info;
+ int ret;
+
+ info = cdsp_coder_info_get(id);
+ if (info->state != STATE_PLAYING)
+ return -EBUSY;
+
+ ret = cdsp_coder_stop(id, MADEVCDSP_VERIFY_COMP_ON);
+ if (ret < 0)
+ return ret;
+
+ cdsp_fifo_stop(id);
+
+ info->state = STATE_READY;
+
+ return ret;
+}
diff --git a/sound/soc/codecs/ymu831/mccdspdrv.h b/sound/soc/codecs/ymu831/mccdspdrv.h
new file mode 100644
index 0000000..11e669c
--- /dev/null
+++ b/sound/soc/codecs/ymu831/mccdspdrv.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+ *
+ * Copyright(c) 2012 Yamaha Corporation. All rights reserved.
+ *
+ * Module : mccdspdrv.h
+ * Description : MC C-DSP driver 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 unnecessary comments
+ * - remove unused codes
+ */
+#ifndef _MCCDSPDRV_H
+#define _MCCDSPDRV_H
+
+#include "mcresctrl.h"
+
+enum mc_cdsp_fifo_sel {
+ CDSP_FIFO_SEL_PORT,
+ CDSP_FIFO_SEL_HOST
+};
+
+enum mc_cdsp_id {
+ CDSP_DECODER,
+ CDSP_ENCODER,
+};
+
+int mc_cdsp_init(void);
+void mc_cdsp_term(void);
+void mc_cdsp_irq(void);
+int mc_cdsp_set_dsp(struct mcdrv_aec_info *aec);
+int mc_cdsp_set_fs(enum mc_cdsp_id id, u8 fs);
+int mc_cdsp_set_dfifo_sel(enum mc_cdsp_fifo_sel sel);
+int mc_cdsp_set_rfifo_sel(enum mc_cdsp_fifo_sel sel);
+int mc_cdsp_start(enum mc_cdsp_id id);
+int mc_cdsp_stop(enum mc_cdsp_id id);
+
+#endif /* _MCCDSPDRV_H */
--
1.7.9.5
More information about the Alsa-devel
mailing list