From f74563140631525e804c987b58f92a40198a492b Mon Sep 17 00:00:00 2001 From: wangzijiao Date: Wed, 1 Aug 2018 15:15:23 +0800 Subject: [PATCH] add mic i2s0 changes --- lichee/linux-4.9/drivers/misc/Kconfig | 24 + lichee/linux-4.9/drivers/misc/Makefile | 5 + .../drivers/misc/adau1761-r311-pv1.c | 1988 ++++++++++ lichee/linux-4.9/drivers/misc/xunfei/Kconfig | 7 + lichee/linux-4.9/drivers/misc/xunfei/Makefile | 1 + .../drivers/misc/xunfei/cpld/cx20810.c | 362 ++ .../drivers/misc/xunfei/cpld/cx20810_config.h | 340 ++ .../drivers/misc/xunfei/cpld/fpga_config.c | 428 +++ .../drivers/misc/xunfei/cpld/fpga_loader.c | 267 ++ .../drivers/misc/xunfei/cpld/i2c_operator.c | 313 ++ .../drivers/misc/xunfei/cpld/netease_config.c | 101 + .../linux-4.9/sound/soc/sunxi/sunxi-daudio.c | 3321 ++++++++--------- .../sound/soc/sunxi/sunxi-snddaudio.c | 4 + package/allwinner/adau1761/Makefile | 98 + package/allwinner/adau1761/src/Makefile | 16 + package/allwinner/adau1761/src/main.c | 148 + package/base-files/files/etc/config/system | 2 +- .../usr/share/golang/lib/time/zoneinfo.zip | Bin 0 -> 366113 bytes .../files/usr/share/zoneinfo/Asia/Shanghai | Bin 0 -> 172 bytes package/libs/libmsc/lib/libmsc.so | Bin 0 -> 2911636 bytes .../netease/netease_control_center/Makefile | 6 +- package/netease/netease_voice/src/base.c | 10 +- .../netease/netease_voice/src/include/base.h | 1 + .../netease/netease_voice/src/include/error.h | 6 +- package/netease/netease_voice/src/main.c | 18 +- package/netease/netease_voice/src/yunxin.c | 5 + package/netease/ntes_record/Makefile | 2 +- package/netease/ntes_record/src/record.c | 2 - target/allwinner/mandolin-pv1/config-4.9 | 11 +- .../mandolin-pv1/configs/sys_config.fex | 27 +- target/allwinner/mandolin-pv1/defconfig | 21 +- 31 files changed, 5807 insertions(+), 1727 deletions(-) create mode 100755 lichee/linux-4.9/drivers/misc/adau1761-r311-pv1.c create mode 100755 lichee/linux-4.9/drivers/misc/xunfei/Kconfig create mode 100755 lichee/linux-4.9/drivers/misc/xunfei/Makefile create mode 100755 lichee/linux-4.9/drivers/misc/xunfei/cpld/cx20810.c create mode 100755 lichee/linux-4.9/drivers/misc/xunfei/cpld/cx20810_config.h create mode 100755 lichee/linux-4.9/drivers/misc/xunfei/cpld/fpga_config.c create mode 100755 lichee/linux-4.9/drivers/misc/xunfei/cpld/fpga_loader.c create mode 100755 lichee/linux-4.9/drivers/misc/xunfei/cpld/i2c_operator.c create mode 100644 lichee/linux-4.9/drivers/misc/xunfei/cpld/netease_config.c create mode 100644 package/allwinner/adau1761/Makefile create mode 100644 package/allwinner/adau1761/src/Makefile create mode 100755 package/allwinner/adau1761/src/main.c create mode 100644 package/base-files/files/usr/share/golang/lib/time/zoneinfo.zip create mode 100644 package/base-files/files/usr/share/zoneinfo/Asia/Shanghai create mode 100644 package/libs/libmsc/lib/libmsc.so diff --git a/lichee/linux-4.9/drivers/misc/Kconfig b/lichee/linux-4.9/drivers/misc/Kconfig index 6e5ba7fa2..6418a30e9 100644 --- a/lichee/linux-4.9/drivers/misc/Kconfig +++ b/lichee/linux-4.9/drivers/misc/Kconfig @@ -4,6 +4,29 @@ menu "Misc devices" +config ADAU1761 + tristate "ADI ADAU1761 DSP" + default n + ---help--- + ADI ADAU1761 DSP. + +config ADAU1761_ES1 + tristate "ADI ADAU1761 DSP FOR ES1" + default n + ---help--- + ADI ADAU1761 DSP FOR ES1. + +config ADAU1761_ES2 + tristate "ADI ADAU1761 DSP FOR ES2" + default n + ---help--- + ADI ADAU1761 DSP FOR ES2. + +config ADAU1761_R311_PV1 + tristate "ADI ADAU1761 DSP FOR R311 PV1" + default n + ---help--- + ADI ADAU1761 DSP FOR R311 PV1. config SENSORS_LIS3LV02D tristate depends on INPUT @@ -800,4 +823,5 @@ source "drivers/misc/genwqe/Kconfig" source "drivers/misc/echo/Kconfig" source "drivers/misc/cxl/Kconfig" source "drivers/misc/sunxi-rf/Kconfig" +source "drivers/misc/xunfei/Kconfig" endmenu diff --git a/lichee/linux-4.9/drivers/misc/Makefile b/lichee/linux-4.9/drivers/misc/Makefile index b29d0a81c..92eb1c4c5 100644 --- a/lichee/linux-4.9/drivers/misc/Makefile +++ b/lichee/linux-4.9/drivers/misc/Makefile @@ -73,3 +73,8 @@ $(obj)/lkdtm_rodata_objcopy.o: $(obj)/lkdtm_rodata.o FORCE $(call if_changed,objcopy) obj-$(CONFIG_SUNXI_RFKILL) += sunxi-rf/ +obj-$(CONFIG_ADAU1761) += adau1761.o +obj-$(CONFIG_ADAU1761_ES1) += adau1761-es1.o +obj-$(CONFIG_ADAU1761_ES2) += adau1761-es2.o +obj-$(CONFIG_ADAU1761_R311_PV1) += adau1761-r311-pv1.o +obj-y += xunfei/ \ No newline at end of file diff --git a/lichee/linux-4.9/drivers/misc/adau1761-r311-pv1.c b/lichee/linux-4.9/drivers/misc/adau1761-r311-pv1.c new file mode 100755 index 000000000..e26da4bb6 --- /dev/null +++ b/lichee/linux-4.9/drivers/misc/adau1761-r311-pv1.c @@ -0,0 +1,1988 @@ +/* + * Driver for ADAU1761 codec + * +* Copyright: (C) 2017 NetEase(Hangzhou) Network Co., Ltd. + * All rights reserved. + + * + * Licensed under the GPL-2 or later. + */ +#define DEBUG + +#ifdef DEBUG +#define DSP_DEBUG(...) \ + do { \ + printk("[ADAU1761]: "__VA_ARGS__); \ + } while (0) +#else +#define DSP_DEBUG(...) +#endif + +#include +#include +#include +#include /* guess what */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* For put_user and get_user */ +#include + +#define SIGMA_MAGIC "ADISIGM" +#define ADAU1761_FIRMWARE "adau1761.bin" + +struct sigma_firmware_header { + unsigned char magic[7]; + u8 version; + __le32 crc; +} __packed; + +struct sigma_samprate_list { + __le32 samplist_len; + __le32 samplist_ind; + __le32 zeros; + __le32 sample_rate; +} __packed; + +enum { + SIGMA_ACTION_WRITEXBYTES = 0, + SIGMA_ACTION_CONTROL, + SIGMA_ACTION_END, +}; + +struct sigma_action { + __le32 len; // data chunk length + __le32 ind; // data to load, or control address? + __le32 mask; // do not care +} __packed; + +struct sigma_firmware { + const struct firmware *fw; + size_t pos; + void *control_data; +}; + +#define ADAU1761_DIGMIC_JACKDETECT 0x4008 +#define ADAU1761_REC_MIXER_LEFT0 0x400A +#define ADAU1761_REC_MIXER_LEFT1 0x400B +#define ADAU1761_REC_MIXER_RIGHT0 0x400C +#define ADAU1761_REC_MIXER_RIGHT1 0x400D +#define ADAU1761_LEFT_DIFF_INPUT_VOL 0x400E +#define ADAU1761_RIGHT_DIFF_INPUT_VOL 0x400F +#define ADAU1761_PLAY_LR_MIXER_LEFT 0x4020 +#define ADAU1761_PLAY_MIXER_LEFT0 0x401C +#define ADAU1761_PLAY_MIXER_LEFT1 0x401D +#define ADAU1761_PLAY_MIXER_RIGHT0 0x401E +#define ADAU1761_PLAY_MIXER_RIGHT1 0x401F +#define ADAU1761_PLAY_LR_MIXER_RIGHT 0x4021 +#define ADAU1761_PLAY_MIXER_MONO 0x4022 +#define ADAU1761_PLAY_HP_LEFT_VOL 0x4023 +#define ADAU1761_PLAY_HP_RIGHT_VOL 0x4024 +#define ADAU1761_PLAY_LINE_LEFT_VOL 0x4025 +#define ADAU1761_PLAY_LINE_RIGHT_VOL 0x4026 +#define ADAU1761_PLAY_MONO_OUTPUT_VOL 0x4027 +#define ADAU1761_POP_CLICK_SUPPRESS 0x4028 +#define ADAU1761_JACK_DETECT_PIN 0x4031 +#define ADAU1761_DEJITTER 0x4036 +#define ADAU1761_CLK_ENABLE0 0x40F9 +#define ADAU1761_CLK_ENABLE1 0x40FA + +/* 17x1 common registers */ +#define ADAU17X1_CLOCK_CONTROL 0x4000 +#define ADAU17X1_PLL_CONTROL 0x4002 +#define ADAU17X1_REC_POWER_MGMT 0x4009 +#define ADAU17X1_MICBIAS 0x4010 +#define ADAU17X1_SERIAL_PORT0 0x4015 +#define ADAU17X1_SERIAL_PORT1 0x4016 +#define ADAU17X1_CONVERTER0 0x4017 +#define ADAU17X1_CONVERTER1 0x4018 +#define ADAU17X1_LEFT_INPUT_DIGITAL_VOL 0x401A +#define ADAU17X1_RIGHT_INPUT_DIGITAL_VOL 0x401B +#define ADAU17X1_ADC_CONTROL 0x4019 +#define ADAU17X1_PLAY_POWER_MGMT 0x4029 +#define ADAU17X1_DAC_CONTROL0 0x402A +#define ADAU17X1_DAC_CONTROL1 0x402B +#define ADAU17X1_DAC_CONTROL2 0x402C +#define ADAU17X1_SERIAL_PORT_PAD 0x402D +#define ADAU17X1_CONTROL_PORT_PAD0 0x402F +#define ADAU17X1_CONTROL_PORT_PAD1 0x4030 +#define ADAU17X1_DSP_SAMPLING_RATE 0x40EB +#define ADAU17X1_SERIAL_INPUT_ROUTE 0x40F2 +#define ADAU17X1_SERIAL_OUTPUT_ROUTE 0x40F3 +#define ADAU17X1_DSP_ENABLE 0x40F5 +#define ADAU17X1_DSP_RUN 0x40F6 +#define ADAU17X1_SERIAL_SAMPLING_RATE 0x40F8 + +#define ADAU17X1_SERIAL_PORT0_BCLK_POL BIT(4) +#define ADAU17X1_SERIAL_PORT0_LRCLK_POL BIT(3) +#define ADAU17X1_SERIAL_PORT0_MASTER BIT(0) + +#define ADAU17X1_SERIAL_PORT1_DELAY1 0x00 +#define ADAU17X1_SERIAL_PORT1_DELAY0 0x01 +#define ADAU17X1_SERIAL_PORT1_DELAY8 0x02 +#define ADAU17X1_SERIAL_PORT1_DELAY16 0x03 +#define ADAU17X1_SERIAL_PORT1_DELAY_MASK 0x03 + +#define ADAU17X1_CLOCK_CONTROL_INFREQ_MASK 0x6 +#define ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL BIT(3) +#define ADAU17X1_CLOCK_CONTROL_SYSCLK_EN BIT(0) + +#define ADAU17X1_SERIAL_PORT1_BCLK64 (0x0 << 5) +#define ADAU17X1_SERIAL_PORT1_BCLK32 (0x1 << 5) +#define ADAU17X1_SERIAL_PORT1_BCLK48 (0x2 << 5) +#define ADAU17X1_SERIAL_PORT1_BCLK128 (0x3 << 5) +#define ADAU17X1_SERIAL_PORT1_BCLK256 (0x4 << 5) +#define ADAU17X1_SERIAL_PORT1_BCLK_MASK (0x7 << 5) + +#define ADAU17X1_SERIAL_PORT0_STEREO (0x0 << 1) +#define ADAU17X1_SERIAL_PORT0_TDM4 (0x1 << 1) +#define ADAU17X1_SERIAL_PORT0_TDM8 (0x2 << 1) +#define ADAU17X1_SERIAL_PORT0_TDM_MASK (0x3 << 1) +#define ADAU17X1_SERIAL_PORT0_PULSE_MODE BIT(5) + +#define ADAU17X1_CONVERTER0_DAC_PAIR(x) (((x)-1) << 5) +#define ADAU17X1_CONVERTER0_DAC_PAIR_MASK (0x3 << 5) +#define ADAU17X1_CONVERTER1_ADC_PAIR(x) ((x)-1) +#define ADAU17X1_CONVERTER1_ADC_PAIR_MASK 0x3 + +#define ADAU17X1_CONVERTER0_CONVSR_MASK 0x7 + +#define ADAU1761_DATA_PARAM_START_ADDR (0x0000) +#define ADAU1761_DATA_PARAM_END_ADDR (0x03FF) +#define ADAU1761_DATA_PARAM_WORD_LEN (4) + +#define ADAU1761_PROG_PARAM_START_ADDR (0x0800) +#define ADAU1761_PROG_PARAM_END_ADDR (0x0BFF) +#define ADAU1761_PROG_PARAM_WORD_LEN (5) + +#define ADAU1761_DEF_VOL_STEP (20) +#define VOL_CTL_ADDR (0x0009) +#define SRC_SW_ADDR (0x0008) + +/* safeload registers */ +#define SAFE_LOAD_DATA_1_REG (0x0001) +#define SAFE_LOAD_TARGET_ADDR_REG (0x0006) +#define SAFE_LOAD_WORD_NUM_REG (0x0007) +#define SAFE_LOAD_REG_NUM (SAFE_LOAD_WORD_NUM_REG - SAFE_LOAD_DATA_1_REG + 1) +#define SAFE_LOAD_WORD_NUM_MAX (5) +#define ADAU1761_DATA_COUNT (4) +#define SAFE_LOAD_EQ_SWITCH_REG (0x0047) + +const unsigned char adau1761_init_arr_00[] = { + 0x40, 0xEB, /* (0) IC 1.Sample Rate Setting */ + 0x7F}; + +const unsigned char adau1761_init_arr_01[] = { + 0x40, + 0xF6, /* (1) IC 1.DSP Run Register */ + 0x00, +}; + +const unsigned char adau1761_init_arr_02[] = { + 0x40, + 0x00, /* (2) IC 1.Clock Control Register */ + 0x0F, +}; + +const unsigned char adau1761_init_arr_03[] = { + 0x40, 0x02, /* (3) IC 1.PLL Control Register */ + 0x00, 0x7D, 0x00, 0x0C, 0x23, 0x01, +}; + +const unsigned char adau1761_init_arr_04[] = { + // 0x00, 0x00, /* (4) IC 1.Delay */ + // 0x00, 0x64, +}; + +const unsigned char adau1761_init_arr_05[] = { + 0x40, + 0x15, /* (5) IC 1.Serial Port Control Registers */ + 0x00, + 0x00, +}; + +const unsigned char adau1761_init_arr_06[] = { + 0x40, 0x11, /* (6) IC 1.ALC Control Registers */ + 0x00, 0x00, 0x00, 0x00, +}; + +const unsigned char adau1761_init_arr_07[] = { + 0x40, + 0x08, /* (7) IC 1.Microphone Control Register */ + 0x00, +}; + +const unsigned char adau1761_init_arr_08[] = { + 0x40, 0x09, /* (8) IC 1.Record Input Signal Path Registers */ + 0x00, 0x01, 0x08, 0x01, 0x08, 0x33, 0x33, 0x00, +}; + +const unsigned char adau1761_init_arr_09[] = { + 0x40, 0x19, /* (9) IC 1.ADC Control Registers */ + 0x13, 0x00, 0x00, +}; + +const unsigned char adau1761_init_arr_10[] = { + 0x40, 0x1C, /* (10) IC 1.Playback Output Signal Path Registers */ + 0x21, 0x00, 0x41, 0x00, 0x03, 0x09, 0x00, + 0xE5, 0xE5, 0xE6, 0xE6, 0xE5, 0x00, 0x03, +}; + +const unsigned char adau1761_init_arr_11[] = { + 0x40, + 0x17, /* (11) IC 1.Converter Control Registers */ + 0x00, + 0x00, +}; + +const unsigned char adau1761_init_arr_12[] = { + 0x40, 0x2A, /* (12) IC 1.DAC Control Registers */ + 0x03, 0x00, 0x00, +}; + +const unsigned char adau1761_init_arr_13[] = { + 0x40, + 0x2D, /* (13) IC 1.Serial Port Pad Control Registers */ + 0xAA, +}; + +const unsigned char adau1761_init_arr_14[] = { + 0x40, + 0x2F, /* (14) IC 1.Communication Port Pad Control Registers */ + 0xAA, + 0x00, +}; + +const unsigned char adau1761_init_arr_15[] = { + 0x40, + 0x31, /* (15) IC 1.Jack Detect Pad Control Register */ + 0x08, +}; + +const unsigned char adau1761_init_arr_16[] = { + 0x08, 0x00, /* (16) Program Clear Block 0 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +const unsigned char adau1761_init_arr_17[] = { + 0x08, 0xCC, /* (17) Program Clear Block 1 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +const unsigned char adau1761_init_arr_18[] = { + 0x09, 0x98, /* (18) Program Clear Block 2 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +const unsigned char adau1761_init_arr_19[] = { + 0x0A, 0x64, /* (19) Program Clear Block 3 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +const unsigned char adau1761_init_arr_20[] = { + 0x0B, 0xFC, /* (20) Program Clear Block 4 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +const unsigned char adau1761_init_arr_21[] = { + 0x40, + 0xF5, /* (21) IC 1.DSP ON Register */ + 0x01, +}; + +const unsigned char adau1761_init_arr_22[] = { + 0x40, 0xC0, /* (22) IC 1.CRC Registers */ + 0x7F, 0x7F, 0x7F, 0x7F, 0x01, +}; + +const unsigned char adau1761_init_arr_23[] = { + 0x40, 0xC6, /* (23) IC 1.GPIO Registers */ + 0x00, 0x00, 0x00, 0x00, +}; + +const unsigned char adau1761_init_arr_24[] = { + 0x40, + 0xE9, /* (24) IC 1.Non Modulo Registers */ + 0x0F, + 0xFC, +}; + +const unsigned char adau1761_init_arr_25[] = { + 0x40, 0xD0, /* (25) IC 1.Watchdog Registers */ + 0x00, 0x04, 0x00, 0x00, 0x00, +}; + +const unsigned char adau1761_init_arr_26[] = { + 0x40, + 0xEB, /* (26) IC 1.Sampling Rate Setting Register */ + 0x7F, +}; + +const unsigned char adau1761_init_arr_27[] = { + 0x40, + 0xF2, /* (27) IC 1.Routing Matrix Inputs Register */ + 0x00, +}; + +const unsigned char adau1761_init_arr_28[] = { + 0x40, + 0xF3, /* (28) IC 1.Routing Matrix Outputs Register */ + 0x00, +}; + +const unsigned char adau1761_init_arr_29[] = { + 0x40, + 0xF4, /* (29) IC 1.Serial Data Configuration Register */ + 0x00, +}; + +const unsigned char adau1761_init_arr_30[] = { + 0x40, + 0xF7, /* (30) IC 1.DSP Slew Mode Register */ + 0x00, +}; + +const unsigned char adau1761_init_arr_31[] = { + 0x40, + 0xF8, /* (31) IC 1.Serial Port Sample Rate Register */ + 0x00, +}; + +const unsigned char adau1761_init_arr_32[] = { + 0x40, + 0xF9, /* (32) IC 1.Clock Enable Registers */ + 0x7F, + 0x03, +}; + +const unsigned char adau1761_init_arr_33[] = { + 0x08, 0x00, /* (33) Program Data */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xE0, 0x00, 0x00, 0x00, 0xFF, 0x34, + 0x00, 0x00, 0x00, 0xFF, 0x2C, 0x00, 0x00, 0x00, 0xFF, 0x54, 0x00, 0x00, + 0x00, 0xFF, 0x5C, 0x00, 0x00, 0x00, 0xFF, 0xF5, 0x08, 0x20, 0x00, 0xFF, + 0x38, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xE8, 0x0C, 0x00, 0x00, + 0xFE, 0x30, 0x00, 0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0xE8, 0x07, 0x20, 0x08, 0x00, 0x00, 0x06, 0xA0, 0x00, 0xFF, 0xE0, 0x00, + 0xC0, 0x00, 0xFF, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC0, 0x22, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFE, 0xE8, 0x1E, 0x00, 0x00, 0xFF, 0xE8, 0x01, 0x20, + 0x00, 0xFF, 0xD8, 0x01, 0x03, 0x00, 0x00, 0x07, 0xC6, 0x00, 0x00, 0xFF, + 0x08, 0x00, 0x00, 0x00, 0xFF, 0xF4, 0x00, 0x20, 0x00, 0xFF, 0xD8, 0x07, + 0x02, 0x00, 0xFD, 0xA5, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x00, + 0xFD, 0xAD, 0x08, 0x20, 0x00, 0x00, 0x08, 0x00, 0xE2, 0x00, 0xFD, 0x25, + 0x08, 0x20, 0x00, 0x00, 0x10, 0x00, 0xE2, 0x00, 0xFD, 0x2D, 0x08, 0x20, + 0x00, 0x00, 0x18, 0x00, 0xE2, 0x00, 0xFF, 0xE8, 0x08, 0x20, 0x00, 0x00, + 0x58, 0x00, 0xE2, 0x00, 0x00, 0x05, 0x08, 0x20, 0x00, 0x00, 0x30, 0x00, + 0xE2, 0x00, 0x00, 0x0D, 0x08, 0x20, 0x00, 0x00, 0x40, 0x00, 0xE2, 0x00, + 0x00, 0x15, 0x08, 0x20, 0x00, 0x00, 0x38, 0x00, 0xE2, 0x00, 0x00, 0x1D, + 0x08, 0x20, 0x00, 0x00, 0x48, 0x00, 0xE2, 0x00, 0xFF, 0xF5, 0x08, 0x20, + 0x00, 0x00, 0xB0, 0x00, 0xE2, 0x00, 0x00, 0x55, 0x08, 0x20, 0x00, 0x00, + 0x5D, 0x08, 0x22, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xED, 0x08, + 0x20, 0x26, 0x00, 0xB0, 0x00, 0xE2, 0x00, 0x00, 0x75, 0x08, 0x20, 0x00, + 0xFF, 0xED, 0x13, 0x22, 0x48, 0x00, 0x55, 0x08, 0x20, 0x00, 0x00, 0x95, + 0x08, 0x20, 0x25, 0x00, 0x98, 0x00, 0xE2, 0x00, 0x00, 0x85, 0x08, 0x20, + 0x00, 0xFF, 0xED, 0x13, 0x22, 0x48, 0x00, 0x55, 0x08, 0x20, 0x00, 0x00, + 0xA5, 0x08, 0x20, 0x25, 0x00, 0xA8, 0x00, 0xE2, 0x00, 0x00, 0xBD, 0x08, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x00, 0xF0, 0x00, + 0x00, 0xCD, 0x08, 0x20, 0x00, 0xFF, 0xED, 0x13, 0x22, 0x48, 0x00, 0xB5, + 0x08, 0x20, 0x00, 0xFF, 0xF5, 0x08, 0x20, 0x25, 0x00, 0xB0, 0x00, 0xE2, + 0x00, 0x00, 0x55, 0x08, 0x20, 0x00, 0x00, 0x58, 0x00, 0xE2, 0x25, 0x00, + 0x65, 0x08, 0x20, 0x00, 0x00, 0x75, 0x08, 0x22, 0x40, 0x00, 0xC0, 0x00, + 0xE2, 0x00, 0x00, 0x75, 0x08, 0x20, 0x00, 0x00, 0xC5, 0x14, 0x22, 0x00, + 0x00, 0x78, 0x00, 0xE2, 0x00, 0x00, 0x98, 0x00, 0xC0, 0x00, 0x00, 0x07, + 0xFF, 0xA0, 0x00, 0x00, 0x78, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x37, 0xFF, 0x20, 0x80, 0x00, 0x20, 0x00, 0xE2, 0x00, 0x00, + 0x47, 0xFF, 0x40, 0x80, 0x00, 0x28, 0x00, 0xE4, 0x00, 0xFF, 0xED, 0x08, + 0x20, 0x00, 0xFF, 0xEF, 0xFF, 0x22, 0x40, 0x00, 0x88, 0x00, 0xE2, 0x00, + 0x00, 0xA8, 0x00, 0xC0, 0x00, 0x00, 0x07, 0xFF, 0xA0, 0x00, 0x00, 0x88, + 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0xFF, 0x20, + 0x80, 0x00, 0x25, 0x08, 0x22, 0x00, 0x00, 0x20, 0x00, 0xE2, 0x00, 0x00, + 0x47, 0xFF, 0x40, 0x80, 0x00, 0x2D, 0x08, 0x44, 0x00, 0x00, 0x28, 0x00, + 0xE4, 0x00, 0x00, 0x65, 0x08, 0x20, 0x00, 0x00, 0xB5, 0x08, 0x22, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0xF0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xE8, 0x09, 0x20, 0x00, 0x00, 0xD5, 0x08, 0x22, + 0x40, 0x00, 0xF0, 0x00, 0xE2, 0x00, 0x00, 0xE5, 0x08, 0x20, 0x00, 0x00, + 0xD5, 0x08, 0x34, 0x00, 0x00, 0xF0, 0x0A, 0x22, 0x00, 0x00, 0xD8, 0x00, + 0xE2, 0x00, 0x00, 0xD8, 0x00, 0xC0, 0x00, 0x00, 0xE8, 0x00, 0xF2, 0x00, + 0x00, 0x27, 0xFF, 0x20, 0x00, 0x01, 0x08, 0x00, 0xE2, 0x00, 0x00, 0x2F, + 0xFF, 0x20, 0x00, 0x01, 0x50, 0x00, 0xE2, 0x00, 0x01, 0x18, 0x0E, 0x20, + 0x00, 0x01, 0x10, 0x0F, 0x22, 0x00, 0x01, 0x08, 0x0B, 0x22, 0x00, 0x01, + 0x00, 0x0C, 0x22, 0x00, 0x00, 0xF8, 0x0D, 0x22, 0x00, 0x01, 0x20, 0x00, + 0xE2, 0x00, 0x01, 0x30, 0x13, 0x20, 0x00, 0x01, 0x28, 0x14, 0x22, 0x00, + 0x01, 0x20, 0x10, 0x22, 0x00, 0x01, 0x18, 0x11, 0x22, 0x00, 0x01, 0x10, + 0x12, 0x22, 0x00, 0x01, 0x38, 0x00, 0xE2, 0x00, 0x01, 0x60, 0x0E, 0x20, + 0x00, 0x01, 0x58, 0x0F, 0x22, 0x00, 0x01, 0x50, 0x0B, 0x22, 0x00, 0x01, + 0x48, 0x0C, 0x22, 0x00, 0x01, 0x40, 0x0D, 0x22, 0x00, 0x01, 0x68, 0x00, + 0xE2, 0x00, 0x01, 0x78, 0x13, 0x20, 0x00, 0x01, 0x70, 0x14, 0x22, 0x00, + 0x01, 0x68, 0x10, 0x22, 0x00, 0x01, 0x60, 0x11, 0x22, 0x00, 0x01, 0x58, + 0x12, 0x22, 0x00, 0x01, 0x80, 0x00, 0xE2, 0x00, 0x01, 0x90, 0x18, 0x20, + 0x00, 0x01, 0x88, 0x19, 0x22, 0x00, 0x01, 0x38, 0x15, 0x22, 0x00, 0x01, + 0x30, 0x16, 0x22, 0x00, 0x01, 0x28, 0x17, 0x22, 0x00, 0x01, 0x98, 0x00, + 0xE2, 0x00, 0x01, 0xA8, 0x1D, 0x20, 0x00, 0x01, 0xA0, 0x1E, 0x22, 0x00, + 0x01, 0x98, 0x1A, 0x22, 0x00, 0x01, 0x90, 0x1B, 0x22, 0x00, 0x01, 0x88, + 0x1C, 0x22, 0x00, 0x01, 0xB0, 0x00, 0xE2, 0x00, 0x01, 0xC0, 0x22, 0x20, + 0x00, 0x01, 0xB8, 0x23, 0x22, 0x00, 0x01, 0xB0, 0x1F, 0x22, 0x00, 0x01, + 0xA8, 0x20, 0x22, 0x00, 0x01, 0xA0, 0x21, 0x22, 0x00, 0x01, 0xC8, 0x00, + 0xE2, 0x00, 0x01, 0xD8, 0x27, 0x20, 0x00, 0x01, 0xD0, 0x28, 0x22, 0x00, + 0x01, 0xC8, 0x24, 0x22, 0x00, 0x01, 0xC0, 0x25, 0x22, 0x00, 0x01, 0xB8, + 0x26, 0x22, 0x00, 0x01, 0xE0, 0x00, 0xE2, 0x00, 0x01, 0xF0, 0x2C, 0x20, + 0x00, 0x01, 0xE8, 0x2D, 0x22, 0x00, 0x01, 0xE0, 0x29, 0x22, 0x00, 0x01, + 0xD8, 0x2A, 0x22, 0x00, 0x01, 0xD0, 0x2B, 0x22, 0x00, 0x01, 0xF8, 0x00, + 0xE2, 0x00, 0x02, 0x08, 0x31, 0x20, 0x00, 0x02, 0x00, 0x32, 0x22, 0x00, + 0x01, 0xF8, 0x2E, 0x22, 0x00, 0x01, 0xF0, 0x2F, 0x22, 0x00, 0x01, 0xE8, + 0x30, 0x22, 0x00, 0x02, 0x10, 0x00, 0xE2, 0x00, 0x02, 0x20, 0x18, 0x20, + 0x00, 0x02, 0x18, 0x19, 0x22, 0x00, 0x01, 0x80, 0x15, 0x22, 0x00, 0x01, + 0x78, 0x16, 0x22, 0x00, 0x01, 0x70, 0x17, 0x22, 0x00, 0x02, 0x28, 0x00, + 0xE2, 0x00, 0x02, 0x38, 0x1D, 0x20, 0x00, 0x02, 0x30, 0x1E, 0x22, 0x00, + 0x02, 0x28, 0x1A, 0x22, 0x00, 0x02, 0x20, 0x1B, 0x22, 0x00, 0x02, 0x18, + 0x1C, 0x22, 0x00, 0x02, 0x40, 0x00, 0xE2, 0x00, 0x02, 0x50, 0x22, 0x20, + 0x00, 0x02, 0x48, 0x23, 0x22, 0x00, 0x02, 0x40, 0x1F, 0x22, 0x00, 0x02, + 0x38, 0x20, 0x22, 0x00, 0x02, 0x30, 0x21, 0x22, 0x00, 0x02, 0x58, 0x00, + 0xE2, 0x00, 0x02, 0x68, 0x27, 0x20, 0x00, 0x02, 0x60, 0x28, 0x22, 0x00, + 0x02, 0x58, 0x24, 0x22, 0x00, 0x02, 0x50, 0x25, 0x22, 0x00, 0x02, 0x48, + 0x26, 0x22, 0x00, 0x02, 0x70, 0x00, 0xE2, 0x00, 0x02, 0x80, 0x2C, 0x20, + 0x00, 0x02, 0x78, 0x2D, 0x22, 0x00, 0x02, 0x70, 0x29, 0x22, 0x00, 0x02, + 0x68, 0x2A, 0x22, 0x00, 0x02, 0x60, 0x2B, 0x22, 0x00, 0x02, 0x88, 0x00, + 0xE2, 0x00, 0x02, 0x98, 0x31, 0x20, 0x00, 0x02, 0x90, 0x32, 0x22, 0x00, + 0x02, 0x88, 0x2E, 0x22, 0x00, 0x02, 0x80, 0x2F, 0x22, 0x00, 0x02, 0x78, + 0x30, 0x22, 0x00, 0x02, 0xA0, 0x00, 0xE2, 0x00, 0x02, 0xB0, 0x36, 0x20, + 0x00, 0x02, 0xA8, 0x37, 0x22, 0x00, 0x01, 0x38, 0x33, 0x22, 0x00, 0x01, + 0x30, 0x34, 0x22, 0x00, 0x01, 0x28, 0x35, 0x22, 0x00, 0x02, 0xB8, 0x00, + 0xE2, 0x00, 0x02, 0xC8, 0x3B, 0x20, 0x00, 0x02, 0xC0, 0x3C, 0x22, 0x00, + 0x02, 0xB8, 0x38, 0x22, 0x00, 0x02, 0xB0, 0x39, 0x22, 0x00, 0x02, 0xA8, + 0x3A, 0x22, 0x00, 0x02, 0xD0, 0x00, 0xE2, 0x00, 0x02, 0xE0, 0x40, 0x20, + 0x00, 0x02, 0xD8, 0x41, 0x22, 0x00, 0x02, 0xD0, 0x3D, 0x22, 0x00, 0x02, + 0xC8, 0x3E, 0x22, 0x00, 0x02, 0xC0, 0x3F, 0x22, 0x00, 0x02, 0xE8, 0x00, + 0xE2, 0x00, 0x02, 0xF8, 0x45, 0x20, 0x00, 0x02, 0xF0, 0x46, 0x22, 0x00, + 0x02, 0xE8, 0x42, 0x22, 0x00, 0x02, 0xE0, 0x43, 0x22, 0x00, 0x02, 0xD8, + 0x44, 0x22, 0x00, 0x03, 0x00, 0x00, 0xE2, 0x00, 0x03, 0x10, 0x36, 0x20, + 0x00, 0x03, 0x08, 0x37, 0x22, 0x00, 0x01, 0x80, 0x33, 0x22, 0x00, 0x01, + 0x78, 0x34, 0x22, 0x00, 0x01, 0x70, 0x35, 0x22, 0x00, 0x03, 0x18, 0x00, + 0xE2, 0x00, 0x03, 0x28, 0x3B, 0x20, 0x00, 0x03, 0x20, 0x3C, 0x22, 0x00, + 0x03, 0x18, 0x38, 0x22, 0x00, 0x03, 0x10, 0x39, 0x22, 0x00, 0x03, 0x08, + 0x3A, 0x22, 0x00, 0x03, 0x30, 0x00, 0xE2, 0x00, 0x03, 0x40, 0x40, 0x20, + 0x00, 0x03, 0x38, 0x41, 0x22, 0x00, 0x03, 0x30, 0x3D, 0x22, 0x00, 0x03, + 0x28, 0x3E, 0x22, 0x00, 0x03, 0x20, 0x3F, 0x22, 0x00, 0x03, 0x48, 0x00, + 0xE2, 0x00, 0x03, 0x58, 0x45, 0x20, 0x00, 0x03, 0x50, 0x46, 0x22, 0x00, + 0x03, 0x48, 0x42, 0x22, 0x00, 0x03, 0x40, 0x43, 0x22, 0x00, 0x03, 0x38, + 0x44, 0x22, 0x00, 0x03, 0x60, 0x00, 0xE2, 0x00, 0xFF, 0xE8, 0x47, 0x20, + 0x00, 0x03, 0xB0, 0x00, 0xE2, 0x00, 0x01, 0x3D, 0x08, 0x20, 0x00, 0x03, + 0x78, 0x00, 0xE2, 0x00, 0x01, 0x85, 0x08, 0x20, 0x00, 0x03, 0x90, 0x00, + 0xE2, 0x00, 0x02, 0x15, 0x08, 0x20, 0x00, 0x03, 0x80, 0x00, 0xE2, 0x00, + 0x02, 0xA5, 0x08, 0x20, 0x00, 0x03, 0x98, 0x00, 0xE2, 0x00, 0x03, 0x05, + 0x08, 0x20, 0x00, 0x03, 0x88, 0x00, 0xE2, 0x00, 0x03, 0x65, 0x08, 0x20, + 0x00, 0x03, 0xA0, 0x00, 0xE2, 0x00, 0xFF, 0xF5, 0x08, 0x20, 0x00, 0x04, + 0x08, 0x00, 0xE2, 0x00, 0x03, 0xAD, 0x08, 0x20, 0x00, 0x03, 0xB5, 0x08, + 0x22, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xED, 0x08, 0x20, 0x26, + 0x04, 0x08, 0x00, 0xE2, 0x00, 0x03, 0xCD, 0x08, 0x20, 0x00, 0xFF, 0xED, + 0x13, 0x22, 0x48, 0x03, 0xAD, 0x08, 0x20, 0x00, 0x03, 0xED, 0x08, 0x20, + 0x25, 0x03, 0xF0, 0x00, 0xE2, 0x00, 0x03, 0xDD, 0x08, 0x20, 0x00, 0xFF, + 0xED, 0x13, 0x22, 0x48, 0x03, 0xAD, 0x08, 0x20, 0x00, 0x03, 0xFD, 0x08, + 0x20, 0x25, 0x04, 0x00, 0x00, 0xE2, 0x00, 0x04, 0x15, 0x08, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x00, 0xF0, 0x00, 0x04, 0x25, + 0x08, 0x20, 0x00, 0xFF, 0xED, 0x13, 0x22, 0x48, 0x04, 0x0D, 0x08, 0x20, + 0x00, 0xFF, 0xF5, 0x08, 0x20, 0x25, 0x04, 0x08, 0x00, 0xE2, 0x00, 0x03, + 0xAD, 0x08, 0x20, 0x00, 0x03, 0xB0, 0x00, 0xE2, 0x25, 0x03, 0xBD, 0x08, + 0x20, 0x00, 0x03, 0xCD, 0x08, 0x22, 0x40, 0x04, 0x18, 0x00, 0xE2, 0x00, + 0x03, 0xCD, 0x08, 0x20, 0x00, 0x04, 0x1D, 0x14, 0x22, 0x00, 0x03, 0xD0, + 0x00, 0xE2, 0x00, 0x03, 0xF0, 0x00, 0xC0, 0x00, 0x00, 0x07, 0xFF, 0xA0, + 0x00, 0x03, 0xD0, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x7F, 0xFF, 0x20, 0x80, 0x03, 0x68, 0x00, 0xE2, 0x00, 0x03, 0x97, 0xFF, + 0x40, 0x80, 0x03, 0x70, 0x00, 0xE4, 0x00, 0xFF, 0xED, 0x08, 0x20, 0x00, + 0xFF, 0xEF, 0xFF, 0x22, 0x40, 0x03, 0xE0, 0x00, 0xE2, 0x00, 0x04, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x07, 0xFF, 0xA0, 0x00, 0x03, 0xE0, 0x00, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x7F, 0xFF, 0x20, 0x80, 0x03, + 0x6D, 0x08, 0x22, 0x00, 0x03, 0x68, 0x00, 0xE2, 0x00, 0x03, 0x97, 0xFF, + 0x40, 0x80, 0x03, 0x75, 0x08, 0x44, 0x00, 0x03, 0x70, 0x00, 0xE4, 0x00, + 0x03, 0xBD, 0x08, 0x20, 0x00, 0x04, 0x0D, 0x08, 0x22, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x68, 0x48, 0x20, 0x00, 0x03, 0x70, 0x48, 0x22, 0x00, 0x04, + 0x38, 0x00, 0xE2, 0x00, 0x04, 0x60, 0x4C, 0x20, 0x00, 0x04, 0x58, 0x4D, + 0x22, 0x00, 0x04, 0x48, 0x4C, 0x34, 0x00, 0x04, 0x40, 0x4D, 0x22, 0x00, + 0x04, 0x38, 0x49, 0x22, 0x00, 0x04, 0x30, 0x4A, 0x22, 0x00, 0x04, 0x28, + 0x4B, 0x22, 0x00, 0x04, 0x50, 0x00, 0xE2, 0x00, 0x04, 0x68, 0x00, 0xF2, + 0x00, 0x04, 0x90, 0x51, 0x20, 0x00, 0x04, 0x88, 0x52, 0x22, 0x00, 0x04, + 0x78, 0x51, 0x34, 0x00, 0x04, 0x70, 0x52, 0x22, 0x00, 0x04, 0x50, 0x4E, + 0x22, 0x00, 0x04, 0x48, 0x4F, 0x22, 0x00, 0x04, 0x40, 0x50, 0x22, 0x00, + 0x04, 0x80, 0x00, 0xE2, 0x00, 0x04, 0x98, 0x00, 0xF2, 0x00, 0x04, 0x80, + 0x53, 0x20, 0x00, 0x04, 0xB0, 0x00, 0xE2, 0x00, 0x04, 0xD8, 0x56, 0x20, + 0x00, 0x04, 0xD0, 0x58, 0x22, 0x00, 0x04, 0xC0, 0x56, 0x34, 0x00, 0x04, + 0xB8, 0x58, 0x22, 0x00, 0x04, 0xB0, 0x54, 0x22, 0x00, 0x04, 0xA8, 0x55, + 0x22, 0x00, 0x04, 0xA0, 0x57, 0x22, 0x00, 0x04, 0xC8, 0x00, 0xE2, 0x00, + 0x04, 0xE0, 0x00, 0xF2, 0x00, 0x05, 0x08, 0x5B, 0x20, 0x00, 0x05, 0x00, + 0x5D, 0x22, 0x00, 0x04, 0xF0, 0x5B, 0x34, 0x00, 0x04, 0xE8, 0x5D, 0x22, + 0x00, 0x04, 0xC8, 0x59, 0x22, 0x00, 0x04, 0xC0, 0x5A, 0x22, 0x00, 0x04, + 0xB8, 0x5C, 0x22, 0x00, 0x04, 0xF8, 0x00, 0xE2, 0x00, 0x05, 0xA0, 0x00, + 0xE2, 0x00, 0x05, 0x10, 0x00, 0xF2, 0x00, 0x04, 0x85, 0x08, 0x20, 0x00, + 0x05, 0x28, 0x00, 0xE2, 0x00, 0x05, 0x50, 0x60, 0x20, 0x00, 0x05, 0x48, + 0x62, 0x22, 0x00, 0x05, 0x38, 0x60, 0x34, 0x00, 0x05, 0x30, 0x62, 0x22, + 0x00, 0x05, 0x28, 0x5E, 0x22, 0x00, 0x05, 0x20, 0x5F, 0x22, 0x00, 0x05, + 0x18, 0x61, 0x22, 0x00, 0x05, 0x40, 0x00, 0xE2, 0x00, 0x05, 0x58, 0x00, + 0xF2, 0x00, 0x05, 0x80, 0x65, 0x20, 0x00, 0x05, 0x78, 0x67, 0x22, 0x00, + 0x05, 0x68, 0x65, 0x34, 0x00, 0x05, 0x60, 0x67, 0x22, 0x00, 0x05, 0x40, + 0x63, 0x22, 0x00, 0x05, 0x38, 0x64, 0x22, 0x00, 0x05, 0x30, 0x66, 0x22, + 0x00, 0x05, 0x70, 0x00, 0xE2, 0x00, 0x06, 0x18, 0x00, 0xE2, 0x00, 0x05, + 0x88, 0x00, 0xF2, 0x00, 0x05, 0xC8, 0x6B, 0x20, 0x00, 0x05, 0xC0, 0x6C, + 0x22, 0x00, 0x05, 0xB0, 0x6B, 0x34, 0x00, 0x05, 0xA8, 0x6C, 0x22, 0x00, + 0x05, 0xA0, 0x68, 0x22, 0x00, 0x05, 0x98, 0x69, 0x22, 0x00, 0x05, 0x90, + 0x6A, 0x22, 0x00, 0x05, 0xB8, 0x00, 0xE2, 0x00, 0x05, 0xD0, 0x00, 0xF2, + 0x00, 0x05, 0xF8, 0x70, 0x20, 0x00, 0x05, 0xF0, 0x71, 0x22, 0x00, 0x05, + 0xE0, 0x70, 0x34, 0x00, 0x05, 0xD8, 0x71, 0x22, 0x00, 0x05, 0xB8, 0x6D, + 0x22, 0x00, 0x05, 0xB0, 0x6E, 0x22, 0x00, 0x05, 0xA8, 0x6F, 0x22, 0x00, + 0x05, 0xE8, 0x00, 0xE2, 0x00, 0x06, 0x00, 0x00, 0xF2, 0x00, 0x06, 0x40, + 0x75, 0x20, 0x00, 0x06, 0x38, 0x76, 0x22, 0x00, 0x06, 0x28, 0x75, 0x34, + 0x00, 0x06, 0x20, 0x76, 0x22, 0x00, 0x06, 0x18, 0x72, 0x22, 0x00, 0x06, + 0x10, 0x73, 0x22, 0x00, 0x06, 0x08, 0x74, 0x22, 0x00, 0x06, 0x30, 0x00, + 0xE2, 0x00, 0x06, 0x48, 0x00, 0xF2, 0x00, 0x06, 0x70, 0x7A, 0x20, 0x00, + 0x06, 0x68, 0x7B, 0x22, 0x00, 0x06, 0x58, 0x7A, 0x34, 0x00, 0x06, 0x50, + 0x7B, 0x22, 0x00, 0x06, 0x30, 0x77, 0x22, 0x00, 0x06, 0x28, 0x78, 0x22, + 0x00, 0x06, 0x20, 0x79, 0x22, 0x00, 0x06, 0x60, 0x00, 0xE2, 0x00, 0x06, + 0x78, 0x00, 0xF2, 0x00, 0x06, 0xA0, 0x7F, 0x20, 0x00, 0x06, 0x98, 0x80, + 0x22, 0x00, 0x06, 0x88, 0x7F, 0x34, 0x00, 0x06, 0x80, 0x80, 0x22, 0x00, + 0x06, 0x60, 0x7C, 0x22, 0x00, 0x06, 0x58, 0x7D, 0x22, 0x00, 0x06, 0x50, + 0x7E, 0x22, 0x00, 0x06, 0x90, 0x00, 0xE2, 0x00, 0x06, 0xA8, 0x00, 0xF2, + 0x00, 0x06, 0xD0, 0x84, 0x20, 0x00, 0x06, 0xC8, 0x85, 0x22, 0x00, 0x06, + 0xB8, 0x84, 0x34, 0x00, 0x06, 0xB0, 0x85, 0x22, 0x00, 0x06, 0x90, 0x81, + 0x22, 0x00, 0x06, 0x88, 0x82, 0x22, 0x00, 0x06, 0x80, 0x83, 0x22, 0x00, + 0x06, 0xC0, 0x00, 0xE2, 0x00, 0x06, 0xD8, 0x00, 0xF2, 0x00, 0x07, 0x00, + 0x89, 0x20, 0x00, 0x06, 0xF8, 0x8A, 0x22, 0x00, 0x06, 0xE8, 0x89, 0x34, + 0x00, 0x06, 0xE0, 0x8A, 0x22, 0x00, 0x06, 0xC0, 0x86, 0x22, 0x00, 0x06, + 0xB8, 0x87, 0x22, 0x00, 0x06, 0xB0, 0x88, 0x22, 0x00, 0x06, 0xF0, 0x00, + 0xE2, 0x00, 0x07, 0x08, 0x00, 0xF2, 0x00, 0x07, 0x30, 0x8E, 0x20, 0x00, + 0x07, 0x28, 0x8F, 0x22, 0x00, 0x07, 0x18, 0x8E, 0x34, 0x00, 0x07, 0x10, + 0x8F, 0x22, 0x00, 0x06, 0xF0, 0x8B, 0x22, 0x00, 0x06, 0xE8, 0x8C, 0x22, + 0x00, 0x06, 0xE0, 0x8D, 0x22, 0x00, 0x07, 0x20, 0x00, 0xE2, 0x00, 0x07, + 0x38, 0x00, 0xF2, 0x00, 0x7F, 0xE0, 0x92, 0x20, 0x00, 0x7F, 0xE0, 0x91, + 0x34, 0x00, 0x7F, 0xE8, 0x90, 0x22, 0x00, 0xFF, 0xD8, 0x91, 0x02, 0x00, + 0xFF, 0xD8, 0x92, 0x12, 0x00, 0x05, 0xE8, 0x91, 0x20, 0x00, 0x07, 0x40, + 0x00, 0xE2, 0x00, 0x7F, 0xF0, 0x95, 0x20, 0x00, 0x7F, 0xF0, 0x94, 0x34, + 0x00, 0x7F, 0xF8, 0x93, 0x22, 0x00, 0xFF, 0xD8, 0x94, 0x02, 0x00, 0xFF, + 0xD8, 0x95, 0x12, 0x00, 0x07, 0x20, 0x94, 0x20, 0x00, 0x07, 0x48, 0x00, + 0xE2, 0x00, 0xFF, 0xE8, 0xC1, 0x40, 0x00, 0x07, 0x40, 0x00, 0xC0, 0x00, + 0x07, 0x47, 0xFF, 0x20, 0x00, 0x07, 0xB0, 0x00, 0xE2, 0x00, 0x07, 0xB8, + 0x00, 0xF2, 0x00, 0x07, 0x45, 0x0C, 0x20, 0x00, 0x07, 0xD8, 0x00, 0xE2, + 0x00, 0x07, 0xD8, 0x00, 0xC0, 0x00, 0x07, 0xDF, 0xFF, 0x20, 0x00, 0x07, + 0xD8, 0x00, 0xE2, 0x00, 0x07, 0xE5, 0x08, 0x20, 0x00, 0x07, 0xE0, 0xBE, + 0x22, 0x40, 0x07, 0xD8, 0xBE, 0x22, 0x08, 0x07, 0xE8, 0x00, 0xE2, 0x00, + 0x07, 0x6D, 0x08, 0x20, 0x00, 0x07, 0x68, 0xBE, 0x22, 0x40, 0x07, 0xB8, + 0xBE, 0x22, 0x00, 0x07, 0x5D, 0x08, 0x34, 0x00, 0x07, 0x58, 0xBE, 0x22, + 0x40, 0x07, 0xB0, 0xBE, 0x22, 0x00, 0x07, 0x60, 0x00, 0xE2, 0x00, 0xFF, + 0xF5, 0x08, 0x42, 0x00, 0x07, 0x70, 0x00, 0xF2, 0x00, 0x07, 0xED, 0x08, + 0x20, 0x00, 0xFF, 0xF5, 0x08, 0x82, 0x00, 0xFF, 0xF5, 0x08, 0x84, 0x23, + 0xFF, 0xED, 0x0A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, + 0x00, 0xF6, 0x00, 0x07, 0xF5, 0x08, 0x22, 0x00, 0x07, 0xC0, 0x00, 0xE2, + 0x00, 0x07, 0xC0, 0x00, 0xF6, 0x23, 0x07, 0x8D, 0x08, 0x20, 0x08, 0x07, + 0x90, 0x00, 0xE2, 0x00, 0x07, 0x7D, 0x08, 0x20, 0x00, 0xFF, 0xE8, 0xC0, + 0x22, 0x67, 0x07, 0x80, 0x00, 0xE2, 0x00, 0x07, 0xC5, 0x08, 0x22, 0x48, + 0x07, 0xC5, 0x08, 0x20, 0x00, 0x07, 0x80, 0x00, 0xE2, 0x27, 0xFF, 0xE8, + 0xBF, 0x20, 0x00, 0x07, 0x90, 0x00, 0xE2, 0x27, 0x07, 0x95, 0x08, 0x20, + 0x08, 0xFF, 0xFD, 0x08, 0x22, 0x40, 0x07, 0x90, 0x00, 0xE2, 0x26, 0x07, + 0x85, 0x1A, 0x20, 0x00, 0x07, 0xC8, 0x00, 0xE2, 0x00, 0x07, 0xD0, 0x00, + 0xF2, 0x00, 0x07, 0xC8, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0xA1, 0x00, 0xFF, 0xE5, + 0x08, 0x20, 0x00, 0x00, 0x00, 0x96, 0xA1, 0x00, 0xFF, 0xE5, 0x08, 0x22, + 0x40, 0x07, 0x98, 0x00, 0xE2, 0x00, 0x07, 0xD0, 0x00, 0xC0, 0x00, 0x07, + 0x9F, 0xFF, 0x20, 0x00, 0xFF, 0xE5, 0x08, 0x22, 0x00, 0x07, 0xA8, 0x00, + 0xE2, 0x00, 0x07, 0xA8, 0x00, 0xC0, 0x00, 0x07, 0x47, 0xFF, 0x20, 0x00, + 0x07, 0x50, 0x00, 0xE2, 0x00, 0x07, 0x48, 0xC2, 0x20, 0x00, 0x07, 0xF8, + 0x00, 0xE2, 0x00, 0xFF, 0xE8, 0xEE, 0x40, 0x00, 0x07, 0x50, 0x00, 0xC0, + 0x00, 0x07, 0x57, 0xFF, 0x20, 0x00, 0x08, 0x60, 0x00, 0xE2, 0x00, 0x08, + 0x68, 0x00, 0xF2, 0x00, 0x07, 0x55, 0x0C, 0x20, 0x00, 0x08, 0x88, 0x00, + 0xE2, 0x00, 0x08, 0x88, 0x00, 0xC0, 0x00, 0x08, 0x8F, 0xFF, 0x20, 0x00, + 0x08, 0x88, 0x00, 0xE2, 0x00, 0x08, 0x95, 0x08, 0x20, 0x00, 0x08, 0x90, + 0xEB, 0x22, 0x40, 0x08, 0x88, 0xEB, 0x22, 0x08, 0x08, 0x98, 0x00, 0xE2, + 0x00, 0x08, 0x1D, 0x08, 0x20, 0x00, 0x08, 0x18, 0xEB, 0x22, 0x40, 0x08, + 0x68, 0xEB, 0x22, 0x00, 0x08, 0x0D, 0x08, 0x34, 0x00, 0x08, 0x08, 0xEB, + 0x22, 0x40, 0x08, 0x60, 0xEB, 0x22, 0x00, 0x08, 0x10, 0x00, 0xE2, 0x00, + 0xFF, 0xF5, 0x08, 0x42, 0x00, 0x08, 0x20, 0x00, 0xF2, 0x00, 0x08, 0x9D, + 0x08, 0x20, 0x00, 0xFF, 0xF5, 0x08, 0x82, 0x00, 0xFF, 0xF5, 0x08, 0x84, + 0x23, 0xFF, 0xED, 0x0A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0xA0, 0x00, 0xF6, 0x00, 0x08, 0xA5, 0x08, 0x22, 0x00, 0x08, 0x70, 0x00, + 0xE2, 0x00, 0x08, 0x70, 0x00, 0xF6, 0x23, 0x08, 0x3D, 0x08, 0x20, 0x08, + 0x08, 0x40, 0x00, 0xE2, 0x00, 0x08, 0x2D, 0x08, 0x20, 0x00, 0xFF, 0xE8, + 0xED, 0x22, 0x67, 0x08, 0x30, 0x00, 0xE2, 0x00, 0x08, 0x75, 0x08, 0x22, + 0x48, 0x08, 0x75, 0x08, 0x20, 0x00, 0x08, 0x30, 0x00, 0xE2, 0x27, 0xFF, + 0xE8, 0xEC, 0x20, 0x00, 0x08, 0x40, 0x00, 0xE2, 0x27, 0x08, 0x45, 0x08, + 0x20, 0x08, 0xFF, 0xFD, 0x08, 0x22, 0x40, 0x08, 0x40, 0x00, 0xE2, 0x26, + 0x08, 0x35, 0x1A, 0x20, 0x00, 0x08, 0x78, 0x00, 0xE2, 0x00, 0x08, 0x80, + 0x00, 0xF2, 0x00, 0x08, 0x78, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0xA1, 0x00, 0xFF, + 0xE5, 0x08, 0x20, 0x00, 0x00, 0x00, 0xC3, 0xA1, 0x00, 0xFF, 0xE5, 0x08, + 0x22, 0x40, 0x08, 0x48, 0x00, 0xE2, 0x00, 0x08, 0x80, 0x00, 0xC0, 0x00, + 0x08, 0x4F, 0xFF, 0x20, 0x00, 0xFF, 0xE5, 0x08, 0x22, 0x00, 0x08, 0x58, + 0x00, 0xE2, 0x00, 0x08, 0x58, 0x00, 0xC0, 0x00, 0x07, 0x57, 0xFF, 0x20, + 0x00, 0x08, 0x00, 0x00, 0xE2, 0x00, 0xFF, 0xE9, 0x1A, 0x40, 0x00, 0x07, + 0xF8, 0x00, 0xC0, 0x00, 0x07, 0xFF, 0xFF, 0x20, 0x00, 0x09, 0x00, 0x00, + 0xE2, 0x00, 0x09, 0x08, 0x00, 0xF2, 0x00, 0x07, 0xFD, 0x0C, 0x20, 0x00, + 0x09, 0x28, 0x00, 0xE2, 0x00, 0x09, 0x28, 0x00, 0xC0, 0x00, 0x09, 0x2F, + 0xFF, 0x20, 0x00, 0x09, 0x28, 0x00, 0xE2, 0x00, 0x09, 0x35, 0x08, 0x20, + 0x00, 0x09, 0x31, 0x17, 0x22, 0x40, 0x09, 0x29, 0x17, 0x22, 0x08, 0x09, + 0x38, 0x00, 0xE2, 0x00, 0x08, 0xBD, 0x08, 0x20, 0x00, 0x08, 0xB9, 0x17, + 0x22, 0x40, 0x09, 0x09, 0x17, 0x22, 0x00, 0x08, 0xAD, 0x08, 0x34, 0x00, + 0x08, 0xA9, 0x17, 0x22, 0x40, 0x09, 0x01, 0x17, 0x22, 0x00, 0x08, 0xB0, + 0x00, 0xE2, 0x00, 0xFF, 0xF5, 0x08, 0x42, 0x00, 0x08, 0xC0, 0x00, 0xF2, + 0x00, 0x09, 0x3D, 0x08, 0x20, 0x00, 0xFF, 0xF5, 0x08, 0x82, 0x00, 0xFF, + 0xF5, 0x08, 0x84, 0x23, 0xFF, 0xED, 0x0A, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x09, 0x40, 0x00, 0xF6, 0x00, 0x09, 0x45, 0x08, 0x22, 0x00, + 0x09, 0x10, 0x00, 0xE2, 0x00, 0x09, 0x10, 0x00, 0xF6, 0x23, 0x08, 0xDD, + 0x08, 0x20, 0x08, 0x08, 0xE0, 0x00, 0xE2, 0x00, 0x08, 0xCD, 0x08, 0x20, + 0x00, 0xFF, 0xE9, 0x19, 0x22, 0x67, 0x08, 0xD0, 0x00, 0xE2, 0x00, 0x09, + 0x15, 0x08, 0x22, 0x48, 0x09, 0x15, 0x08, 0x20, 0x00, 0x08, 0xD0, 0x00, + 0xE2, 0x27, 0xFF, 0xE9, 0x18, 0x20, 0x00, 0x08, 0xE0, 0x00, 0xE2, 0x27, + 0x08, 0xE5, 0x08, 0x20, 0x08, 0xFF, 0xFD, 0x08, 0x22, 0x40, 0x08, 0xE0, + 0x00, 0xE2, 0x26, 0x08, 0xD5, 0x1A, 0x20, 0x00, 0x09, 0x18, 0x00, 0xE2, + 0x00, 0x09, 0x20, 0x00, 0xF2, 0x00, 0x09, 0x18, 0x00, 0xC0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, + 0xA1, 0x00, 0xFF, 0xE5, 0x08, 0x20, 0x00, 0x00, 0x00, 0xEF, 0xA1, 0x00, + 0xFF, 0xE5, 0x08, 0x22, 0x40, 0x08, 0xE8, 0x00, 0xE2, 0x00, 0x09, 0x20, + 0x00, 0xC0, 0x00, 0x08, 0xEF, 0xFF, 0x20, 0x00, 0xFF, 0xE5, 0x08, 0x22, + 0x00, 0x08, 0xF8, 0x00, 0xE2, 0x00, 0x08, 0xF8, 0x00, 0xC0, 0x00, 0x07, + 0xFF, 0xFF, 0x20, 0x00, 0x09, 0x60, 0x00, 0xE2, 0x00, 0x08, 0x01, 0x1B, + 0x20, 0x00, 0x09, 0x48, 0x00, 0xE2, 0x00, 0x09, 0x89, 0x1F, 0x20, 0x00, + 0x09, 0x81, 0x20, 0x22, 0x00, 0x09, 0x71, 0x1F, 0x34, 0x00, 0x09, 0x69, + 0x20, 0x22, 0x00, 0x09, 0x61, 0x1C, 0x22, 0x00, 0x09, 0x59, 0x1D, 0x22, + 0x00, 0x09, 0x51, 0x1E, 0x22, 0x00, 0x09, 0x78, 0x00, 0xE2, 0x00, 0x09, + 0x90, 0x00, 0xF2, 0x00, 0x09, 0xB9, 0x24, 0x20, 0x00, 0x09, 0xB1, 0x25, + 0x22, 0x00, 0x09, 0xA1, 0x24, 0x34, 0x00, 0x09, 0x99, 0x25, 0x22, 0x00, + 0x09, 0x79, 0x21, 0x22, 0x00, 0x09, 0x71, 0x22, 0x22, 0x00, 0x09, 0x69, + 0x23, 0x22, 0x00, 0x09, 0xA8, 0x00, 0xE2, 0x00, 0x09, 0xC0, 0x00, 0xF2, + 0x00, 0x09, 0xE9, 0x29, 0x20, 0x00, 0x09, 0xE1, 0x2A, 0x22, 0x00, 0x09, + 0xD1, 0x29, 0x34, 0x00, 0x09, 0xC9, 0x2A, 0x22, 0x00, 0x09, 0xA9, 0x26, + 0x22, 0x00, 0x09, 0xA1, 0x27, 0x22, 0x00, 0x09, 0x99, 0x28, 0x22, 0x00, + 0x09, 0xD8, 0x00, 0xE2, 0x00, 0x09, 0xF0, 0x00, 0xF2, 0x00, 0x09, 0x4D, + 0x08, 0x20, 0x00, 0xFD, 0xB0, 0x00, 0xE2, 0x00, 0x09, 0xD9, 0x2B, 0x20, + 0x00, 0x09, 0xF8, 0x00, 0xE2, 0x00, 0x09, 0xFD, 0x08, 0x20, 0x00, 0xFD, + 0xB8, 0x00, 0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC0, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + +}; + +const unsigned char adau1761_init_arr_34[] = { + 0x00, 0x00, /* (34) Param */ + 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x87, 0x95, 0xA0, 0x00, 0x00, 0x08, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x0F, 0x02, 0x67, 0x53, 0x00, 0x7D, 0xA0, 0xAF, 0x00, 0xFD, 0x98, 0xAD, + 0x0F, 0x82, 0x5F, 0x51, 0x00, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x9E, 0x3D, + 0x00, 0x34, 0x25, 0x2B, 0x00, 0x7F, 0x61, 0xC3, 0x0F, 0xCB, 0xDA, 0xD5, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE7, 0x44, + 0x0F, 0x13, 0x71, 0x1C, 0x00, 0x70, 0x4A, 0x0B, 0x00, 0xEC, 0x8E, 0xE4, + 0x0F, 0x8E, 0xCE, 0xB1, 0x00, 0x7B, 0xD6, 0x6A, 0x0F, 0x71, 0xA0, 0xD2, + 0x00, 0x63, 0x1A, 0xDB, 0x00, 0x8E, 0x5F, 0x2E, 0x0F, 0xA1, 0x0E, 0xBB, + 0x00, 0x21, 0x51, 0x9D, 0x00, 0x42, 0xA3, 0x3A, 0x00, 0x21, 0x51, 0x9D, + 0x00, 0x26, 0xDF, 0xA6, 0x0F, 0xD3, 0xD9, 0xE5, 0x00, 0x7D, 0x61, 0xFE, + 0x0F, 0x05, 0x3C, 0x04, 0x00, 0x7D, 0x61, 0xFE, 0x00, 0xFA, 0xB2, 0x8B, + 0x0F, 0x85, 0x2A, 0x94, 0x00, 0x80, 0x50, 0xA2, 0x0F, 0x05, 0xB3, 0x1E, + 0x00, 0x7A, 0x85, 0xBD, 0x00, 0xFA, 0x4C, 0xE2, 0x0F, 0x85, 0x29, 0xA1, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x7F, 0x76, 0x6D, 0x0F, 0x01, 0x13, 0x27, + 0x00, 0x7F, 0x76, 0x6D, 0x00, 0xFE, 0xEC, 0x48, 0x0F, 0x81, 0x12, 0x96, + 0x00, 0x7F, 0x76, 0x6D, 0x0F, 0x01, 0x13, 0x27, 0x00, 0x7F, 0x76, 0x6D, + 0x00, 0xFE, 0xEC, 0x48, 0x0F, 0x81, 0x12, 0x96, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x0D, 0x16, 0x00, 0x00, 0x1A, 0x2D, 0x00, 0xF9, 0xD7, 0x21, + 0x00, 0x00, 0x0D, 0x16, 0x0F, 0x86, 0x03, 0xCF, 0x00, 0x00, 0x09, 0x44, + 0x00, 0x00, 0x12, 0x88, 0x00, 0xF9, 0xD7, 0x21, 0x00, 0x00, 0x09, 0x44, + 0x0F, 0x86, 0x03, 0xCF, 0x00, 0x4E, 0xEA, 0x47, 0x0F, 0x62, 0x2B, 0x72, + 0x00, 0xFA, 0x13, 0xC2, 0x00, 0x4E, 0xEA, 0x47, 0x0F, 0x85, 0xC9, 0xF2, + 0x00, 0x7D, 0x12, 0x74, 0x0F, 0x05, 0xDB, 0x18, 0x00, 0xFA, 0x13, 0xC2, + 0x00, 0x7D, 0x12, 0x74, 0x0F, 0x85, 0xC9, 0xF2, 0x00, 0x80, 0x1D, 0x97, + 0x0F, 0x00, 0xEC, 0x9F, 0x00, 0x7E, 0xFD, 0xD9, 0x00, 0xFF, 0x13, 0x61, + 0x0F, 0x80, 0xE4, 0x90, 0x00, 0x80, 0x50, 0x64, 0x0F, 0x00, 0xA5, 0x22, + 0x00, 0x7F, 0x0E, 0x0F, 0x00, 0xFF, 0x5A, 0xDE, 0x0F, 0x80, 0xA1, 0x8D, + 0x00, 0x80, 0x8B, 0x50, 0x0F, 0x06, 0x4F, 0x3C, 0x00, 0x79, 0xAE, 0x9C, + 0x00, 0xF9, 0xB0, 0xC4, 0x0F, 0x85, 0xC6, 0x15, 0x00, 0x80, 0x7E, 0xBB, + 0x0F, 0x03, 0xF8, 0x4B, 0x00, 0x7B, 0xAE, 0x5C, 0x00, 0xFC, 0x07, 0xB5, + 0x0F, 0x83, 0xD2, 0xE9, 0x00, 0x99, 0x7D, 0xD0, 0x0F, 0xA2, 0x18, 0x34, + 0x00, 0x3A, 0xCB, 0x2A, 0x00, 0x37, 0x9D, 0x8E, 0x0F, 0xD2, 0x01, 0x44, + 0x00, 0x7D, 0x06, 0xB4, 0x0F, 0x35, 0xAB, 0x24, 0x00, 0x66, 0x0E, 0x45, + 0x00, 0xCA, 0x54, 0xDC, 0x0F, 0x9C, 0xEB, 0x07, 0x00, 0x84, 0xFA, 0x80, + 0x0F, 0x7B, 0x91, 0x2F, 0x00, 0x54, 0x90, 0xF6, 0x00, 0x84, 0x6E, 0xD1, + 0x0F, 0xA6, 0x74, 0x89, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x94, 0xC5, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x94, 0xC5, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x74, 0xA8, 0xB6, + 0x00, 0x5F, 0x3E, 0x5E, 0x00, 0x47, 0x4B, 0xE9, 0x00, 0x32, 0xF5, 0x1E, + 0x00, 0x24, 0x13, 0x47, 0x00, 0x19, 0x82, 0x54, 0x00, 0x12, 0x09, 0xA3, + 0x00, 0x0C, 0xC1, 0x2A, 0x00, 0x09, 0x04, 0xD2, 0x00, 0x06, 0x60, 0x95, + 0x00, 0x04, 0x82, 0x69, 0x00, 0x00, 0x01, 0x6A, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x51, 0xEC, 0x0F, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x7B, 0x31, 0x33, + 0x00, 0x69, 0x82, 0xC9, 0x00, 0x51, 0x87, 0x68, 0x00, 0x3B, 0x86, 0x20, + 0x00, 0x2A, 0xE0, 0x26, 0x00, 0x1E, 0x51, 0x4F, 0x00, 0x15, 0x70, 0x13, + 0x00, 0x0F, 0x28, 0xA7, 0x00, 0x0A, 0xB8, 0x09, 0x00, 0x07, 0x94, 0x54, + 0x00, 0x05, 0x5C, 0x05, 0x00, 0x00, 0x1B, 0x5D, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x9E, 0x00, 0x00, 0x51, 0xEC, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x72, 0x15, 0x9E, + 0x00, 0x5D, 0x53, 0xC3, 0x00, 0x46, 0x9A, 0xB6, 0x00, 0x32, 0xEA, 0xCB, + 0x00, 0x24, 0x13, 0x47, 0x00, 0x19, 0x8A, 0x13, 0x00, 0x12, 0x14, 0x9A, + 0x00, 0x0C, 0xC8, 0xEB, 0x00, 0x09, 0x0A, 0x4D, 0x00, 0x06, 0x64, 0x75, + 0x00, 0x04, 0x85, 0x27, 0x00, 0x03, 0x32, 0x3B, 0x00, 0x02, 0x42, 0x93, + 0x00, 0x01, 0x12, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x8B, + 0x00, 0x00, 0x51, 0xEC, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, +}; + +const unsigned char adau1761_init_arr_35[] = { + 0x1F, 0xFC, /* (35) Non Modulo RAM */ + 0x00, 0x7F, 0xF2, 0x59, 0x00, 0x00, 0x0D, 0xA7, + 0x00, 0x7F, 0xF2, 0x59, 0x00, 0x00, 0x0D, 0xA7, +}; + +const unsigned char adau1761_init_arr_36[] = { + 0x40, + 0xEB, /* (36) IC 1.Sample Rate Setting */ + 0x01, +}; + +const unsigned char adau1761_init_arr_37[] = { + 0x40, + 0xF6, /* (37) IC 1.DSP Run Register */ + 0x01, +}; + +const unsigned char adau1761_init_arr_38[] = { + 0x40, + 0x36, /* (38) IC 1.Dejitter Register Control */ + 0x00, +}; + +const unsigned char adau1761_init_arr_39[] = { + 0x40, + 0x36, /* (39) IC 1.Dejitter Register Control */ + 0x03, +}; + +typedef struct { + const unsigned char *p_arr; + unsigned int byte_len; +} adau1761_init_matrix; + +const adau1761_init_matrix adau1761_init_matrix_arr[] = { + {adau1761_init_arr_00, sizeof(adau1761_init_arr_00)}, + {adau1761_init_arr_01, sizeof(adau1761_init_arr_01)}, + {adau1761_init_arr_02, sizeof(adau1761_init_arr_02)}, + {adau1761_init_arr_03, sizeof(adau1761_init_arr_03)}, + {adau1761_init_arr_04, sizeof(adau1761_init_arr_04)}, + {adau1761_init_arr_05, sizeof(adau1761_init_arr_05)}, + {adau1761_init_arr_06, sizeof(adau1761_init_arr_06)}, + {adau1761_init_arr_07, sizeof(adau1761_init_arr_07)}, + {adau1761_init_arr_08, sizeof(adau1761_init_arr_08)}, + {adau1761_init_arr_09, sizeof(adau1761_init_arr_09)}, + {adau1761_init_arr_10, sizeof(adau1761_init_arr_10)}, + {adau1761_init_arr_11, sizeof(adau1761_init_arr_11)}, + {adau1761_init_arr_12, sizeof(adau1761_init_arr_12)}, + {adau1761_init_arr_13, sizeof(adau1761_init_arr_13)}, + {adau1761_init_arr_14, sizeof(adau1761_init_arr_14)}, + {adau1761_init_arr_15, sizeof(adau1761_init_arr_15)}, + {adau1761_init_arr_16, sizeof(adau1761_init_arr_16)}, + {adau1761_init_arr_17, sizeof(adau1761_init_arr_17)}, + {adau1761_init_arr_18, sizeof(adau1761_init_arr_18)}, + {adau1761_init_arr_19, sizeof(adau1761_init_arr_19)}, + {adau1761_init_arr_20, sizeof(adau1761_init_arr_20)}, + {adau1761_init_arr_21, sizeof(adau1761_init_arr_21)}, + {adau1761_init_arr_22, sizeof(adau1761_init_arr_22)}, + {adau1761_init_arr_23, sizeof(adau1761_init_arr_23)}, + {adau1761_init_arr_24, sizeof(adau1761_init_arr_24)}, + {adau1761_init_arr_25, sizeof(adau1761_init_arr_25)}, + {adau1761_init_arr_26, sizeof(adau1761_init_arr_26)}, + {adau1761_init_arr_27, sizeof(adau1761_init_arr_27)}, + {adau1761_init_arr_28, sizeof(adau1761_init_arr_28)}, + {adau1761_init_arr_29, sizeof(adau1761_init_arr_29)}, + {adau1761_init_arr_30, sizeof(adau1761_init_arr_30)}, + {adau1761_init_arr_31, sizeof(adau1761_init_arr_31)}, + {adau1761_init_arr_32, sizeof(adau1761_init_arr_32)}, + {adau1761_init_arr_33, sizeof(adau1761_init_arr_33)}, + {adau1761_init_arr_34, sizeof(adau1761_init_arr_34)}, + {adau1761_init_arr_35, sizeof(adau1761_init_arr_35)}, + {adau1761_init_arr_36, sizeof(adau1761_init_arr_36)}, + {adau1761_init_arr_37, sizeof(adau1761_init_arr_37)}, + {adau1761_init_arr_38, sizeof(adau1761_init_arr_38)}, + {adau1761_init_arr_39, sizeof(adau1761_init_arr_39)}}; + +#define ADAU1761_INIT_ARR_COUNT \ + (sizeof(adau1761_init_matrix_arr) / sizeof(adau1761_init_matrix)) + +struct vol_table { + int vtable_step; + float volgain_db; + uint8_t ram_word[4]; +}; + +/* 2dB step */ +static const struct vol_table adau1761_vol_table[] = { + {20, 0, {0x00, 0x80, 0x00, 0x00}}, {19, -1, {0x00, 0x72, 0x14, 0x7B}}, + {18, -2, {0x00, 0x65, 0xAC, 0x8C}}, {17, -3, {0x00, 0x5A, 0x9D, 0xF8}}, + {16, -4, {0x00, 0x50, 0xC3, 0x36}}, {15, -6, {0x00, 0x40, 0x26, 0xE7}}, + {14, -8, {0x00, 0x32, 0xF5, 0x2D}}, {13, -10, {0x00, 0x28, 0x7A, 0x27}}, + {12, -12, {0x00, 0x20, 0x26, 0xF3}}, {11, -14, {0x00, 0x19, 0x8A, 0x13}}, + {10, -16, {0x00, 0x14, 0x49, 0x61}}, {9, -20, {0x00, 0x0C, 0xCC, 0xCD}}, + {8, -24, {0x00, 0x08, 0x13, 0x85}}, {7, -28, {0x00, 0x05, 0x5E, 0x7F}}, + {6, -32, {0x00, 0x03, 0x37, 0x18}}, {5, -36, {0x00, 0x02, 0x07, 0x56}}, + {4, -40, {0x00, 0x01, 0x47, 0xAE}}, {3, -44, {0x00, 0x00, 0xCE, 0xC1}}, + {2, -52, {0x00, 0x00, 0x52, 0x4F}}, {1, -60, {0x00, 0x00, 0x20, 0xC5}}, + {0, -80, {0x00, 0x00, 0x03, 0x47}}, +}; + +#define VOL_STEP_NUM (sizeof(adau1761_vol_table) / sizeof(struct vol_table)) +#define MAX_VOL_STEP (VOL_STEP_NUM - 1) + +const u8 src_analog_arr[] = {0x00, 0x00, 0x00, 0x00}; +const u8 src_dig_arr[] = {0x00, 0x00, 0x00, 0x01}; + +const unsigned char adau1761_eq1_normal[] = {0x00, 0x00, 0x00, 0x00}; + +const unsigned char adau1761_eq1_decrease[] = {0x00, 0x00, 0x00, 0x01}; + +const unsigned char adau1761_eq2_improve[] = {0x00, 0x00, 0x00, 0x02}; + +// io commands +#define MAGIC_NUM 'A' +#define ADAU1761_CMD_VOL_SET _IOW(MAGIC_NUM, 0, int) +#define ADAU1761_CMD_VOL_GET _IOR(MAGIC_NUM, 1, int) +#define ADAU1761_CMD_AMP_MUTE_SET _IOW(MAGIC_NUM, 2, int) +#define ADAU1761_CMD_AMP_MUTE_GET _IOR(MAGIC_NUM, 3, int) +#define ADAU1761_CMD_SRC_SET _IOW(MAGIC_NUM, 4, int) +#define ADAU1761_CMD_SRC_GET _IOR(MAGIC_NUM, 5, int) +#define ADAU1761_CMD_FW_LOAD _IOW(MAGIC_NUM, 6, int) +#define ADAU1761_CMD_EQ_SET _IOW(MAGIC_NUM, 7, int) + +#define ADAU1761_CMD_MAX (7) + +struct adau1761_priv_data { + struct i2c_client *i2c_client; + u8 i2c_ch; + u8 vol; + u8 is_mute; + u8 src; // 0-analog, 1-i2s +}; + +static int default_pwm_freq = 24576000; // 24.576 default +static struct pwm_device *pwm_dev[2]; +static int duty_ns; +static int period_ns; +static int polarity = 0; +/*for pa sdz gpio ctrl*/ +static int pa_sdz_item; +/*for pa mute gpio ctrl*/ +static int pa_mute_item; + +static DEFINE_MUTEX(adau1761_mutex); +static struct adau1761_priv_data adau1761_priv; + +static inline u32 sigma_action_len(struct sigma_action *sa) { + return (le32_to_cpu(sa->len)); +} + +static size_t sigma_action_size(struct sigma_action *sa) { + size_t payload = 0; + + switch (le32_to_cpu(sa->ind)) { + case SIGMA_ACTION_WRITEXBYTES: + case SIGMA_ACTION_CONTROL: + payload = sigma_action_len(sa); + break; + + default: + break; + } + + return payload; +} + +/* + * Returns a negative error value in case of an error, 0 if processing of + * the firmware should be stopped after this action, 1 otherwise. + */ +static int process_sigma_action(struct sigma_firmware *ssfw, + struct sigma_action *sa) { + size_t len = sigma_action_len(sa); + u16 addr; + int ret; + + DSP_DEBUG("%s: len:%d ind:%#x\n", __func__, len, le32_to_cpu(sa->ind)); + + switch (le32_to_cpu(sa->ind)) { + case SIGMA_ACTION_WRITEXBYTES: + if (len <= sizeof(struct sigma_action) + 2) { + pr_debug("%s: short length in SIGMA_ACTION_WRITEXBYTES!\n", + __func__); + return -EINVAL; + } + + len = len - sizeof(struct sigma_action); + addr = *(const u16 *)(ssfw->fw->data + ssfw->pos + + sizeof(struct sigma_action)); + DSP_DEBUG("%s: addr:%#x\n", __func__, addr); + + if ((addr == 0) && (len == 4)) { + msleep(100); + } else { + ret = i2c_master_send(adau1761_priv.i2c_client, + (const char *)(ssfw->fw->data + ssfw->pos + + sizeof(struct sigma_action)), + len); + if (ret < 0) + return -EINVAL; + } + break; + + case SIGMA_ACTION_CONTROL: + return 0; + + default: + return -EINVAL; + } + + return 1; +} + +static int process_sigma_actions(struct sigma_firmware *ssfw) { + struct sigma_action *sa; + size_t size; + int ret; + + while (ssfw->pos < ssfw->fw->size) { + sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos); + size = sigma_action_size(sa); + + if (size == 0) + break; + + ret = process_sigma_action(ssfw, sa); + + DSP_DEBUG("%s: action returned %i\n", __func__, ret); + + if (ret <= 0) + return ret; + + size = ALIGN(size, 4); + ssfw->pos += size; + } + + return 0; +} + +static int _process_sigma_firmware(struct device *dev, + struct sigma_firmware *ssfw, + const char *name) { + int ret; + struct sigma_firmware_header *ssfw_head; + const struct firmware *fw; + u32 crc; + + DSP_DEBUG("%s: loading firmware %s\n", __func__, name); + + /* first load the blob */ + ret = request_firmware(&fw, name, dev); + if (ret) { + pr_debug("%s: request_firmware() failed with %i\n", __func__, ret); + return ret; + } + ssfw->fw = fw; + + /* then verify the header */ + ret = -EINVAL; + + /* + * Reject too small or unreasonable large files. The upper limit has been + * chosen a bit arbitrarily, but it should be enough for all practical + * purposes and having the limit makes it easier to avoid integer + * overflows later in the loading process. + */ + if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000) { + dev_err(dev, "Failed to load firmware: Invalid size\n"); + goto done; + } + + ssfw_head = (void *)fw->data; + if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic))) { + dev_err(dev, "Failed to load firmware: Invalid magic\n"); + goto done; + } + + crc = + crc32(0, fw->data + sizeof(*ssfw_head), fw->size - sizeof(*ssfw_head)); + DSP_DEBUG("%s: crc=%x\n", __func__, crc); + + if (crc != le32_to_cpu(ssfw_head->crc)) { + dev_err( + dev, + "Failed to load firmware: Wrong crc checksum: expected %x got %x\n", + le32_to_cpu(ssfw_head->crc), crc); + goto done; + } + + ssfw->pos = sizeof(*ssfw_head) + sizeof(struct sigma_samprate_list); + + /* finally process all of the actions */ + ret = process_sigma_actions(ssfw); + +done: + release_firmware(fw); + + DSP_DEBUG("%s: loaded %s\n", __func__, name); + + return ret; +} + +int process_sigma_firmware(struct i2c_client *client, const char *name) { + struct sigma_firmware ssfw; + + ssfw.control_data = client; + + return _process_sigma_firmware(&client->dev, &ssfw, name); +} + +static void pwm_init(int pwm_ch) { + char pwm_name[10]; + sprintf(pwm_name, "pwm_%d", pwm_ch); + + pwm_dev[pwm_ch] = pwm_request(pwm_ch, pwm_name); + if (NULL == pwm_dev[pwm_ch] || IS_ERR(pwm_dev[pwm_ch])) { + DSP_DEBUG("OSAL_Pwm_request pwm fail!\n"); + } + + pwm_set_polarity(pwm_dev[pwm_ch], polarity); + + period_ns = 1000000000 / default_pwm_freq; + + duty_ns = (128 * period_ns) / 256; + + pwm_config(pwm_dev[pwm_ch], duty_ns, period_ns); +} + +static int adau1761_safe_load(uint8_t *word_arr, unsigned int word_num, + unsigned int target_addr) { + uint8_t temp_arr[SAFE_LOAD_REG_NUM * 4 + 2]; + int cnt, ret = 0; + + if (word_num > SAFE_LOAD_WORD_NUM_MAX) { + DSP_DEBUG("safe_load: > 5 words!\n"); + ret = -1; + + return ret; + } + + if (word_arr == NULL) { + DSP_DEBUG("safe_load: word_arr == NULL!\n"); + ret = -1; + + return ret; + } + + if (target_addr < 1) { + DSP_DEBUG("safe_load: target_addr < 1!\n"); + ret = -1; + + return ret; + } + + /* fill with zero */ + memset(temp_arr, 0, sizeof(temp_arr)); + + /* safeload register */ + temp_arr[0] = (uint8_t)((SAFE_LOAD_DATA_1_REG >> 8) & 0xFF); + temp_arr[1] = (uint8_t)(SAFE_LOAD_DATA_1_REG & 0xFF); + + /* fill with data */ + for (cnt = 0; cnt < word_num * 4; cnt++) { + temp_arr[cnt + 2] = word_arr[cnt]; + } + + /* target addr */ + cnt = (SAFE_LOAD_TARGET_ADDR_REG - SAFE_LOAD_DATA_1_REG) * 4 + 4; + target_addr = target_addr - 1; + temp_arr[cnt] = (unsigned char)((target_addr >> 8) & 0xFF); + cnt++; + temp_arr[cnt] = (unsigned char)(target_addr & 0xFF); + + /* word number */ + cnt = (SAFE_LOAD_WORD_NUM_REG - SAFE_LOAD_DATA_1_REG) * 4 + 5; + temp_arr[cnt] = (unsigned char)(word_num & 0xFF); + + /* burst transfer */ + cnt = SAFE_LOAD_REG_NUM * 4 + 2; + ret = + i2c_master_send(adau1761_priv.i2c_client, (const char *)temp_arr, cnt); + return ret; +} + +/* + * Change EQ when system operating + * input: int arg + * output: int ret + */ +static int adau1761_safe_load_new_eq(unsigned long arg) { + unsigned int i; + int ret = -1; + gpio_set_value(pa_mute_item, 1); + if (arg == 0) { + ret = adau1761_safe_load((uint8_t *)(&adau1761_eq1_normal[0]), 1, + SAFE_LOAD_EQ_SWITCH_REG); + } else if (arg == 1) { + ret = adau1761_safe_load((uint8_t *)(&adau1761_eq1_decrease[0]), 1, + SAFE_LOAD_EQ_SWITCH_REG); + } else if (arg == 2) { + ret = adau1761_safe_load((uint8_t *)(&adau1761_eq2_improve[0]), 1, + SAFE_LOAD_EQ_SWITCH_REG); + } else { + DSP_DEBUG("failed to load adau1761_new_EQ: out range\n"); + } + gpio_set_value(pa_mute_item, 0); + return ret; +} + +static unsigned int adau1761_register_size(unsigned int reg) { + switch (reg) { + case ADAU1761_DIGMIC_JACKDETECT: + case ADAU1761_REC_MIXER_LEFT0: + case ADAU1761_REC_MIXER_LEFT1: + case ADAU1761_REC_MIXER_RIGHT0: + case ADAU1761_REC_MIXER_RIGHT1: + case ADAU1761_LEFT_DIFF_INPUT_VOL: + case ADAU1761_RIGHT_DIFF_INPUT_VOL: + case ADAU1761_PLAY_LR_MIXER_LEFT: + case ADAU1761_PLAY_MIXER_LEFT0: + case ADAU1761_PLAY_MIXER_LEFT1: + case ADAU1761_PLAY_MIXER_RIGHT0: + case ADAU1761_PLAY_MIXER_RIGHT1: + case ADAU1761_PLAY_LR_MIXER_RIGHT: + case ADAU1761_PLAY_MIXER_MONO: + case ADAU1761_PLAY_HP_LEFT_VOL: + case ADAU1761_PLAY_HP_RIGHT_VOL: + case ADAU1761_PLAY_LINE_LEFT_VOL: + case ADAU1761_PLAY_LINE_RIGHT_VOL: + case ADAU1761_PLAY_MONO_OUTPUT_VOL: + case ADAU1761_POP_CLICK_SUPPRESS: + case ADAU1761_JACK_DETECT_PIN: + case ADAU1761_DEJITTER: + case ADAU1761_CLK_ENABLE0: + case ADAU1761_CLK_ENABLE1: + case ADAU17X1_CLOCK_CONTROL: + case ADAU17X1_PLL_CONTROL: + case ADAU17X1_REC_POWER_MGMT: + case ADAU17X1_MICBIAS: + case ADAU17X1_SERIAL_PORT0: + case ADAU17X1_SERIAL_PORT1: + case ADAU17X1_CONVERTER0: + case ADAU17X1_CONVERTER1: + case ADAU17X1_LEFT_INPUT_DIGITAL_VOL: + case ADAU17X1_RIGHT_INPUT_DIGITAL_VOL: + case ADAU17X1_ADC_CONTROL: + case ADAU17X1_PLAY_POWER_MGMT: + case ADAU17X1_DAC_CONTROL0: + case ADAU17X1_DAC_CONTROL1: + case ADAU17X1_DAC_CONTROL2: + case ADAU17X1_SERIAL_PORT_PAD: + case ADAU17X1_CONTROL_PORT_PAD0: + case ADAU17X1_CONTROL_PORT_PAD1: + case ADAU17X1_DSP_SAMPLING_RATE: + case ADAU17X1_SERIAL_INPUT_ROUTE: + case ADAU17X1_SERIAL_OUTPUT_ROUTE: + case ADAU17X1_DSP_ENABLE: + case ADAU17X1_DSP_RUN: + case ADAU17X1_SERIAL_SAMPLING_RATE: + return 1; + + default: + if ((reg > ADAU1761_DATA_PARAM_START_ADDR) && + (reg <= ADAU1761_DATA_PARAM_END_ADDR)) { + return 4; + } else { // do not support program RAM + DSP_DEBUG("register_size: Unsupported register address: %d\n", reg); + + return 0; + } + } +} + +static unsigned int adau1761_read(unsigned int reg) { + unsigned int i; + unsigned int size; + uint8_t buf[4]; + int ret; + + size = adau1761_register_size(reg); + if (size == 0) { + return 0; + } + + buf[0] = (uint8_t)((reg >> 8) && 0xFF); + buf[1] = (uint8_t)(reg && 0xFF); + + ret = i2c_master_send(adau1761_priv.i2c_client, buf, 2); + + if (ret < 0) { + i = (unsigned int)ret; + + return i; + } else if (ret != size + 2) { + i = (unsigned int)(-EIO); + + return i; + } + + ret = i2c_master_recv(adau1761_priv.i2c_client, buf, size); + + if (ret != size) { + i = (unsigned int)(-EIO); + + return i; + } else { + ret = 0; + + for (i = 0; i < size; i++) { + ret += buf[i]; + ret <<= 8; + } + + i = (uint32_t)ret; + + return i; + } +} + +static int adau1761_write(unsigned int reg, unsigned int value) { + unsigned int i; + unsigned int size; + uint8_t buf[4]; + int ret; + + size = adau1761_register_size(reg); + if (size == 0) { + return -EINVAL; + } + + buf[0] = (uint8_t)((reg >> 8) && 0xFF); + buf[1] = (uint8_t)(reg && 0xFF); + + for (i = size + 1; i > 1; --i) { + buf[i] = (uint8_t)(value && 0xFF); + value >>= 8; + } + + ret = i2c_master_send(adau1761_priv.i2c_client, buf, size + 2); + + if (ret == size + 2) { + return 0; + } else if (ret < 0) { + return ret; + } else { + return -EIO; + } +} + +int adau1761_open(struct inode *inode, struct file *filep) { + int ret; + + DSP_DEBUG("open start\n"); + + mutex_lock(&adau1761_mutex); + ret = nonseekable_open(inode, filep); + mutex_unlock(&adau1761_mutex); + + return ret; +} + +int adau1761_release(struct inode *inode, struct file *filep) { + DSP_DEBUG("release start\n"); + + return 0; +} + +// file operations +static long adau1761_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { + u8 i; + int ret = 0; + + DSP_DEBUG("ioctl start cmd: %d arg: %lX\n", cmd, arg); + + if (_IOC_TYPE(cmd) != MAGIC_NUM) + return -EINVAL; + + if (_IOC_NR(cmd) > ADAU1761_CMD_MAX) + return -EINVAL; + + if (_IOC_DIR(cmd) & _IOC_READ) + ret = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd)); + if (_IOC_DIR(cmd) & _IOC_WRITE) + ret = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd)); + + if (ret) + return -EFAULT; + + DSP_DEBUG("ioctl start\n"); + + mutex_lock(&adau1761_mutex); + + DSP_DEBUG("ioctl lock\n"); + + switch (cmd) { + case ADAU1761_CMD_VOL_SET: { + if (arg > MAX_VOL_STEP) { + ret = -EINVAL; + goto failure; + } + + for (i = 0; i < VOL_STEP_NUM; i++) { + if (adau1761_vol_table[i].vtable_step == arg) { + adau1761_priv.vol = arg; + adau1761_safe_load((uint8_t *)(adau1761_vol_table[i].ram_word), + 1, VOL_CTL_ADDR); + break; + } + } + } break; + + case ADAU1761_CMD_VOL_GET: { + *(unsigned long *)arg = (unsigned long)adau1761_priv.vol; + } break; + + case ADAU1761_CMD_AMP_MUTE_SET: { + if (arg > 1) { + ret = -EINVAL; + goto failure; + } + + adau1761_priv.is_mute = arg; + gpio_set_value(pa_mute_item, arg); + } break; + + case ADAU1761_CMD_AMP_MUTE_GET: { + *(unsigned long *)arg = (unsigned long)adau1761_priv.is_mute; + } break; + + case ADAU1761_CMD_SRC_SET: { + if (arg > 1) { + ret = -EINVAL; + goto failure; + } + + adau1761_priv.src = arg; + + if (0 == arg) { // ana + adau1761_safe_load((uint8_t *)src_analog_arr, 1, SRC_SW_ADDR); + break; + } else { // dig + adau1761_safe_load((uint8_t *)src_dig_arr, 1, SRC_SW_ADDR); + break; + } + } break; + + case ADAU1761_CMD_SRC_GET: { + *(unsigned long *)arg = (unsigned long)adau1761_priv.src; + } break; + + case ADAU1761_CMD_FW_LOAD: { + process_sigma_firmware(adau1761_priv.i2c_client, ADAU1761_FIRMWARE); + } break; + + case ADAU1761_CMD_EQ_SET: { + ret = adau1761_safe_load_new_eq(arg); + } break; + + default: + break; + } + + mutex_unlock(&adau1761_mutex); + + DSP_DEBUG("ioctl end\n"); + + return ret; + +failure: + DSP_DEBUG("ioctl err: %d\n", ret); + mutex_unlock(&adau1761_mutex); + + return ret; +} + +static const struct file_operations adau1761_fops = { + .owner = THIS_MODULE, + .open = adau1761_open, + .release = adau1761_release, + .unlocked_ioctl = adau1761_ioctl, +}; + +static struct miscdevice adau1761_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = "adau1761", + .fops = &adau1761_fops, +}; + +/*****************************************************/ +static int adau1761_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *i2c_id) { + int i, ret = 0; + + DSP_DEBUG("i2c_probe start\n"); + + adau1761_priv.i2c_client = client; + adau1761_priv.vol = ADAU1761_DEF_VOL_STEP; + adau1761_priv.src = 0; // ana + + for (i = 0; i < ADAU1761_INIT_ARR_COUNT; i++) { + if (adau1761_init_matrix_arr[i].byte_len) { + ret = i2c_master_send(adau1761_priv.i2c_client, + adau1761_init_matrix_arr[i].p_arr, + adau1761_init_matrix_arr[i].byte_len); + + if (ret > 0) { + DSP_DEBUG("Succeeded to load adau1761_init_arr_%d, transfer: " + "%d bytes\n", + i, ret); + } else { + DSP_DEBUG("Failed to load adau1761_init_arr_%d, failure: %d\n", + i, ret); + + return -1; + } + + } else { + msleep(100); + } + } + + for (i = 0; ARRAY_SIZE(adau1761_vol_table); i++) { + if (adau1761_vol_table[i].vtable_step == ADAU1761_DEF_VOL_STEP) { + // use safeload + ret = adau1761_safe_load( + (uint8_t *)(adau1761_vol_table[i].ram_word), 1, VOL_CTL_ADDR); + + break; + } + } + + DSP_DEBUG("i2c_probe end\n"); + + if (ret > 0) { + ret = 0; + } else { + ret = -1; + } + + return ret; +} + +static int adau1761_i2c_remove(struct i2c_client *i2c) { return 0; } + +static struct i2c_board_info adau1761_i2c_board_info[] = { + { + I2C_BOARD_INFO("adau1761_0", 0x38), + }, +}; + +static const struct i2c_device_id adau1761_i2c_id[] = { + {"adau1761_0", 0}, +}; +MODULE_DEVICE_TABLE(i2c, adau1761_i2c_id); + +static const unsigned short m_normal_i2c[2] = {0x38, I2C_CLIENT_END}; + +static struct i2c_driver adau1761_i2c_driver = { + .driver = + { + .name = "adau1761_0", + .owner = THIS_MODULE, + }, + .address_list = m_normal_i2c, + .probe = adau1761_i2c_probe, + .remove = adau1761_i2c_remove, + .id_table = adau1761_i2c_id, +}; + +static int __init adau1761_r311_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct gpio_config config; + + pa_sdz_item = of_get_named_gpio_flags(np, "audio_pa_sdz", 0, + (enum of_gpio_flags *)&config); + if (!gpio_is_valid(pa_sdz_item)) { + printk("get audio_pa_sdz failed\n"); + return -EINVAL; + } else { + printk("Get audio_pa_sdz success,gpio:%d\n", pa_sdz_item); + } + + devm_gpio_request(dev, pa_sdz_item, "pa_sdz_item"); + gpio_direction_output(pa_sdz_item, 1); + + pa_mute_item = of_get_named_gpio_flags(np, "audio_pa_mute", 0, + (enum of_gpio_flags *)&config); + if (!gpio_is_valid(pa_mute_item)) { + printk("get pa_mute_item failed\n"); + return -EINVAL; + } else { + printk("Get pa_mute_item success,gpio:%d\n", pa_mute_item); + } + + devm_gpio_request(dev, pa_mute_item, "pa_mute_item"); + if (adau1761_priv.is_mute) { + gpio_direction_output(pa_mute_item, 1); // set mute high + } else { + gpio_direction_output(pa_mute_item, 0); // set mute low + } + + printk("adau1761, set pa_sdz=1, set pa_mute=%d\n", adau1761_priv.is_mute); + + return 0; +} + +static const struct of_device_id adau1761_r311_ids[] = { + {.compatible = "allwinner,adau1761-r311-pv1"}, {/* Sentinel */}}; + +static struct platform_driver adau1761_r311_driver = { + .driver = + { + .owner = THIS_MODULE, + .name = "adau1761-r311-pv1", + .of_match_table = adau1761_r311_ids, + }, +}; + +static int __init adau1761_init(void) { + struct i2c_adapter *adapter; + struct i2c_client *client; + int req_status, ret, i = 0; + + DSP_DEBUG("init start\n"); + + adau1761_priv.is_mute = 1; // mute + + platform_driver_probe(&adau1761_r311_driver, adau1761_r311_probe); + + ret = misc_register(&adau1761_misc); + if (ret < 0) { + DSP_DEBUG("init reg err\n"); + misc_deregister(&adau1761_misc); + + return ret; + } + + adau1761_priv.i2c_ch = 1; + adapter = i2c_get_adapter(adau1761_priv.i2c_ch); + + if (!adapter) + return -ENODEV; + for (i = 0; i < sizeof(adau1761_i2c_board_info) / + sizeof(adau1761_i2c_board_info[0]); + i++) { + client = NULL; + client = i2c_new_device(adapter, &adau1761_i2c_board_info[i]); + if (!client) + return -ENODEV; + } + i2c_put_adapter(adapter); + + return i2c_add_driver(&adau1761_i2c_driver); +} +module_init(adau1761_init); + +static void __exit adau1761_exit(void) { i2c_del_driver(&adau1761_i2c_driver); } +module_exit(adau1761_exit); + +MODULE_DESCRIPTION("ASoC codec adau1761 driver"); +MODULE_AUTHOR("Netease IHW"); +MODULE_LICENSE("GPL"); diff --git a/lichee/linux-4.9/drivers/misc/xunfei/Kconfig b/lichee/linux-4.9/drivers/misc/xunfei/Kconfig new file mode 100755 index 000000000..6248c4727 --- /dev/null +++ b/lichee/linux-4.9/drivers/misc/xunfei/Kconfig @@ -0,0 +1,7 @@ +menu "Xunfei module driver" +config XUNFEI_CPLD + tristate "xunfei cpld driver" + help + Xunfei CPLD Mic sample board control interfaces. Added by wzj. 2018-07-27 + +endmenu diff --git a/lichee/linux-4.9/drivers/misc/xunfei/Makefile b/lichee/linux-4.9/drivers/misc/xunfei/Makefile new file mode 100755 index 000000000..e5a7851af --- /dev/null +++ b/lichee/linux-4.9/drivers/misc/xunfei/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_XUNFEI_CPLD) += cpld/i2c_operator.o cpld/fpga_loader.o cpld/fpga_config.o cpld/cx20810.o cpld/netease_config.o diff --git a/lichee/linux-4.9/drivers/misc/xunfei/cpld/cx20810.c b/lichee/linux-4.9/drivers/misc/xunfei/cpld/cx20810.c new file mode 100755 index 000000000..000e5a298 --- /dev/null +++ b/lichee/linux-4.9/drivers/misc/xunfei/cpld/cx20810.c @@ -0,0 +1,362 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// codec init param +#include "cx20810_config.h" + +#define I2C_CX20810_DRIVER_NAME "i2c_cx20810" +#define MAX_CX20810_NUM (3) +void netease_enable_clk(void); +static int gpio_adc_rst = -1; + +// g_client_cx20810[0] is on adapter 0 and its address is 0x35 +// g_client_cx20810[1] is on adapter 1 and its address is 0x35 +// g_client_cx20810[2] is on adapter 1 and its address is 0x3B +static struct i2c_client *g_client_cx20810[MAX_CX20810_NUM]; +static const unsigned short i2c_cx20810_addr[] = {0x35, 0x3B, I2C_CLIENT_END}; +static const struct i2c_device_id i2c_driver_cx20810_id[] = { + {I2C_CX20810_DRIVER_NAME, 0}, {}}; + +// function declaration +static int cx20810_hw_init(void); +static int i2c_driver_cx20810_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int i2c_driver_cx20810_remove(struct i2c_client *client); +static int i2c_driver_cx20810_detect(struct i2c_client *client, + struct i2c_board_info *info); +static int i2c_master_send_array_to_cx20810(const struct i2c_client *client, + const char *buf, int length); +static void cx20810_init(int index, int mode); +int cx20810_set_mode(int mode, int index); + +// set cx20810 work mode +int cx20810_set_mode(int mode, int index) { + printk("Timothy:cx20810.c->cx20810_set_mode(), mode = %d, index = %d\n", + mode, index); + int i; + int ret; + char *param; + int length; + + switch (mode) { + case CX20810_NORMAL_MODE: + param = codec_config_param_normal_mode; + length = sizeof(codec_config_param_normal_mode); + break; + + case CX20810_NORMAL_MODE_SIMPLE: + param = codec_config_param_normal_mode_simple; + length = sizeof(codec_config_param_normal_mode_simple); + break; + + case CX20810_48K_16BIT_MODE: + param = codec_config_param_48k_16bit_mode; + length = sizeof(codec_config_param_48k_16bit_mode); + break; + + case CX20810_96K_16BIT_MODE: + param = codec_config_param_96k_16bit_mode; + length = sizeof(codec_config_param_96k_16bit_mode); + break; + + case CX20810_NIRMAL_MODE_CODEC3: + param = codec3_config_param_normal_mode; + length = sizeof(codec3_config_param_normal_mode); + break; + + case CX20810_NIRMAL_MODE_CODEC3_SIMPLE: + param = codec3_config_param_normal_mode_simple; + length = sizeof(codec3_config_param_normal_mode_simple); + break; + + default: + return; + break; + } + + // if client is null, return + if (g_client_cx20810[index] == NULL) { + printk("Timothy:cx20810(%d) is not detected yet\n", index); + return -1; + } + + ret = i2c_master_send_array_to_cx20810(g_client_cx20810[index], param, + length); + if (ret != 0) { + printk("Timothy:cx82011[%x] init error!\n", + g_client_cx20810[index]->addr); + return -1; + } else { + printk("Timothy:cx20810[%x] init ok\n", g_client_cx20810[index]->addr); + return 0; + } +} +EXPORT_SYMBOL(cx20810_set_mode); + +int cx20810_write_reg(int index, int addr, int regval) { + char writedata[2] = {0}; + if (index > 1) { + return -1; + } + writedata[0] = (char)addr; + writedata[1] = (char)regval; + + return i2c_master_send(g_client_cx20810[index], writedata, 2); +} +EXPORT_SYMBOL(cx20810_write_reg); + +int cx20810_read_reg(int index, int cmd, int *regval) { + int error = 0; + char data = 0; + if (index > 1) { + return -1; + } + + error = i2c_master_send(g_client_cx20810[index], (const char *)&cmd, 1); + // write reg addr + if (1 != i2c_master_send(g_client_cx20810[index], (const char *)&cmd, 1)) { + printk(KERN_ERR " cx20810_read_reg fail1! \n"); + return -1; + } + // wait + msleep(10); + // read + if (error >= 0) { + error = i2c_master_recv(g_client_cx20810[index], &data, 1); + if (error < 0) { + printk(KERN_ERR " cx20810_read_reg fail2! \n"); + } + } else { + printk(KERN_ERR " cx20810_read_reg fail1! \n"); + } + + *regval = (int)data; + + return 0; +} +EXPORT_SYMBOL(cx20810_read_reg); + +// send parameters to cx20810 as master +static int i2c_master_send_array_to_cx20810(const struct i2c_client *client, + const char *buf, int length) { + printk("Timothy:cx20810.c->i2c_master_send_array_to_cx20810()\n"); + int i; + int nwrite; + for (i = 0; i < (length / 2); i++) { + nwrite = i2c_master_send(client, buf + i * 2, 2); + if (nwrite != 2) { + printk("Timothy:send to cx20810 error\n"); + return -1; + } + } + return 0; +} + +// initial cx20810 +static void cx20810_init(int index, int mode) { + printk("Timothy:cx20810.c->cx20810_init()\n"); + if (cx20810_set_mode(mode, index) == 0) { + printk("Timothy:cx20810 init success\n"); + } else { + printk("Timothy:cx20810 init fail\n"); + } +} + +static int i2c_driver_cx20810_probe(struct i2c_client *client, + const struct i2c_device_id *id) { + if (client->adapter->nr == 0 && client->addr == i2c_cx20810_addr[0]) { + g_client_cx20810[1] = client; + printk("Timothy:cx20810 (0x%x) init ok\n", client->addr); + cx20810_init(1, CX20810_NORMAL_MODE); + } else if (client->adapter->nr == 0 && + client->addr == i2c_cx20810_addr[1]) { + g_client_cx20810[0] = client; + printk("Timothy:cx20810 (0x%x) init ok\n", client->addr); + cx20810_init(0, CX20810_NORMAL_MODE); + } + return 0; +} + +static int i2c_driver_cx20810_remove(struct i2c_client *client) { + printk("Timothy:cx20810.c->i2c_driver_cx20810_remove()\n"); + return 0; +} +MODULE_DEVICE_TABLE(i2c, i2c_driver_cx20810_id); + +static int i2c_driver_cx20810_detect(struct i2c_client *client, + struct i2c_board_info *info) { + printk("Timothy:cx20810.c->i2c_driver_cx20810_detect()...\n"); + struct i2c_adapter *p_adapter; + const char *type_name = I2C_CX20810_DRIVER_NAME; + p_adapter = client->adapter; + printk("Timothy:adapter->nr = %d\n", p_adapter->nr); + if (0 == p_adapter->nr) { + if (info->addr == i2c_cx20810_addr[0]) { + printk("Timothy:detect cx20810 (%x) on i2c adapter (%d)\n", + info->addr, p_adapter->nr); + strlcpy(info->type, type_name, I2C_NAME_SIZE); + return 0; + } else if (info->addr == i2c_cx20810_addr[1]) { + printk("Timothy:detect cx20810 (%x) on i2c adapter (%d)\n", + info->addr, p_adapter->nr); + strlcpy(info->type, type_name, I2C_NAME_SIZE); + return 0; + } + } + return ENODEV; +} + +static struct i2c_driver i2c_driver_cx20810 = { + .class = I2C_CLASS_HWMON, + .probe = i2c_driver_cx20810_probe, + .remove = i2c_driver_cx20810_remove, + .id_table = i2c_driver_cx20810_id, + .driver = + { + .name = I2C_CX20810_DRIVER_NAME, + .owner = THIS_MODULE, + }, + .detect = i2c_driver_cx20810_detect, + .address_list = i2c_cx20810_addr}; + +static int __init i2c_driver_cx20810_init(void) { + printk("Timothy:cx20810.c->i2c_driver_cx20810_init()\n"); + msleep(300); + // cx20810_hw_init(); + return i2c_add_driver(&i2c_driver_cx20810); +} + +static void __exit i2c_driver_cx20810_exit(void) { + printk("Timothy:cx20810.c->i2c_driver_cx20810_exit()\n"); + i2c_del_driver(&i2c_driver_cx20810); +} + +static int __init cpld_r311_probe(struct platform_device *pdev) { + printk("Begin to set luyao asked gpios \n"); + + struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct gpio_config cfg; + int gpionum; + + gpionum = of_get_named_gpio_flags(np, "4v5_ldo_en", 0, + (enum of_gpio_flags *)&cfg); + if (gpio_is_valid(gpionum)) { + gpio_request(gpionum, "4v5_ldo_en"); + gpio_direction_output(gpionum, 1); + printk("Set 4v5_ldo_en(%d) success\n", gpionum); + } else { + printk("Set 4v5_ldo_en fail\n"); + } + + gpionum = + of_get_named_gpio_flags(np, "3v_ldo_en", 0, (enum of_gpio_flags *)&cfg); + if (gpio_is_valid(gpionum)) { + gpio_request(gpionum, "3v_ldo_en"); + gpio_direction_output(gpionum, 1); + printk("Set 3v_ldo_en(%d) success\n", gpionum); + } else { + printk("Set 3v_ldo_en fail\n"); + } + + gpionum = of_get_named_gpio_flags(np, "gp_adc_rst", 0, + (enum of_gpio_flags *)&cfg); + gpio_adc_rst = gpionum; + if (!gpio_is_valid(gpionum)) { + printk("get gp_adc_rst failed\n"); + return -EINVAL; + } else { + printk("Get gp_adc_rst success,gpio:%d\n", gpionum); + } + + devm_gpio_request(dev, gpionum, "gp_adc_rst"); + gpio_direction_output(gpionum, 1); + printk("Set gp_adc_rst(%d) to 1\n", gpionum); + + return 0; +} + +void netease_cpld_reset(void) { + printk("Begin to reset cpld!\n"); + if (gpio_is_valid(gpio_adc_rst)) { + gpio_set_value(gpio_adc_rst, 0); + msleep(100); + printk("Begin to start cpld!\n"); + gpio_set_value(gpio_adc_rst, 1); + msleep(800); + printk("Finish reseting cpld!\n"); + } else { + printk("Adc rst gpio is not init!\n"); + } +} + +static const struct of_device_id cpld_r311_ids[] = { + {.compatible = "allwinner,cpld-r311-pv1"}, {/* Sentinel */}}; + +static struct platform_driver cpld_r311_driver = { + .driver = + { + .owner = THIS_MODULE, + .name = "cpld", + .of_match_table = cpld_r311_ids, + }, +}; + +static int __init cpld_r311_init(void) { + int ret = 0; +#if 0 + type = script_get_item("cpld", "gp_ldo_4_5", &item); + if (SCIRPT_ITEM_VALUE_TYPE_PIO == type) { + printk("luyao:set gp_ldo_4_5\n"); + printk("Gpio:%d\n", item.gpio.gpio); + + gpio_request(item.gpio.gpio, NULL); + + gpio_direction_output(item.gpio.gpio, 1); + gpio_set_value(item.gpio.gpio, 1); + + gpio_free(item.gpio.gpio); + } + + type = script_get_item("cpld", "gp_ldo_3", &item); + if (SCIRPT_ITEM_VALUE_TYPE_PIO == type) { + printk("luyao:set gp_ldo_3\n"); + printk("Gpio:%d\n", item.gpio.gpio); + gpio_request(item.gpio.gpio, NULL); + gpio_direction_output(item.gpio.gpio, 1); + gpio_set_value(item.gpio.gpio, 1); + gpio_free(item.gpio.gpio); + } +#endif + printk("Begin to init cpld r311 driver!!\n"); + ret = platform_driver_probe(&cpld_r311_driver, cpld_r311_probe); + printk("platform_driver_probe:%d!\n", ret); + + return ret; +} + +static void __exit cpld_r311_deinit(void) {} + +fs_initcall_sync(cpld_r311_init); +module_exit(cpld_r311_deinit); + +late_initcall_sync(i2c_driver_cx20810_init); +module_exit(i2c_driver_cx20810_exit); + +MODULE_AUTHOR("Timothy"); +MODULE_DESCRIPTION("I2C device cx20810 loader"); +MODULE_LICENSE("GPL"); diff --git a/lichee/linux-4.9/drivers/misc/xunfei/cpld/cx20810_config.h b/lichee/linux-4.9/drivers/misc/xunfei/cpld/cx20810_config.h new file mode 100755 index 000000000..79e4a0012 --- /dev/null +++ b/lichee/linux-4.9/drivers/misc/xunfei/cpld/cx20810_config.h @@ -0,0 +1,340 @@ +#ifndef CX20810_CONFIG_H_ +#define CX20810_CONFIG_H_ + +enum +{ + CX20810_NORMAL_MODE = 0, + CX20810_NORMAL_MODE_SIMPLE, + CX20810_NIRMAL_MODE_CODEC3, + CX20810_NIRMAL_MODE_CODEC3_SIMPLE, + CX20810_96K_16BIT_MODE, + CX20810_48K_16BIT_MODE, +}; + +const char codec_config_param_normal_mode[]= +{ + 0x0F,0x03, //RST + 0x0F,0x03, //repeat write is let chip has more time to RST + 0x0F,0x03, + 0x0F,0x03, + + 0x0F,0x00,//release reset + + 0x78,0x33, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + 0x78,0x33, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + 0x78,0x33, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + 0x78,0x33, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + 0x78,0x33, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + + 0x78,0x73, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + 0x78,0x73, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + 0x78,0x73, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + 0x78,0x73, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + 0x78,0x73, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + + 0x7A,0x01, + 0x01,0x01, + + 0xA0,0x07,//ADC bias EN + 0xA7,0x07, + 0xAE,0x07, + 0xB5,0x07, + + 0xBC,0x38,// 0x28 20dB 0x34 26dB + 0xBD,0x38, + 0xBE,0x38, + 0xBF,0x38, + + 0x30,0x14,//14 24bit 0a 16bit + 0x31,0x07,//frame (n+1)*8 bit 32+32=64 + 0x32,0x07,// + 0x33,0x1F,//sys width 32 clk + 0x34,0x1F, + 0x35,0xA2,// TX left justified i2s1+i2s2 + 0x36,0x00,// config for right justified ignored. + 0x37,0x00,// RX left justified. + 0x38,0x00,// config for right justified ignored. + 0x39,0x08, // ADC12 0n DATA1.ADC34 On DATA2 + 0x3A,0x00,//Slot1 + 0x3B,0x00,//slot2 + 0x3C,0x00,//slot3 + 0x3D,0x00,//slot4 + 0x3E,0x1F,//slot4 + + 0x16,0x00, // Use DC Filter for ADCs + + 0x80,0x03,// MCLK + 0x81,0x01,// LRCLK BCLK RX Pull down + 0x82,0x3F,// LRCLK BCLK RX + 0x83,0x0F,// LRCLK BCLK +/* +// PLL config + + 0x08,0x00,// disable MCLK + + 0x09,0x40,// I2S TX Bit Clock + + 0x60,0xF8, //reset and Disable PLL1 + + 0x61,0xDF,// + 0x62,0x01, + 0x63,0x01, +//{0x64,0x90}, +//{0x65,0x24}, + 0x66,0x80, + 0x67,0x02, +//{0x68,0x0}, +//{0x69,0x0}, + // enable PLL1 + + 0x60,0xFB,//delay for PLL locked + 0x60,0xFB, + 0x60,0xFB, + 0x60,0xFB, + 0x60,0xFB, + 0x60,0xFB, + +// end PLL config +*/ + + 0x0F,0x01, //RST,clears DSP,audio data interface values + 0x0F,0x01, //repeat write is let chip has more time to RST + 0x0F,0x01, + 0x0F,0x01, + + 0x08,0x00,// disable MCLK to chip + 0x0C,0x0A,// Clocks gated + 0x09,0x02, + + + 0x0F,0x00,//clear RST + //0x08,0x30,// enable MCLK to chip + //0x08,0x38, + 0x08,0x20, + 0x09,0x03, + + 0x10,0x00, // Disable all ADC clocks + 0x11,0x10, // Disable all ADC and Mixer + 0x10,0x1F, // Enable all ADC clocks and ADC digital + 0x11,0x1F, // Enable all ADC and set 16k sample rate + 0x10,0x5F, // Enable all ADC clocks, ADC digital and ADC Mic Clock Gate + +}; + +const char codec_config_param_normal_mode_simple[]= +{ + // mic pga 增益 + // 4通道录音工具 + 0xBC,0x28,// 0x28 20dB 0x34 26dB + 0xBD,0x28, + 0xBE,0x28, + 0xBF,0x28, + + 0x60,0x04, + 0x66,0x00, + 0x67,0x02, + + //PAD配置 + 0x80,0x03,// MCLK 为输入 + 0x83,0x0F,// LRCLK BCLK 为输入脚,TX1 TX2为输出脚 + + //0x08,0x30,// MCLK 作为输入 + //0x08,0x38,// MCLK divisor 生效 + 0x08,0x20,// MCLK 作为输入 12.288MHz + 0x09,0x03,// 选MCLK作为PLL输入源 + 0x0a,0x0b, + 0x0a,0x8b, + 0x0C,0x0A,// RT clock disable, TX clock enable, enable clock to ADC3/4 + + // I2S + //0x30,0x0A,// Tx sample size:16bit, Normal mode + 0x30,0x14,// Tx sample size:24bit, Normal mode + 0x35,0xA2,// left justified, enable I2S-1 and I2S-2 + + 0x10,0x00, + 0x11,0x00, + 0x10,0x1F, + 0x11,0x1F,// ADC 96k, enables all ADCs + 0x16,0x00, + 0x10,0x5F, + +}; + +const char codec3_config_param_normal_mode[]= +{ + // POWER + 0x78,0x39, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + 0x78,0x39, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + 0x78,0x39, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + 0x78,0x39, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + 0x78,0x39, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + + 0x78,0x79, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + 0x78,0x79, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + 0x78,0x79, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + 0x78,0x79, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + 0x78,0x79, //*PLLEN = 1 ABIASEN IOBUFEN REFIMP = 11 3KR + + 0x7A,0x01, + 0x01,0x01, + + // Analog ADC Control + // MIcIn PGA A0,A7,AE,B5 [5:4] ctrl_rcm , [1] enable [3] mute [7] bypass + // 模拟部分电源 + 0xA0,0x07,//ADC bias EN + 0xA7,0x07, + 0xAE,0x07, + 0xB5,0x07, + + // mic pga 增益 + // 4通道录音工具 + 0xBC,0x06,// 0x28 20dB 0x34 26dB + 0xBD,0x06, + 0xBE,0x0C, + 0xBF,0x14, + + 0x60,0x04, + 0x66,0x00, + 0x67,0x02, + + //PAD配置 + 0x80,0x03,// MCLK 为输入 + 0x83,0x0F,// LRCLK BCLK 为输入脚,TX1 TX2为输出脚 + + //0x08,0x30,// MCLK 作为输入 + //0x08,0x38,// MCLK divisor 生效 + 0x08,0x20,// MCLK 作为输入 12.288MHz + 0x09,0x03,// 选MCLK作为PLL输入源 + 0x0a,0x0b, + 0x0a,0x8b, + 0x0C,0x0A,// RT clock disable, TX clock enable, enable clock to ADC3/4 + + // I2S + //0x30,0x0A,// Tx sample size:16bit, Normal mode + 0x30,0x14,// Tx sample size:24bit, Normal mode + 0x35,0xA2,// left justified, enable I2S-1 and I2S-2 + + 0x10,0x00, + 0x11,0x00, + 0x10,0x1F, + 0x11,0x1F,// ADC 96k, enables all ADCs + 0x16,0x00, + 0x10,0x5F, + +}; + +const char codec3_config_param_normal_mode_simple[]= +{ + // mic pga 增益 + // 4通道录音工具 + 0xBC,0x28,// 0x28 20dB 0x34 26dB + 0xBD,0x28, + 0xBE,0x28, + 0xBF,0x28, + + 0x60,0x04, + 0x66,0x00, + 0x67,0x02, + + //PAD配置 + 0x80,0x03,// MCLK 为输入 + 0x83,0x0F,// LRCLK BCLK 为输入脚,TX1 TX2为输出脚 + + //0x08,0x30,// MCLK 作为输入 + //0x08,0x38,// MCLK divisor 生效 + 0x08,0x20,// MCLK 作为输入 12.288MHz + 0x09,0x03,// 选MCLK作为PLL输入源 + 0x0a,0x0b, + 0x0a,0x8b, + 0x0C,0x0A,// RT clock disable, TX clock enable, enable clock to ADC3/4 + + // I2S + //0x30,0x0A,// Tx sample size:16bit, Normal mode + 0x30,0x14,// Tx sample size:24bit, Normal mode + 0x35,0xA2,// left justified, enable I2S-1 and I2S-2 + + 0x10,0x00, + 0x11,0x00, + 0x10,0x1F, + 0x11,0x1F,// ADC 96k, enables all ADCs + 0x16,0x00, + 0x10,0x5F, +}; + +const char codec_config_param_48k_16bit_mode[]= +{ + // mic pga 增益 + // 4通道录音工具 + 0xBC,29 << 1,// 0x28 20dB 0x34 26dB + 0xBD,29 << 1, + 0xBE,29 << 1, + 0xBF,29 << 1, + + 0x60,0x04, + 0x66,0x00, + 0x67,0x02, + + //PAD配置 + 0x80,0x03,// MCLK 为输入 + 0x83,0x0F,// LRCLK BCLK 为输入脚,TX1 TX2为输出脚 + + //0x08,0x30,// MCLK 作为输入 + //0x08,0x38,// MCLK divisor 生效 + 0x08,0x20,// MCLK 作为输入 12.288MHz + 0x09,0x03,//选MCLK作为PLL输入源 + 0x0a,0x03, + 0x0a,0x83, + 0x0C,0x0A,// RT clock disable, TX clock enable, enable clock to ADC3/4 + + // I2S + 0x30,0x0A,// Tx sample size:16bit, Normal mode + //0x30,0x14,// Tx sample size:24bit, Normal mode + 0x35,0xA2,// left justified, enable I2S-1 and I2S-2 + + 0x10,0x00, + 0x11,0x00, + 0x10,0x1F, + 0x11,0x4F,// ADC 96k, enables all ADCs + 0x16,0x00, + 0x10,0x5F, +}; + +const char codec_config_param_96k_16bit_mode[]= +{ + // mic pga 增益 + // 4通道录音工具 + 0xBC,29 << 1,// 0x28 20dB 0x34 26dB + 0xBD,29 << 1, + 0xBE,29 << 1, + 0xBF,29 << 1, + + 0x60,0x04, + 0x66,0x00, + 0x67,0x02, + + //PAD配置 + 0x80,0x03,// MCLK 为输入 + 0x83,0x0F,// LRCLK BCLK 为输入脚,TX1 TX2为输出脚 + + //0x08,0x30,// MCLK 作为输入 + //0x08,0x38,// MCLK divisor 生效 + 0x08,0x20,// MCLK 作为输入 12.288MHz + 0x09,0x03,// 选MCLK作为PLL输入源 + 0x0a,0x01, + 0x0a,0x81, + 0x0C,0x0A,// RT clock disable, TX clock enable, enable clock to ADC3/4 + + // I2S + 0x30,0x0A,// Tx sample size:16bit, Normal mode + //0x30,0x14,// Tx sample size:24bit, Normal mode + 0x35,0xA2,// left justified, enable I2S-1 and I2S-2 + + 0x10,0x00, + 0x11,0x00, + 0x10,0x1F, + 0x11,0x5F,// ADC 96k, enables all ADCs + 0x16,0x00, + 0x10,0x5F, +}; + +#endif /* CX20810_CONFIG_H_ */ diff --git a/lichee/linux-4.9/drivers/misc/xunfei/cpld/fpga_config.c b/lichee/linux-4.9/drivers/misc/xunfei/cpld/fpga_config.c new file mode 100755 index 000000000..569dd40d4 --- /dev/null +++ b/lichee/linux-4.9/drivers/misc/xunfei/cpld/fpga_config.c @@ -0,0 +1,428 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include + +// unsigned char toupad_get_key(void); +// void tipa_set_vol(unsigned char abs_vol); +int at_8740_write(unsigned char *pbuf, unsigned int len); +int at_8740_read(unsigned char *pbuf, unsigned int len); +void at_8740_wakeup(void); + +static unsigned int map_io_base; +#define D_IO_BASE map_io_base +#define D_IO_BASE_PHY (0x01c20800) +#define D_IO_LEN (0x400) +#define D_IO_A (0) +#define D_IO_B (1) +#define D_IO_C (2) +#define D_IO_D (3) +#define D_IO_E (4) +#define D_IO_F (5) +#define D_IO_G (6) +#define D_IO_H (7) +#define D_IO_I (8) +#define D_IO_CFG0(x) (D_IO_BASE + (x * 0x24) + 0x00) +#define D_IO_CFG1(x) (D_IO_BASE + (x * 0x24) + 0x04) +#define D_IO_CFG2(x) (D_IO_BASE + (x * 0x24) + 0x08) +#define D_IO_CFG3(x) (D_IO_BASE + (x * 0x24) + 0x0c) +#define D_IO_DAT(x) (D_IO_BASE + (x * 0x24) + 0x10) +#define D_IO_DRV0(x) (D_IO_BASE + (x * 0x24) + 0x14) +#define D_IO_DRV1(x) (D_IO_BASE + (x * 0x24) + 0x18) +#define D_IO_PUL0(x) (D_IO_BASE + (x * 0x24) + 0x1c) +#define D_IO_PUL1(x) (D_IO_BASE + (x * 0x24) + 0x20) + +int cx20810_set_mode(int mode, int index); + +typedef struct { + unsigned int opcode; + unsigned int param[3]; +} t_data_unit; + +enum { + eDU_RESVER = 0, + eDU_IVW_PRESET_TIME, + eDU_REC_TYPE, + eDU_IVW_POS_INFO, + eDU_MAX +}; + +t_data_unit database[eDU_MAX]; + +static int major_num; +static struct class *p_class; +static struct device *p_fpga; +static struct device *p_reg_debug; +static struct device *p_dsp_settings; +static struct device *p_au; +static struct device *p_tk; +static struct device *p_vol; +static struct device *p_vol2; +static struct device *p_8740; +static struct device *p_8740_wakeup; + +static unsigned int param_config; + +static struct kset *kset_vendor; +static struct kobject kobj_pa; + +static ssize_t gen_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) { + strcpy(buf, "wocao"); + return strlen(buf); +} + +static ssize_t gen_attr_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + int i = simple_strtol(buf, (char **)(buf + strlen(buf) - 1), 0); + printk("vol=%ddb", i); + // tipa_set_vol(2 * (24-i)); + return count; +} + +struct attribute gen_vol_set = { + .name = "vol_set", + .mode = S_IRWXUGO, +}; + +struct attribute *gen_attr_group[] = { + &gen_vol_set, + NULL, +}; + +static const struct sysfs_ops gen_ops = { + .show = gen_attr_show, + .store = gen_attr_store, +}; + +static void gen_release(struct kobject *k) { + // nothing to do +} + +static struct kobj_type gen_ktype = { + .sysfs_ops = &gen_ops, + .default_attrs = gen_attr_group, + .release = gen_release, +}; + +static int gp_open(struct inode *pnode, struct file *pfile) { + int major = MAJOR(pnode->i_rdev); + int minor = MINOR(pnode->i_rdev); + + if (minor == 0) { + pfile->private_data = (void *)p_fpga; + } else if (minor == 1) { + pfile->private_data = (void *)p_reg_debug; + } else if (minor == 2) { + pfile->private_data = (void *)p_dsp_settings; + } else if (minor == 3) { + pfile->private_data = (void *)p_au; + } else if (minor == 4) { + pfile->private_data = (void *)p_tk; + } else if (minor == 5) { + pfile->private_data = (void *)p_vol; + } + // else if(minor == 6) + // { + // pfile->private_data = (void*)p_8740; + // } + // else if(minor == 7) + // { + // pfile->private_data = (void*)p_8740_wakeup; + // } + else { + pfile->private_data = NULL; + } + + return 0; +} + +static int gp_close(struct inode *pnode, struct file *pfile) { return 0; } + +static ssize_t gp_read(struct file *pfile, char __user *puser, size_t len, + loff_t *poff) { + if (pfile->private_data == p_fpga) { + return 0; + } else if (pfile->private_data == p_reg_debug) { + unsigned int base_addr = (unsigned int)ioremap(0x1C22400, 0x100); + unsigned int i; + for (i = 0; i <= 0x3C; i += 4) { + printk("[i2s1] addr:0x%x val:0x%x\r\n", base_addr + i, + *((unsigned int *)(base_addr + i))); + } + return len; + } else if (pfile->private_data == p_au) { + t_data_unit tmp_data; + copy_from_user((void *)&tmp_data, puser, len); + if (tmp_data.opcode < eDU_MAX) { + copy_to_user(puser, &database[tmp_data.opcode], + sizeof(t_data_unit)); + return len; + } else { + return 0; + } + } + // else if(pfile->private_data == p_tk) + // { + // unsigned char tmp = toupad_get_key(); + // copy_to_user(puser, &tmp, sizeof(unsigned char)); + // return len; + // } + // else if(pfile->private_data == p_8740) + // { + // unsigned char * pbuf; + // pbuf = kmalloc(len, GFP_KERNEL); + // printk("8740 nread:%d\r\n", at_8740_read(pbuf, len)); + // copy_to_user(puser, pbuf, len); + // kfree(pbuf); + // return len; + // } + // else if(pfile->private_data == p_8740_wakeup) + // { + // return len; + // } + return 0; +} + +enum { + CX20810_NORMAL_MODE = 0, + CX20810_NORMAL_MODE_SIMPLE, + CX20810_NIRMAL_MODE_CODEC3, + CX20810_NIRMAL_MODE_CODEC3_SIMPLE, + CX20810_96K_16BIT_MODE, + CX20810_48K_16BIT_MODE, +}; + +static ssize_t gp_write(struct file *pfile, const char __user *puser, + size_t len, loff_t *poff) { + if (pfile->private_data == p_fpga) { + copy_from_user((void *)¶m_config, puser, len); + switch (param_config) { + case 0: + printk("fpga_config:mode0\r\n"); + // cx20810_set_mode(CX20810_NORMAL_MODE, 0); + // cx20810_set_mode(CX20810_NORMAL_MODE, 1); + // cx20810_set_mode(CX20810_NORMAL_MODE, 2); + // writel((readl(D_IO_CFG0(D_IO_D)) & ~0x7000000) | + // 0x1000000, D_IO_CFG0(D_IO_D)); + // writel((readl(D_IO_DAT(D_IO_D)) & ~(1 << 6)), + // D_IO_DAT(D_IO_D)); + // writel((readl(D_IO_CFG0(D_IO_D)) & ~0x7000) | + // 0x1000, D_IO_CFG0(D_IO_D)); + // writel((readl(D_IO_DAT(D_IO_D)) & ~(1 << 3)), + // D_IO_DAT(D_IO_D)); + // writel((readl(D_IO_CFG0(D_IO_D)) & ~0x70000) | + // 0x10000, D_IO_CFG0(D_IO_D)); + // writel((readl(D_IO_DAT(D_IO_D)) & ~(1 << 4)), + // D_IO_DAT(D_IO_D)); + writel((readl(D_IO_CFG0(D_IO_E)) & ~0x70000) | 0x10000, + D_IO_CFG0(D_IO_E)); + writel((readl(D_IO_DAT(D_IO_E)) & ~(1 << 4)), D_IO_DAT(D_IO_E)); + writel((readl(D_IO_CFG0(D_IO_H)) & ~0x70000000) | 0x10000000, + D_IO_CFG0(D_IO_H)); + writel((readl(D_IO_DAT(D_IO_H)) & ~(1 << 7)), D_IO_DAT(D_IO_H)); + writel((readl(D_IO_CFG0(D_IO_E)) & ~0x7000) | 0x1000, + D_IO_CFG0(D_IO_E)); + writel((readl(D_IO_DAT(D_IO_E)) & ~(1 << 3)), D_IO_DAT(D_IO_E)); + break; + case 1: + printk("fpga_config:mode1\r\n"); + cx20810_set_mode(CX20810_96K_16BIT_MODE, 1); + // writel((readl(D_IO_CFG0(D_IO_D)) & ~0x7000000) | + // 0x1000000, D_IO_CFG0(D_IO_D)); + // writel((readl(D_IO_DAT(D_IO_D)) & ~(1 << 6)), + // D_IO_DAT(D_IO_D)); + // writel((readl(D_IO_CFG0(D_IO_D)) & ~0x7000) | + // 0x1000, D_IO_CFG0(D_IO_D)); + // writel((readl(D_IO_DAT(D_IO_D)) | (1 << 3)), + // D_IO_DAT(D_IO_D)); + // writel((readl(D_IO_CFG0(D_IO_D)) & ~0x70000) | + // 0x10000, D_IO_CFG0(D_IO_D)); + // writel((readl(D_IO_DAT(D_IO_D)) & ~(1 << 4)), + // D_IO_DAT(D_IO_D)); + writel((readl(D_IO_CFG0(D_IO_E)) & ~0x70000) | 0x10000, + D_IO_CFG0(D_IO_E)); + writel((readl(D_IO_DAT(D_IO_E)) & ~(1 << 4)), D_IO_DAT(D_IO_E)); + writel((readl(D_IO_CFG0(D_IO_H)) & ~0x70000000) | 0x10000000, + D_IO_CFG0(D_IO_H)); + writel((readl(D_IO_DAT(D_IO_H)) & ~(1 << 7)), D_IO_DAT(D_IO_H)); + writel((readl(D_IO_CFG0(D_IO_E)) & ~0x7000) | 0x1000, + D_IO_CFG0(D_IO_E)); + writel((readl(D_IO_DAT(D_IO_E)) | (1 << 3)), D_IO_DAT(D_IO_E)); + break; + case 2: + printk("fpga_config:mode2\r\n"); + cx20810_set_mode(CX20810_48K_16BIT_MODE, 0); + // writel((readl(D_IO_CFG0(D_IO_D)) & ~0x7000000) | + // 0x1000000, D_IO_CFG0(D_IO_D)); + // writel((readl(D_IO_DAT(D_IO_D)) & ~(1 << 6)), + // D_IO_DAT(D_IO_D)); + // writel((readl(D_IO_CFG0(D_IO_D)) & ~0x7000) | + // 0x1000, D_IO_CFG0(D_IO_D)); + // writel((readl(D_IO_DAT(D_IO_D)) & ~(1 << 3)), + // D_IO_DAT(D_IO_D)); + // writel((readl(D_IO_CFG0(D_IO_D)) & ~0x70000) | + // 0x10000, D_IO_CFG0(D_IO_D)); + // writel((readl(D_IO_DAT(D_IO_D)) | (1 << 4)), + // D_IO_DAT(D_IO_D)); + writel((readl(D_IO_CFG0(D_IO_E)) & ~0x70000) | 0x10000, + D_IO_CFG0(D_IO_E)); + writel((readl(D_IO_DAT(D_IO_E)) & ~(1 << 4)), D_IO_DAT(D_IO_E)); + writel((readl(D_IO_CFG0(D_IO_H)) & ~0x70000000) | 0x10000000, + D_IO_CFG0(D_IO_H)); + writel((readl(D_IO_DAT(D_IO_H)) | (1 << 7)), D_IO_DAT(D_IO_H)); + writel((readl(D_IO_CFG0(D_IO_E)) & ~0x7000) | 0x1000, + D_IO_CFG0(D_IO_E)); + writel((readl(D_IO_DAT(D_IO_E)) & ~(1 << 3)), D_IO_DAT(D_IO_E)); + break; + default: + break; + } + return len; + } else if (pfile->private_data == p_reg_debug) { + return len; + } else if (pfile->private_data == p_dsp_settings) { + return len; + } else if (pfile->private_data == p_au) { + t_data_unit tmp_data; + copy_from_user((void *)&tmp_data, puser, len); + if (tmp_data.opcode < eDU_MAX) { + memcpy(&database[tmp_data.opcode], &tmp_data, sizeof(t_data_unit)); + return len; + } else { + return 0; + } + } else if (pfile->private_data == p_vol) { + unsigned char tmp; + copy_from_user((void *)&tmp, puser, len); + // tipa_set_vol(tmp); + return len; + } + // else if(pfile->private_data == p_8740) + // { + // unsigned char * pbuf; + // pbuf = kmalloc(len, GFP_KERNEL); + // copy_from_user((void*)pbuf, puser, len); + // printk("8740 nwrite:%d\r\n", at_8740_write(pbuf, len)); + // kfree(pbuf); + // return len; + // } + // else if(pfile->private_data == p_8740_wakeup) + // { + // printk("8740 wakeup\r\n"); + // at_8740_wakeup(); + // return len; + // } + else { + } + return 0; +} + +static struct file_operations gp_fops = { + .owner = THIS_MODULE, + .open = gp_open, + .release = gp_close, + .read = gp_read, + .write = gp_write, +}; + +static int __init fpga_config_init(void) { + D_IO_BASE = (unsigned int)ioremap(D_IO_BASE_PHY, D_IO_LEN); + if (!D_IO_BASE) { + printk("[gen_prov] init gpio err\r\n"); + return; + } + + kset_vendor = kset_create_and_add("vendor", NULL, NULL); + kobj_pa.kset = kset_vendor; + kobject_init_and_add(&kobj_pa, &gen_ktype, NULL, "pa"); + + major_num = register_chrdev(0, "fpga_chr", &gp_fops); + if (major_num < 0) { + printk("reg_chr_err\n"); + return 1; + } + + p_class = class_create(THIS_MODULE, "fpga_class"); + if (p_class == NULL) { + printk("class create err\n"); + return 1; + } + + p_fpga = + device_create(p_class, NULL, MKDEV(major_num, 0), NULL, "fpga_config"); + if (p_fpga == NULL) { + printk("device_create err:fpga\n"); + return 1; + } + + p_reg_debug = + device_create(p_class, NULL, MKDEV(major_num, 1), NULL, "reg_debug"); + if (p_reg_debug == NULL) { + printk("device_create err:reg_debug\n"); + return 1; + } + + p_dsp_settings = + device_create(p_class, NULL, MKDEV(major_num, 2), NULL, "dsp_settings"); + if (p_dsp_settings == NULL) { + printk("device_create err:p_dsp_settings\n"); + return 1; + } + + p_au = device_create(p_class, NULL, MKDEV(major_num, 3), NULL, "au_base"); + if (p_au == NULL) { + printk("device_create err:au_base\n"); + return 1; + } + + p_tk = device_create(p_class, NULL, MKDEV(major_num, 4), NULL, "touch_key"); + if (p_tk == NULL) { + printk("device_create err:touch_key\n"); + return 1; + } + + p_vol = device_create(p_class, NULL, MKDEV(major_num, 5), NULL, "vbox_vol"); + if (p_vol == NULL) { + printk("device_create err:vbox_vol\n"); + return 1; + } + + // p_8740 = device_create(p_class, NULL, MKDEV(major_num, 6), NULL, + // "atml_sec"); if(p_8740 == NULL) + // { + // printk("device_create err:p_8740\n"); + // return 1; + // } + + // p_8740_wakeup = device_create(p_class, NULL, MKDEV(major_num, 7), + // NULL, "atml_sec_wake"); if(p_8740_wakeup == NULL) + // { + // printk("device_create err:p_8740\n"); + // return 1; + // } + + return 0; +} +//module_init(fpga_config_init); + +static void __exit fpga_config_exit(void) {} +module_exit(fpga_config_exit); + +/* Module information */ +MODULE_AUTHOR("feitao"); +MODULE_DESCRIPTION("fpga config"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:fpga"); diff --git a/lichee/linux-4.9/drivers/misc/xunfei/cpld/fpga_loader.c b/lichee/linux-4.9/drivers/misc/xunfei/cpld/fpga_loader.c new file mode 100755 index 000000000..e476faf71 --- /dev/null +++ b/lichee/linux-4.9/drivers/misc/xunfei/cpld/fpga_loader.c @@ -0,0 +1,267 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// mem define +static unsigned int map_io_base; +#define D_IO_BASE map_io_base +#define D_IO_BASE_PHY (0x01c20800) +#define D_IO_LEN (0x400) +#define D_IO_A (0) +#define D_IO_B (1) +#define D_IO_C (2) +#define D_IO_D (3) +#define D_IO_E (4) +#define D_IO_F (5) +#define D_IO_G (6) +#define D_IO_H (7) +#define D_IO_I (8) +#define D_IO_CFG0(x) (D_IO_BASE + (x * 0x24) + 0x00) +#define D_IO_CFG1(x) (D_IO_BASE + (x * 0x24) + 0x04) +#define D_IO_CFG2(x) (D_IO_BASE + (x * 0x24) + 0x08) +#define D_IO_CFG3(x) (D_IO_BASE + (x * 0x24) + 0x0c) +#define D_IO_DAT(x) (D_IO_BASE + (x * 0x24) + 0x10) +#define D_IO_DRV0(x) (D_IO_BASE + (x * 0x24) + 0x14) +#define D_IO_DRV1(x) (D_IO_BASE + (x * 0x24) + 0x18) +#define D_IO_PUL0(x) (D_IO_BASE + (x * 0x24) + 0x1c) +#define D_IO_PUL1(x) (D_IO_BASE + (x * 0x24) + 0x20) + +static struct i2c_client *fpga_client = NULL; +static const struct i2c_device_id i2c_driver_fpga_id[] = {{"i2c_fpga", 0}, {}}; +MODULE_DEVICE_TABLE(i2c, i2c_driver_fpga_id); + +static unsigned char fpga_refresh_command[] = {0x79, 0x00, 0x00}; + +static unsigned char fpga_none_command[] = {0xff, 0xff, 0xff, 0xff}; + +static const unsigned short i2c_fpga_addr[] = {0x40, I2C_CLIENT_END}; + +static struct delayed_work fpga_reset_work; + +static struct i2c_msg *i2c_recev_msg; +static int current_msg_pos; + +static void fpga_hw_init(void) { + printk("fpga_loader.c->fpga_hw_init()\n"); + + if (!D_IO_BASE) { + // printk("Timothy:D_IO_BASE is not initial yet, initial it now\n"); + D_IO_BASE = (unsigned int)ioremap(D_IO_BASE_PHY, D_IO_LEN); + if (!D_IO_BASE) { + printk("fpga loader hardware init io error\n"); + return -1; + } + } +} + +// set reset for fpga +// enable = 1:set ph7 high +// enable = 0:set ph7 low +static void set_fpga_reset(int enable) { + // printk("Timothy:fpga_loader.c->set_fpga_reset()\n"); + if (1 == enable) { + writel(readl(D_IO_DAT(D_IO_H)) | (1 << 8), D_IO_DAT(D_IO_H)); + } else { + writel(readl(D_IO_DAT(D_IO_H)) & ~(1 << 8), D_IO_DAT(D_IO_H)); + } +} + +int send_to_device(char *data, int count) { + // //printk("Timothy:fpga_loader.c->send_to_device(), count = %d\n", + //count); + int nwrite; + int i; + + if (data[0] == 0) // STOP causes this, send stop + { + // printk("the data send to device is:"); + // for(i = 1; i < count; i++) + // { + // printk("%x ", data[i]); + // } + // printk("\n"); + nwrite = i2c_master_send(fpga_client, &data[1], count - 1); + if (nwrite != count - 1) { + // printk("Timothy:not write enough, nwrite = %d, count = %d\n", + // nwrite, count); + } else { + // //printk("Timothy:write success, count = %d\n", + //count); + } + return nwrite; + } else if (data[0] == + 1) // RESTART causes this, do not send stop, just put int in buf + { + if (current_msg_pos >= 8) { + // printk("Timothy:buf is overflow, quit"); + return -2; + } + // //printk("Timothy:the data add to buf is:"); + // for(i = 1; i < count; i++) + // { + // printk("%x ", data[i]); + // } + // printk("\n"); + i2c_recev_msg[current_msg_pos].addr = i2c_fpga_addr[0]; + i2c_recev_msg[current_msg_pos].len = count - 1; + i2c_recev_msg[current_msg_pos].buf = (unsigned char *)kzalloc( + i2c_recev_msg[current_msg_pos].len * sizeof(unsigned char), + GFP_KERNEL); + memcpy(i2c_recev_msg[current_msg_pos].buf, &data[1], + i2c_recev_msg[current_msg_pos].len); + current_msg_pos++; + return count - 1; + } else if (data[0] == 2) { + // printk("Timothy:send refresh command now\n"); + nwrite = i2c_master_send(fpga_client, fpga_refresh_command, 3); + return nwrite; + } else if (data[0] == 3) { + // printk("Timothy:send none command now\n"); + nwrite = i2c_master_send(fpga_client, fpga_none_command, 4); + nwrite = i2c_master_send(fpga_client, fpga_none_command, 4); + return nwrite; + } else { + // printk("Timothy:unknow flag for send"); + return -1; + } +} + +EXPORT_SYMBOL(send_to_device); + +int receive_from_device(char *data, int count) { + // //printk("Timothy:fpga_loader.c->receive_from_device()\n"); + int nread; + int i, j; + + if (current_msg_pos >= 8) { + // printk("Timothy:buf is overflow, quit"); + return -2; + } + i2c_recev_msg[current_msg_pos].addr = i2c_fpga_addr[0]; + i2c_recev_msg[current_msg_pos].flags = I2C_M_RD | I2C_M_NO_RD_ACK; + i2c_recev_msg[current_msg_pos].len = count; + i2c_recev_msg[current_msg_pos].buf = data; + current_msg_pos++; + + // //printk("Timothy:the data send before read is:"); + // for(i = 0; i < current_msg_pos-1; i++) + // { + // for(j = 0; j < i2c_recev_msg[i].len; j++) + // { + // printk("%x ", i2c_recev_msg[i].buf[j]); + // } + // } + // printk("\n"); + + nread = i2c_transfer(fpga_client->adapter, i2c_recev_msg, current_msg_pos); + + if (nread != current_msg_pos) { + // printk("Timothy:not read enough, nread = %d, current_msg_pos = %d\n", + // nread, current_msg_pos); + } else { + // //printk("Timothy:read success, current_msg_pos = %d\n", + //current_msg_pos); + } + + // //printk("Timothy:the data read from i2c is:"); + // for(i = 0; i < count; i++) + // { + // printk("%x, ", data[i]); + // } + // printk("\n"); + for (i = 0; i < current_msg_pos - 1; i++) { + if (i2c_recev_msg[i].buf) { + kfree(i2c_recev_msg[i].buf); + i2c_recev_msg[i].buf = NULL; + } + } + current_msg_pos = 0; + + return count; +} + +EXPORT_SYMBOL(receive_from_device); + +static int i2c_driver_fpga_probe(struct i2c_client *client, + const struct i2c_device_id *id) { + // printk("Timothy:fpga_loader.c->i2c_driver_fpga_probe()\n"); + if ((client->addr == i2c_fpga_addr[0])) { + fpga_client = client; + // printk("Timothy:fpga (%x) init ok\n", client->addr); + } + return 0; +} + +static int i2c_driver_fpga_remove(struct i2c_client *client) { + // printk("Timothy:fpga_loader.c->i2c_driver_fpga_remove()\n"); + return 0; +} + +static int i2c_driver_fpga_detect(struct i2c_client *client, + struct i2c_board_info *info) { + // printk("Timothy:fpga_loader.c->i2c_driver_fpga_detect()\n"); + struct i2c_adapter *p_adapter; + const char *type_name = "i2c_fpga"; + p_adapter = client->adapter; + // printk("Timothy:adapter->nr = %d\n", p_adapter->nr); + if (2 == p_adapter->nr) { + if (info->addr == i2c_fpga_addr[0]) { + // printk("Timothy:detect fpga (%x) on i2c adapter (%d)\n", + // info->addr, p_adapter->nr); + strlcpy(info->type, type_name, I2C_NAME_SIZE); + return 0; + } + } + return ENODEV; +} + +static struct i2c_driver i2c_driver_fpga = {.class = I2C_CLASS_HWMON, + .probe = i2c_driver_fpga_probe, + .remove = i2c_driver_fpga_remove, + .id_table = i2c_driver_fpga_id, + .driver = + { + .name = "i2c_fpga", + .owner = THIS_MODULE, + }, + .detect = i2c_driver_fpga_detect, + .address_list = i2c_fpga_addr}; + +static int __init i2c_driver_fpga_init(void) { + // printk("Timothy:fpga_loader.c->i2c_driver_fpga_init()\n"); + fpga_hw_init(); + i2c_recev_msg = + (struct i2c_msg *)kzalloc(8 * sizeof(struct i2c_msg), GFP_KERNEL); + current_msg_pos = 0; + + return i2c_add_driver(&i2c_driver_fpga); +} + +static void __exit i2c_driver_fpga_exit(void) { + // printk("Timothy:fpga_loader.c->i2c_driver_fpga_exit()\n"); + if (i2c_recev_msg) { + kfree(i2c_recev_msg); + i2c_recev_msg = NULL; + } + current_msg_pos = 0; + i2c_del_driver(&i2c_driver_fpga); +} + +module_init(i2c_driver_fpga_init); +module_exit(i2c_driver_fpga_exit); + +MODULE_AUTHOR("Timothy"); +MODULE_DESCRIPTION("I2C device fpga loader"); +MODULE_LICENSE("GPL"); \ No newline at end of file diff --git a/lichee/linux-4.9/drivers/misc/xunfei/cpld/i2c_operator.c b/lichee/linux-4.9/drivers/misc/xunfei/cpld/i2c_operator.c new file mode 100755 index 000000000..5f007eec1 --- /dev/null +++ b/lichee/linux-4.9/drivers/misc/xunfei/cpld/i2c_operator.c @@ -0,0 +1,313 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GP_CLASS_NAME "i2c_operator" +#define GP_CHR_DEV_NAME "i2c_operator" +#define GP_I2C_DEV_NAME "i2c_operator_device" + +struct i2c_ioctl_msg { + int i2c_index; + int reg_addr; + int reg_val; +}; + +#define MAGIC_NUM 'A' +#define CMD_I2C_SET _IOW(MAGIC_NUM, 0, struct i2c_ioctl_msg) +#define CMD_I2C_GET _IOR(MAGIC_NUM, 1, struct i2c_ioctl_msg) + +#define CMD_MAX (1) + +static unsigned int map_io_base; +#define D_IO_BASE map_io_base +#define D_IO_BASE_PHY (0x01c20800) +#define D_IO_LEN (0x400) +#define D_IO_B (1) +#define D_IO_C (2) +#define D_IO_D (3) +#define D_IO_E (4) +#define D_IO_F (5) +#define D_IO_G (6) +#define D_IO_H (7) +#define D_IO_CFG0(x) (D_IO_BASE + (x * 0x24) + 0x00) +#define D_IO_CFG1(x) (D_IO_BASE + (x * 0x24) + 0x04) +#define D_IO_CFG2(x) (D_IO_BASE + (x * 0x24) + 0x08) +#define D_IO_CFG3(x) (D_IO_BASE + (x * 0x24) + 0x0c) +#define D_IO_DAT(x) (D_IO_BASE + (x * 0x24) + 0x10) +#define D_IO_DRV0(x) (D_IO_BASE + (x * 0x24) + 0x14) +#define D_IO_DRV1(x) (D_IO_BASE + (x * 0x24) + 0x18) +#define D_IO_PUL0(x) (D_IO_BASE + (x * 0x24) + 0x1c) +#define D_IO_PUL1(x) (D_IO_BASE + (x * 0x24) + 0x20) + +static struct class *p_gp_class; +static struct device *p_class_i2c; +static int major_num; +static unsigned char *i2c_msg; + +int send_to_device(char *data, int count); + +int receive_from_device(char *data, int count); +int cx20810_set_mode(int mode, int index); +// int led_array_set_mode(unsigned char * param, int length); +int led_array_set_enable(int enable); + +int cx20810_write_reg(int index, int addr, int regval); +int cx20810_read_reg(int index, int cmd, int *regval); + +enum { + I2C_DEVICE_FPGA = 0, + I2C_DEVICE_CX20810, + I2C_DEVICE_CX20810_0, + I2C_DEVICE_CX20810_1, + I2C_DEVICE_CX20810_2, + I2C_DEVICE_LED_ARRAY, +}; + +static void gp_hw_init(void) { + printk("i2c_operator.c->gp_hw_init()\n"); + + if (!D_IO_BASE) { + // printk("Timothy:D_IO_BASE is not initial yet, initial it now\n"); + D_IO_BASE = (unsigned int)ioremap(D_IO_BASE_PHY, D_IO_LEN); + if (!D_IO_BASE) { + printk("led array hardware init io error\n"); + return -1; + } + } + + // set pe6 output and set it high to open mute led + // writel(readl(D_IO_CFG0(D_IO_E)) & (~(0x7<<24)) | (0x1<<24), + // D_IO_CFG0(D_IO_E)); writel(readl(D_IO_DAT(D_IO_E)) | 0x1<<6, + // D_IO_DAT(D_IO_E)); +} + +// add by Timothy +// time:2015-02-09 +// start========== +// i2c设备write处理 +static ssize_t gp_i2c_write_dispatch(int len) { + // //printk("Timothy:i2c_operator.c->gp_i2c_write_dispatch(), len = %d\n", + //len); + int ret = 0; + int i; + int device_index = (int)i2c_msg[0]; + int length = len - sizeof(char); + // //printk("Timothy:device_index = %d\n", device_index); + + // all 3 cx20810 + if (I2C_DEVICE_CX20810 == device_index) { + // //printk("Timothy:operate device:cx20810\n"); + for (i = 0; i < 3; i++) { + cx20810_set_mode((int)i2c_msg[1], i); + } + return 0; + } + + else if (I2C_DEVICE_CX20810_0 == device_index) { + // //printk("Timothy:operate device:cx20810_0\n"); + return cx20810_set_mode((int)i2c_msg[1], 0); + } else if (I2C_DEVICE_CX20810_1 == device_index) { + // //printk("Timothy:operate device:cx20810_1\n"); + return cx20810_set_mode((int)i2c_msg[1], 1); + } else if (I2C_DEVICE_CX20810_2 == device_index) { + // //printk("Timothy:operate device:cx20810_2\n"); + return cx20810_set_mode((int)i2c_msg[1], 2); + } + + // LED + // else if(I2C_DEVICE_LED_ARRAY == device_index) + // { + // //printk("Timothy:operate device:led_array\n"); + // return led_array_set_mode(&i2c_msg[1], length); + // } + + // FPGA + else if (I2C_DEVICE_FPGA == device_index) { + // //printk("Timothy:operate device:FPGA, data lendth is + //%d\n", length); + ret = send_to_device((char *)&i2c_msg[1], length); + return ret; + } + return -1; +} + +static int gp_i2c_read_dispatch(int len) { + // //printk("Timothy:i2c_operator.c->gp_i2c_read_dispatch()\n"); + int ret = 0; + int device_index = (int)i2c_msg[0]; + int length = len - sizeof(char); + // //printk("Timothy:device_index = %d\n", device_index); + if (I2C_DEVICE_FPGA == device_index) // FPGA + { + // //printk("Timothy:operate device:FPGA, data lendth is + //%d\n", length); + ret = receive_from_device((char *)&i2c_msg[1], length); + return ret; + } + return -1; +} +// end========== + +static int gp_open(struct inode *pnode, struct file *pfile) { + // printk("Timothy:i2c_operator.c->gp_open()\n"); + int major = MAJOR(pnode->i_rdev); + int minor = MINOR(pnode->i_rdev); + + if (minor == 0) { + pfile->private_data = (void *)p_class_i2c; + // printk("Timothy:gp_open_i2c\n"); + } else { + pfile->private_data = (void *)NULL; + // printk("Timothy:gp_open:unknow device\n"); + } + return 0; +} + +static int gp_close(struct inode *pnode, struct file *pfile) { + pfile->private_data = (void *)NULL; + printk("gp_close\n"); + return 0; +} + +static ssize_t gp_read(struct file *pfile, char __user *puser, size_t len, + loff_t *poff) { + int nread = 0; + int i; + // //printk("Timothy:i2c_operator.c->gp_read()\n"); + if (pfile->private_data == p_class_i2c) { + // //printk("Timothy:gp_read():i2c device\n"); + i2c_msg = + (unsigned char *)kzalloc(len * sizeof(unsigned char), GFP_KERNEL); + copy_from_user((void *)i2c_msg, puser, len); + nread = gp_i2c_read_dispatch(len); + // //printk("Timothy:the data will send to user is:%d\n", + //i2c_msg[1]); + copy_to_user(puser, (void *)i2c_msg, len); + kfree(i2c_msg); + } + // //printk("Timothy:return value is %d\n", nread); + return nread; +} + +static ssize_t gp_write(struct file *pfile, const char __user *puser, + size_t len, loff_t *poff) { + // //printk("Timothy:i2c_operator.c->gp_write()\n"); + int ret = 0; + int i; + if (pfile->private_data == p_class_i2c) { + // //printk("Timothy:gp_write():i2c device\n"); + i2c_msg = + (unsigned char *)kzalloc(len * sizeof(unsigned char), GFP_KERNEL); + copy_from_user((void *)i2c_msg, puser, len); + + // //printk("Timothy:the data is "); + // for(i = 0; i < len; i++) + // { + // printk("%x ", i2c_msg[i]); + // } + // printk("\n"); + ret = gp_i2c_write_dispatch(len); + kfree(i2c_msg); + } else { + // //printk("Timothy:gp_write_null\n"); + } + // //printk("Timothy:return value is %d\n", ret); + return ret; +} + +// file operations +static long gp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { + u8 i; + int ret = 0; + struct i2c_ioctl_msg i2carg = {0}; + + printk("ioctl start cmd: %d arg: %lX\n", cmd, arg); + + if (_IOC_TYPE(cmd) != MAGIC_NUM) + return -EINVAL; + + if (_IOC_NR(cmd) > CMD_MAX) + return -EINVAL; + + printk("ioctl start\n"); + + switch (cmd) { + case CMD_I2C_SET: + ret = copy_from_user(&i2carg, (struct i2c_ioctl_msg *)arg, + sizeof(i2carg)); + if (0 == ret) { + printk("Will set i2c:%d reg:0x%x val:0x%x\n", i2carg.i2c_index, + i2carg.reg_addr, i2carg.reg_val); + } else { + printk("get user arg fail!\n"); + } + cx20810_write_reg(i2carg.i2c_index, i2carg.reg_addr, i2carg.reg_val); + break; + + case CMD_I2C_GET: + i2carg.reg_val = 0; + ret = copy_from_user(&i2carg, (struct i2c_ioctl_msg *)arg, + sizeof(i2carg)); + cx20810_read_reg(i2carg.i2c_index, i2carg.reg_addr, &(i2carg.reg_val)); + printk("Get i2c:%d reg:0x%x val:0x%x\n", i2carg.i2c_index, + i2carg.reg_addr, i2carg.reg_val); + ret = copy_to_user((void *)arg, &i2carg, sizeof(i2carg)); + + break; + + default: + break; + } + printk("ioctl end\n"); + + return ret; +} + +static struct file_operations gp_fops = { + .owner = THIS_MODULE, + .open = gp_open, + .release = gp_close, + .read = gp_read, + .write = gp_write, + .unlocked_ioctl = gp_ioctl, +}; + +static int __init i2c_operator_init(void) { + gp_hw_init(); + + major_num = register_chrdev(0, GP_CHR_DEV_NAME, &gp_fops); + if (major_num < 0) { + // printk("Timothy:gen_prov_reg_chr_err\n"); + return 1; + } + p_gp_class = class_create(THIS_MODULE, GP_CLASS_NAME); + if (p_gp_class == NULL) { + // printk("Timothy:gen_prov:class create err\n"); + } + + p_class_i2c = device_create(p_gp_class, NULL, MKDEV(major_num, 0), NULL, + GP_I2C_DEV_NAME); + if (p_class_i2c == NULL) { + // printk("Timothy:gen_prov:device_create err:i2c\n"); + return 1; + } +} + +static void __exit i2c_operator_exit(void) {} + +module_init(i2c_operator_init); +module_exit(i2c_operator_exit); + +MODULE_AUTHOR("Timothy"); +MODULE_DESCRIPTION("i2c operator driver"); +MODULE_LICENSE("GPL"); diff --git a/lichee/linux-4.9/drivers/misc/xunfei/cpld/netease_config.c b/lichee/linux-4.9/drivers/misc/xunfei/cpld/netease_config.c new file mode 100644 index 000000000..1b5d7ad35 --- /dev/null +++ b/lichee/linux-4.9/drivers/misc/xunfei/cpld/netease_config.c @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include + +static struct kset *netease_keyset = NULL; +static struct kobject cpld_ko; +extern int cx20810_set_mode(int mode, int index); +extern void netease_cpld_reset(void); + +enum { + CX20810_NORMAL_MODE = 0, + CX20810_NORMAL_MODE_SIMPLE, + CX20810_NIRMAL_MODE_CODEC3, + CX20810_NIRMAL_MODE_CODEC3_SIMPLE, + CX20810_96K_16BIT_MODE, + CX20810_48K_16BIT_MODE, +}; + +static ssize_t gen_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) { + int count = 0; + count += sprintf(buf, "Cpld init help:\n"); + count += sprintf(buf + count, "adc rst and config:echo 1 > cpld_init\n"); + count += sprintf(buf + count, "adc rst:echo 2 > cpld_init\n"); + count += sprintf(buf + count, "adc config:echo 3 > cpld_init\n"); + + return count; +} + +static ssize_t gen_attr_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + long ret = -1; + kstrtol(buf, 10, &ret); + + switch (ret) { + case 1: + printk("Adc rst and config\n"); + netease_cpld_reset(); + cx20810_set_mode(CX20810_NORMAL_MODE, 0); + cx20810_set_mode(CX20810_NORMAL_MODE, 1); + break; + case 2: + printk("Adc rst\n"); + netease_cpld_reset(); + break; + case 3: + printk("Adc config\n"); + cx20810_set_mode(CX20810_NORMAL_MODE, 0); + cx20810_set_mode(CX20810_NORMAL_MODE, 1); + break; + default: + printk("Can not read your input cmd, need help? type cat cpld_init."); + } + + printk("Do finish, Get ret:%d, count:%d, input:%s\n", ret, count, buf); + // tipa_set_vol(2 * (24-i)); + return count; +} + +static const struct sysfs_ops cpld_ktype_ops = { + .show = gen_attr_show, + .store = gen_attr_store, +}; +struct attribute cpld_init_set = { + .name = "cpld_init", + .mode = S_IRWXUGO, +}; +struct attribute *cpld_attr_group[] = {&cpld_init_set, NULL}; + +void cpld_release(struct kobject *kobj) { + printk("wzj:release %d\n", kobj->name); +} + +static struct kobj_type cpld_ko_ktype = { + .sysfs_ops = &cpld_ktype_ops, + .default_attrs = cpld_attr_group, + .release = cpld_release, +}; + +static int __init netease_config_init(void) { + printk("Begin to start netease config!\n"); + netease_keyset = kset_create_and_add("netease", NULL, NULL); + + cpld_ko.kset = netease_keyset; + kobject_init_and_add(&cpld_ko, &cpld_ko_ktype, NULL, "cpld_control"); + + return 0; +} + +module_init(netease_config_init); + +static void __exit netease_config_exit(void) {} +module_exit(netease_config_exit); + +/* Module information */ +MODULE_AUTHOR("Wang zijiao"); +MODULE_DESCRIPTION("Netease config!"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:netease_config"); \ No newline at end of file diff --git a/lichee/linux-4.9/sound/soc/sunxi/sunxi-daudio.c b/lichee/linux-4.9/sound/soc/sunxi/sunxi-daudio.c index 51d63d35a..db2d420e4 100644 --- a/lichee/linux-4.9/sound/soc/sunxi/sunxi-daudio.c +++ b/lichee/linux-4.9/sound/soc/sunxi/sunxi-daudio.c @@ -12,25 +12,25 @@ * */ +#include +#include +#include +#include +#include #include #include -#include -#include #include -#include #include -#include -#include +#include #include +#include #include #include -#include #include -#include #include +#include +#include #include -#include -#include #include "sunxi-daudio.h" #include "sunxi-pcm.h" @@ -38,104 +38,104 @@ #include "sunxi-mad.h" #endif -#define DRV_NAME "sunxi-daudio" +#define DRV_NAME "sunxi-daudio" -#define SUNXI_DAUDIO_EXTERNAL_TYPE 1 -#define SUNXI_DAUDIO_TDMHDMI_TYPE 2 +#define SUNXI_DAUDIO_EXTERNAL_TYPE 1 +#define SUNXI_DAUDIO_TDMHDMI_TYPE 2 -#define SUNXI_DAUDIO_DRQDST(sunxi_daudio, x) \ - ((sunxi_daudio)->playback_dma_param.dma_drq_type_num = \ - DRQDST_DAUDIO_##x##_TX) -#define SUNXI_DAUDIO_DRQSRC(sunxi_daudio, x) \ - ((sunxi_daudio)->capture_dma_param.dma_drq_type_num = \ - DRQSRC_DAUDIO_##x##_RX) +#define SUNXI_DAUDIO_DRQDST(sunxi_daudio, x) \ + ((sunxi_daudio)->playback_dma_param.dma_drq_type_num = \ + DRQDST_DAUDIO_##x##_TX) +#define SUNXI_DAUDIO_DRQSRC(sunxi_daudio, x) \ + ((sunxi_daudio)->capture_dma_param.dma_drq_type_num = \ + DRQSRC_DAUDIO_##x##_RX) struct sunxi_daudio_platform_data { - unsigned int daudio_type; - unsigned int external_type; - unsigned int daudio_master; - unsigned int pcm_lrck_period; - unsigned int slot_width_select; - unsigned int audio_format; - unsigned int signal_inversion; - unsigned int frame_type; - unsigned int tdm_config; - unsigned int tdm_num; - unsigned int mclk_div; + unsigned int daudio_type; + unsigned int external_type; + unsigned int daudio_master; + unsigned int pcm_lrck_period; + unsigned int slot_width_select; + unsigned int audio_format; + unsigned int signal_inversion; + unsigned int frame_type; + unsigned int tdm_config; + unsigned int tdm_num; + unsigned int mclk_div; }; struct voltage_supply { - struct regulator *daudio_regulator; - const char *regulator_name; + struct regulator *daudio_regulator; + const char *regulator_name; }; struct sunxi_daudio_info { - struct device *dev; - struct regmap *regmap; - void __iomem *membase; - struct clk *pllclk; - struct clk *moduleclk; - struct voltage_supply vol_supply; - struct mutex mutex; - struct sunxi_dma_params playback_dma_param; - struct sunxi_dma_params capture_dma_param; - struct pinctrl *pinctrl; - struct pinctrl_state *pinstate; - struct pinctrl_state *pinstate_sleep; - struct sunxi_daudio_platform_data *pdata; - unsigned int hub_mode; - unsigned int hdmi_en; - struct delayed_work resume_work; - struct snd_soc_dai *cpu_dai; + struct device *dev; + struct regmap *regmap; + void __iomem *membase; + struct clk *pllclk; + struct clk *moduleclk; + struct voltage_supply vol_supply; + struct mutex mutex; + struct sunxi_dma_params playback_dma_param; + struct sunxi_dma_params capture_dma_param; + struct pinctrl *pinctrl; + struct pinctrl_state *pinstate; + struct pinctrl_state *pinstate_sleep; + struct sunxi_daudio_platform_data *pdata; + unsigned int hub_mode; + unsigned int hdmi_en; + struct delayed_work resume_work; + struct snd_soc_dai *cpu_dai; #ifdef CONFIG_SND_SUNXI_MAD - struct resource res; - unsigned int mad_bind; - unsigned int lpsd_chan_sel; - unsigned int mad_standby_chan_sel; - unsigned int audio_src_chan_num; - unsigned int capture_en; + struct resource res; + unsigned int mad_bind; + unsigned int lpsd_chan_sel; + unsigned int mad_standby_chan_sel; + unsigned int audio_src_chan_num; + unsigned int capture_en; #endif }; static struct reg_label reg_labels[] = { - REG_LABEL(SUNXI_DAUDIO_CTL), - REG_LABEL(SUNXI_DAUDIO_FMT0), - REG_LABEL(SUNXI_DAUDIO_FMT1), - REG_LABEL(SUNXI_DAUDIO_INTSTA), - REG_LABEL(SUNXI_DAUDIO_FIFOCTL), - REG_LABEL(SUNXI_DAUDIO_FIFOSTA), - REG_LABEL(SUNXI_DAUDIO_INTCTL), - REG_LABEL(SUNXI_DAUDIO_CLKDIV), - REG_LABEL(SUNXI_DAUDIO_TXCNT), - REG_LABEL(SUNXI_DAUDIO_RXCNT), - REG_LABEL(SUNXI_DAUDIO_CHCFG), - REG_LABEL(SUNXI_DAUDIO_TX0CHSEL), - REG_LABEL(SUNXI_DAUDIO_TX1CHSEL), - REG_LABEL(SUNXI_DAUDIO_TX2CHSEL), - REG_LABEL(SUNXI_DAUDIO_TX3CHSEL), + REG_LABEL(SUNXI_DAUDIO_CTL), + REG_LABEL(SUNXI_DAUDIO_FMT0), + REG_LABEL(SUNXI_DAUDIO_FMT1), + REG_LABEL(SUNXI_DAUDIO_INTSTA), + REG_LABEL(SUNXI_DAUDIO_FIFOCTL), + REG_LABEL(SUNXI_DAUDIO_FIFOSTA), + REG_LABEL(SUNXI_DAUDIO_INTCTL), + REG_LABEL(SUNXI_DAUDIO_CLKDIV), + REG_LABEL(SUNXI_DAUDIO_TXCNT), + REG_LABEL(SUNXI_DAUDIO_RXCNT), + REG_LABEL(SUNXI_DAUDIO_CHCFG), + REG_LABEL(SUNXI_DAUDIO_TX0CHSEL), + REG_LABEL(SUNXI_DAUDIO_TX1CHSEL), + REG_LABEL(SUNXI_DAUDIO_TX2CHSEL), + REG_LABEL(SUNXI_DAUDIO_TX3CHSEL), #if defined(SUNXI_DAUDIO_MODE_B) - REG_LABEL(SUNXI_DAUDIO_TX0CHMAP0), - REG_LABEL(SUNXI_DAUDIO_TX0CHMAP1), - REG_LABEL(SUNXI_DAUDIO_TX1CHMAP0), - REG_LABEL(SUNXI_DAUDIO_TX1CHMAP1), - REG_LABEL(SUNXI_DAUDIO_TX2CHMAP0), - REG_LABEL(SUNXI_DAUDIO_TX2CHMAP1), - REG_LABEL(SUNXI_DAUDIO_TX3CHMAP0), - REG_LABEL(SUNXI_DAUDIO_TX3CHMAP1), - REG_LABEL(SUNXI_DAUDIO_RXCHSEL), - REG_LABEL(SUNXI_DAUDIO_RXCHMAP0), - REG_LABEL(SUNXI_DAUDIO_RXCHMAP1), - REG_LABEL(SUNXI_DAUDIO_DEBUG), + REG_LABEL(SUNXI_DAUDIO_TX0CHMAP0), + REG_LABEL(SUNXI_DAUDIO_TX0CHMAP1), + REG_LABEL(SUNXI_DAUDIO_TX1CHMAP0), + REG_LABEL(SUNXI_DAUDIO_TX1CHMAP1), + REG_LABEL(SUNXI_DAUDIO_TX2CHMAP0), + REG_LABEL(SUNXI_DAUDIO_TX2CHMAP1), + REG_LABEL(SUNXI_DAUDIO_TX3CHMAP0), + REG_LABEL(SUNXI_DAUDIO_TX3CHMAP1), + REG_LABEL(SUNXI_DAUDIO_RXCHSEL), + REG_LABEL(SUNXI_DAUDIO_RXCHMAP0), + REG_LABEL(SUNXI_DAUDIO_RXCHMAP1), + REG_LABEL(SUNXI_DAUDIO_DEBUG), #else - REG_LABEL(SUNXI_DAUDIO_TX0CHMAP0), - REG_LABEL(SUNXI_DAUDIO_TX1CHMAP0), - REG_LABEL(SUNXI_DAUDIO_TX2CHMAP0), - REG_LABEL(SUNXI_DAUDIO_TX3CHMAP0), - REG_LABEL(SUNXI_DAUDIO_RXCHSEL), - REG_LABEL(SUNXI_DAUDIO_RXCHMAP), - REG_LABEL(SUNXI_DAUDIO_DEBUG), + REG_LABEL(SUNXI_DAUDIO_TX0CHMAP0), + REG_LABEL(SUNXI_DAUDIO_TX1CHMAP0), + REG_LABEL(SUNXI_DAUDIO_TX2CHMAP0), + REG_LABEL(SUNXI_DAUDIO_TX3CHMAP0), + REG_LABEL(SUNXI_DAUDIO_RXCHSEL), + REG_LABEL(SUNXI_DAUDIO_RXCHMAP), + REG_LABEL(SUNXI_DAUDIO_DEBUG), #endif - REG_LABEL_END, + REG_LABEL_END, }; static struct sunxi_daudio_info *sunxi_daudio_global[DAUDIO_NUM_MAX]; @@ -151,880 +151,821 @@ static int device_count; /* * Some codec on electric timing need debugging */ -int daudio_set_clk_onoff(struct snd_soc_dai *dai, u32 mask, u32 onoff) -{ - struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); - - switch (mask) { - case SUNXI_DAUDIO_BCLK: - if (onoff) - regmap_update_bits(sunxi_daudio->regmap, - SUNXI_DAUDIO_FIFOCTL, - (1<regmap, - SUNXI_DAUDIO_FIFOCTL, - (1<regmap, - SUNXI_DAUDIO_FIFOCTL, - (1<regmap, - SUNXI_DAUDIO_FIFOCTL, - (1<regmap, - SUNXI_DAUDIO_CLKDIV, - (1<regmap, - SUNXI_DAUDIO_CLKDIV, - (1<regmap, - SUNXI_DAUDIO_CTL, - (1<regmap, - SUNXI_DAUDIO_CTL, - (1<regmap, SUNXI_DAUDIO_FIFOCTL, + (1 << BCLK_OUT), (1 << BCLK_OUT)); + else + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FIFOCTL, + (1 << BCLK_OUT), (0 << BCLK_OUT)); + break; + case SUNXI_DAUDIO_LRCK: + if (onoff) + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FIFOCTL, + (1 << LRCK_OUT), (1 << LRCK_OUT)); + else + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FIFOCTL, + (1 << LRCK_OUT), (0 << LRCK_OUT)); + break; + case SUNXI_DAUDIO_MCLK: + if (onoff) + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CLKDIV, + (1 << MCLKOUT_EN), (1 << MCLKOUT_EN)); + else + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CLKDIV, + (1 << MCLKOUT_EN), (0 << MCLKOUT_EN)); + break; + case SUNXI_DAUDIO_GEN: + if (onoff) + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << GLOBAL_EN), (1 << GLOBAL_EN)); + else + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << GLOBAL_EN), (0 << GLOBAL_EN)); + break; + default: + return -EINVAL; + } + return 0; } EXPORT_SYMBOL_GPL(daudio_set_clk_onoff); - static int sunxi_daudio_get_hub_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - struct snd_soc_codec *codec = snd_soc_component_to_codec(component); - struct sunxi_daudio_info *sunxi_daudio = - snd_soc_codec_get_drvdata(codec); - unsigned int reg_val; + struct snd_ctl_elem_value *ucontrol) { + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); + struct sunxi_daudio_info *sunxi_daudio = snd_soc_codec_get_drvdata(codec); + unsigned int reg_val; - regmap_read(sunxi_daudio->regmap, SUNXI_DAUDIO_FIFOCTL, ®_val); + regmap_read(sunxi_daudio->regmap, SUNXI_DAUDIO_FIFOCTL, ®_val); - ucontrol->value.integer.value[0] = ((reg_val & (1<value.integer.value[0] = ((reg_val & (1 << HUB_EN)) ? 2 : 1); + return 0; } static int sunxi_daudio_set_hub_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - struct snd_soc_codec *codec = snd_soc_component_to_codec(component); - struct sunxi_daudio_info *sunxi_daudio = - snd_soc_codec_get_drvdata(codec); + struct snd_ctl_elem_value *ucontrol) { + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); + struct sunxi_daudio_info *sunxi_daudio = snd_soc_codec_get_drvdata(codec); - switch (ucontrol->value.integer.value[0]) { - case 0: - case 1: - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FIFOCTL, - (1<regmap, SUNXI_DAUDIO_CTL, - (1<regmap, SUNXI_DAUDIO_FIFOCTL, - (1<regmap, SUNXI_DAUDIO_CTL, - (1<value.integer.value[0]) { + case 0: + case 1: + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FIFOCTL, + (1 << HUB_EN), (0 << HUB_EN)); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << CTL_TXEN), (0 << CTL_TXEN)); + break; + case 2: + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FIFOCTL, + (1 << HUB_EN), (1 << HUB_EN)); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << CTL_TXEN), (1 << CTL_TXEN)); + break; + default: + return -EINVAL; + } + return 0; } -static const char *daudio_format_function[] = {"null", - "hub_disable", "hub_enable"}; +static const char *daudio_format_function[] = {"null", "hub_disable", + "hub_enable"}; static const struct soc_enum daudio_format_enum[] = { - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(daudio_format_function), - daudio_format_function), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(daudio_format_function), + daudio_format_function), }; #ifdef CONFIG_SND_SUNXI_MAD /*lpsd channel sel*/ static int sunxi_daudio_set_lpsd_chan(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - struct snd_soc_codec *codec = snd_soc_component_to_codec(component); - struct sunxi_daudio_info *sunxi_daudio = - snd_soc_codec_get_drvdata(codec); + struct snd_ctl_elem_value *ucontrol) { + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); + struct sunxi_daudio_info *sunxi_daudio = snd_soc_codec_get_drvdata(codec); - sunxi_daudio->lpsd_chan_sel = ucontrol->value.integer.value[0]; - return 0; + sunxi_daudio->lpsd_chan_sel = ucontrol->value.integer.value[0]; + return 0; } static int sunxi_daudio_get_lpsd_chan(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - struct snd_soc_codec *codec = snd_soc_component_to_codec(component); - struct sunxi_daudio_info *sunxi_daudio = - snd_soc_codec_get_drvdata(codec); + struct snd_ctl_elem_value *ucontrol) { + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); + struct sunxi_daudio_info *sunxi_daudio = snd_soc_codec_get_drvdata(codec); - ucontrol->value.integer.value[0] = sunxi_daudio->lpsd_chan_sel; - return 0; + ucontrol->value.integer.value[0] = sunxi_daudio->lpsd_chan_sel; + return 0; } - -static const char *lpsd_chan_sel_function[] = {"NULL", "1st_chan", "2nd_chan", - "3rd_chan", "4th_chan", "5th_chan", "6th_chan", "7th_chan", "8th_chan"}; +static const char *lpsd_chan_sel_function[] = { + "NULL", "1st_chan", "2nd_chan", "3rd_chan", "4th_chan", + "5th_chan", "6th_chan", "7th_chan", "8th_chan"}; static const struct soc_enum lpsd_chan_sel_enum[] = { - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lpsd_chan_sel_function), - lpsd_chan_sel_function), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lpsd_chan_sel_function), + lpsd_chan_sel_function), }; /*mad_standby channel sel*/ -static int sunxi_daudio_set_mad_standby_chan(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - struct snd_soc_codec *codec = snd_soc_component_to_codec(component); - struct sunxi_daudio_info *sunxi_daudio = - snd_soc_codec_get_drvdata(codec); +static int +sunxi_daudio_set_mad_standby_chan(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); + struct sunxi_daudio_info *sunxi_daudio = snd_soc_codec_get_drvdata(codec); - sunxi_daudio->mad_standby_chan_sel = ucontrol->value.integer.value[0]; - return 0; + sunxi_daudio->mad_standby_chan_sel = ucontrol->value.integer.value[0]; + return 0; } -static int sunxi_daudio_get_mad_standby_chan(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - struct snd_soc_codec *codec = snd_soc_component_to_codec(component); - struct sunxi_daudio_info *sunxi_daudio = - snd_soc_codec_get_drvdata(codec); +static int +sunxi_daudio_get_mad_standby_chan(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); + struct sunxi_daudio_info *sunxi_daudio = snd_soc_codec_get_drvdata(codec); - ucontrol->value.integer.value[0] = sunxi_daudio->mad_standby_chan_sel; - return 0; + ucontrol->value.integer.value[0] = sunxi_daudio->mad_standby_chan_sel; + return 0; } -static const char *mad_standby_chan_sel_function[] = { - "Zero chan", "Two chan", "Four chan"}; +static const char *mad_standby_chan_sel_function[] = {"Zero chan", "Two chan", + "Four chan"}; static const struct soc_enum mad_standby_chan_sel_enum[] = { - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mad_standby_chan_sel_function), - mad_standby_chan_sel_function), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mad_standby_chan_sel_function), + mad_standby_chan_sel_function), }; #endif /* dts pcm Audio Mode Select */ static const struct snd_kcontrol_new sunxi_daudio_controls[] = { - SOC_ENUM_EXT("sunxi daudio audio hub mode", daudio_format_enum[0], - sunxi_daudio_get_hub_mode, sunxi_daudio_set_hub_mode), - SOC_SINGLE("sunxi daudio loopback debug", SUNXI_DAUDIO_CTL, - LOOP_EN, 1, 0), + SOC_ENUM_EXT("sunxi daudio audio hub mode", daudio_format_enum[0], + sunxi_daudio_get_hub_mode, sunxi_daudio_set_hub_mode), + SOC_SINGLE("sunxi daudio loopback debug", SUNXI_DAUDIO_CTL, LOOP_EN, 1, 0), #ifdef CONFIG_SND_SUNXI_MAD - SOC_ENUM_EXT("lpsd channel sel Function", lpsd_chan_sel_enum[0], - sunxi_daudio_get_lpsd_chan, sunxi_daudio_set_lpsd_chan), - SOC_ENUM_EXT("mad_standby channel sel Function", mad_standby_chan_sel_enum[0], - sunxi_daudio_get_mad_standby_chan, sunxi_daudio_set_mad_standby_chan), + SOC_ENUM_EXT("lpsd channel sel Function", lpsd_chan_sel_enum[0], + sunxi_daudio_get_lpsd_chan, sunxi_daudio_set_lpsd_chan), + SOC_ENUM_EXT( + "mad_standby channel sel Function", mad_standby_chan_sel_enum[0], + sunxi_daudio_get_mad_standby_chan, sunxi_daudio_set_mad_standby_chan), #endif }; static void sunxi_daudio_txctrl_enable(struct sunxi_daudio_info *sunxi_daudio, - int enable) -{ - pr_debug("Enter %s, enable %d\n", __func__, enable); - if (enable) { - /* HDMI audio Transmit Clock just enable at startup */ - if (sunxi_daudio->pdata->daudio_type - != SUNXI_DAUDIO_TDMHDMI_TYPE) - regmap_update_bits(sunxi_daudio->regmap, - SUNXI_DAUDIO_CTL, - (1<regmap, SUNXI_DAUDIO_INTCTL, - (1<regmap, SUNXI_DAUDIO_INTCTL, - (1<pdata->daudio_type - != SUNXI_DAUDIO_TDMHDMI_TYPE) - regmap_update_bits(sunxi_daudio->regmap, - SUNXI_DAUDIO_CTL, - (1<pdata->daudio_type != SUNXI_DAUDIO_TDMHDMI_TYPE) + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << CTL_TXEN), (1 << CTL_TXEN)); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_INTCTL, + (1 << TXDRQEN), (1 << TXDRQEN)); + } else { + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_INTCTL, + (1 << TXDRQEN), (0 << TXDRQEN)); + if (sunxi_daudio->pdata->daudio_type != SUNXI_DAUDIO_TDMHDMI_TYPE) + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << CTL_TXEN), (0 << CTL_TXEN)); + } + pr_debug("End %s, enable %d\n", __func__, enable); } static void sunxi_daudio_rxctrl_enable(struct sunxi_daudio_info *sunxi_daudio, - int enable) -{ - if (enable) { - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, - (1<regmap, SUNXI_DAUDIO_INTCTL, - (1<regmap, SUNXI_DAUDIO_INTCTL, - (1<regmap, SUNXI_DAUDIO_CTL, - (1<regmap, SUNXI_DAUDIO_CTL, + (1 << CTL_RXEN), (1 << CTL_RXEN)); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_INTCTL, + (1 << RXDRQEN), (1 << RXDRQEN)); + } else { + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_INTCTL, + (1 << RXDRQEN), (0 << RXDRQEN)); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << CTL_RXEN), (0 << CTL_RXEN)); + } } static int sunxi_daudio_global_enable(struct sunxi_daudio_info *sunxi_daudio, - int enable) -{ - if (enable) { - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, - (1<hdmi_en) { - regmap_update_bits(sunxi_daudio->regmap, - SUNXI_DAUDIO_CTL, (1<regmap, - SUNXI_DAUDIO_CTL, (1<regmap, - SUNXI_DAUDIO_CTL, (1<regmap, SUNXI_DAUDIO_CTL, - (1<regmap, SUNXI_DAUDIO_CTL, - (1<regmap, SUNXI_DAUDIO_CTL, - (1<hdmi_en) { - regmap_update_bits(sunxi_daudio->regmap, - SUNXI_DAUDIO_CTL, (1<regmap, - SUNXI_DAUDIO_CTL, (1<regmap, - SUNXI_DAUDIO_CTL, (1<regmap, SUNXI_DAUDIO_CTL, + (1 << SDO0_EN), (1 << SDO0_EN)); + if (sunxi_daudio->hdmi_en) { + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << SDO1_EN), (1 << SDO1_EN)); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << SDO2_EN), (1 << SDO2_EN)); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << SDO3_EN), (1 << SDO3_EN)); + } + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << GLOBAL_EN), (1 << GLOBAL_EN)); + } else { + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << GLOBAL_EN), (0 << GLOBAL_EN)); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << SDO0_EN), (0 << SDO0_EN)); + if (sunxi_daudio->hdmi_en) { + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << SDO1_EN), (0 << SDO1_EN)); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << SDO2_EN), (0 << SDO2_EN)); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << SDO3_EN), (0 << SDO3_EN)); + } + } + return 0; } -static int sunxi_daudio_mclk_setting(struct sunxi_daudio_info *sunxi_daudio) -{ - unsigned int mclk_div; +static int sunxi_daudio_mclk_setting(struct sunxi_daudio_info *sunxi_daudio) { + unsigned int mclk_div; - if (sunxi_daudio->pdata->mclk_div) { - switch (sunxi_daudio->pdata->mclk_div) { - case 1: - mclk_div = SUNXI_DAUDIO_MCLK_DIV_1; - break; - case 2: - mclk_div = SUNXI_DAUDIO_MCLK_DIV_2; - break; - case 4: - mclk_div = SUNXI_DAUDIO_MCLK_DIV_3; - break; - case 6: - mclk_div = SUNXI_DAUDIO_MCLK_DIV_4; - break; - case 8: - mclk_div = SUNXI_DAUDIO_MCLK_DIV_5; - break; - case 12: - mclk_div = SUNXI_DAUDIO_MCLK_DIV_6; - break; - case 16: - mclk_div = SUNXI_DAUDIO_MCLK_DIV_7; - break; - case 24: - mclk_div = SUNXI_DAUDIO_MCLK_DIV_8; - break; - case 32: - mclk_div = SUNXI_DAUDIO_MCLK_DIV_9; - break; - case 48: - mclk_div = SUNXI_DAUDIO_MCLK_DIV_10; - break; - case 64: - mclk_div = SUNXI_DAUDIO_MCLK_DIV_11; - break; - case 96: - mclk_div = SUNXI_DAUDIO_MCLK_DIV_12; - break; - case 128: - mclk_div = SUNXI_DAUDIO_MCLK_DIV_13; - break; - case 176: - mclk_div = SUNXI_DAUDIO_MCLK_DIV_14; - break; - case 192: - mclk_div = SUNXI_DAUDIO_MCLK_DIV_15; - break; - default: - dev_err(sunxi_daudio->dev, "unsupport mclk_div\n"); - return -EINVAL; - } - /* setting Mclk as external codec input clk */ - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CLKDIV, - (SUNXI_DAUDIO_MCLK_DIV_MASK<regmap, SUNXI_DAUDIO_CLKDIV, - (1<regmap, SUNXI_DAUDIO_CLKDIV, - (1<pdata->mclk_div) { + switch (sunxi_daudio->pdata->mclk_div) { + case 1: + mclk_div = SUNXI_DAUDIO_MCLK_DIV_1; + break; + case 2: + mclk_div = SUNXI_DAUDIO_MCLK_DIV_2; + break; + case 4: + mclk_div = SUNXI_DAUDIO_MCLK_DIV_3; + break; + case 6: + mclk_div = SUNXI_DAUDIO_MCLK_DIV_4; + break; + case 8: + mclk_div = SUNXI_DAUDIO_MCLK_DIV_5; + break; + case 12: + mclk_div = SUNXI_DAUDIO_MCLK_DIV_6; + break; + case 16: + mclk_div = SUNXI_DAUDIO_MCLK_DIV_7; + break; + case 24: + mclk_div = SUNXI_DAUDIO_MCLK_DIV_8; + break; + case 32: + mclk_div = SUNXI_DAUDIO_MCLK_DIV_9; + break; + case 48: + mclk_div = SUNXI_DAUDIO_MCLK_DIV_10; + break; + case 64: + mclk_div = SUNXI_DAUDIO_MCLK_DIV_11; + break; + case 96: + mclk_div = SUNXI_DAUDIO_MCLK_DIV_12; + break; + case 128: + mclk_div = SUNXI_DAUDIO_MCLK_DIV_13; + break; + case 176: + mclk_div = SUNXI_DAUDIO_MCLK_DIV_14; + break; + case 192: + mclk_div = SUNXI_DAUDIO_MCLK_DIV_15; + break; + default: + dev_err(sunxi_daudio->dev, "unsupport mclk_div\n"); + return -EINVAL; + } + /* setting Mclk as external codec input clk */ + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CLKDIV, + (SUNXI_DAUDIO_MCLK_DIV_MASK << MCLK_DIV), + (mclk_div << MCLK_DIV)); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CLKDIV, + (1 << MCLKOUT_EN), (1 << MCLKOUT_EN)); + + printk("wzj:mclk enable!mdiv:%d\n", mclk_div); + } else { + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CLKDIV, + (1 << MCLKOUT_EN), (0 << MCLKOUT_EN)); + } + return 0; } static int sunxi_daudio_init_fmt(struct sunxi_daudio_info *sunxi_daudio, - unsigned int fmt) -{ - unsigned int offset, mode; - unsigned int lrck_polarity, brck_polarity; + unsigned int fmt) { + unsigned int offset, mode; + unsigned int lrck_polarity, brck_polarity; - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, - (SUNXI_DAUDIO_LRCK_OUT_MASK<regmap, SUNXI_DAUDIO_CTL, - (SUNXI_DAUDIO_LRCK_OUT_MASK<dev, "unknown maser/slave format\n"); - return -EINVAL; - } + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (SUNXI_DAUDIO_LRCK_OUT_MASK << LRCK_OUT), + (SUNXI_DAUDIO_LRCK_OUT_DISABLE << LRCK_OUT)); + break; + case SND_SOC_DAIFMT_CBS_CFS: + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (SUNXI_DAUDIO_LRCK_OUT_MASK << LRCK_OUT), + (SUNXI_DAUDIO_LRCK_OUT_ENABLE << LRCK_OUT)); + break; + default: + dev_err(sunxi_daudio->dev, "unknown maser/slave format\n"); + return -EINVAL; + } - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - offset = SUNXI_DAUDIO_TX_OFFSET_1; - mode = SUNXI_DAUDIO_MODE_CTL_I2S; - break; - case SND_SOC_DAIFMT_RIGHT_J: - offset = SUNXI_DAUDIO_TX_OFFSET_0; - mode = SUNXI_DAUDIO_MODE_CTL_RIGHT; - break; - case SND_SOC_DAIFMT_LEFT_J: - offset = SUNXI_DAUDIO_TX_OFFSET_0; - mode = SUNXI_DAUDIO_MODE_CTL_LEFT; - break; - case SND_SOC_DAIFMT_DSP_A: - offset = SUNXI_DAUDIO_TX_OFFSET_1; - mode = SUNXI_DAUDIO_MODE_CTL_PCM; - break; - case SND_SOC_DAIFMT_DSP_B: - offset = SUNXI_DAUDIO_TX_OFFSET_0; - mode = SUNXI_DAUDIO_MODE_CTL_PCM; - break; - default: - dev_err(sunxi_daudio->dev, "format setting failed\n"); - return -EINVAL; - } - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, - (SUNXI_DAUDIO_MODE_CTL_MASK<regmap, SUNXI_DAUDIO_TX0CHSEL, - (SUNXI_DAUDIO_TX_OFFSET_MASK<hdmi_en) { - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_TX1CHSEL, - (SUNXI_DAUDIO_TX_OFFSET_MASK<regmap, SUNXI_DAUDIO_TX2CHSEL, - (SUNXI_DAUDIO_TX_OFFSET_MASK<regmap, SUNXI_DAUDIO_TX3CHSEL, - (SUNXI_DAUDIO_TX_OFFSET_MASK<dev, "format setting failed\n"); + return -EINVAL; + } + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (SUNXI_DAUDIO_MODE_CTL_MASK << MODE_SEL), + (mode << MODE_SEL)); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_TX0CHSEL, + (SUNXI_DAUDIO_TX_OFFSET_MASK << TX_OFFSET), + (offset << TX_OFFSET)); + if (sunxi_daudio->hdmi_en) { + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_TX1CHSEL, + (SUNXI_DAUDIO_TX_OFFSET_MASK << TX_OFFSET), + (offset << TX_OFFSET)); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_TX2CHSEL, + (SUNXI_DAUDIO_TX_OFFSET_MASK << TX_OFFSET), + (offset << TX_OFFSET)); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_TX3CHSEL, + (SUNXI_DAUDIO_TX_OFFSET_MASK << TX_OFFSET), + (offset << TX_OFFSET)); + } - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_RXCHSEL, - (SUNXI_DAUDIO_RX_OFFSET_MASK<regmap, SUNXI_DAUDIO_RXCHSEL, + (SUNXI_DAUDIO_RX_OFFSET_MASK << RX_OFFSET), + (offset << RX_OFFSET)); - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - lrck_polarity = SUNXI_DAUDIO_LRCK_POLARITY_NOR; - brck_polarity = SUNXI_DAUDIO_BCLK_POLARITY_NOR; - break; - case SND_SOC_DAIFMT_NB_IF: - lrck_polarity = SUNXI_DAUDIO_LRCK_POLARITY_INV; - brck_polarity = SUNXI_DAUDIO_BCLK_POLARITY_NOR; - break; - case SND_SOC_DAIFMT_IB_NF: - lrck_polarity = SUNXI_DAUDIO_LRCK_POLARITY_NOR; - brck_polarity = SUNXI_DAUDIO_BCLK_POLARITY_INV; - break; - case SND_SOC_DAIFMT_IB_IF: - lrck_polarity = SUNXI_DAUDIO_LRCK_POLARITY_INV; - brck_polarity = SUNXI_DAUDIO_BCLK_POLARITY_INV; - break; - default: - dev_err(sunxi_daudio->dev, "invert clk setting failed\n"); - return -EINVAL; - } - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FMT0, - (1<regmap, SUNXI_DAUDIO_FMT0, - (1<dev, "invert clk setting failed\n"); + return -EINVAL; + } + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FMT0, + (1 << LRCK_POLARITY), (lrck_polarity << LRCK_POLARITY)); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FMT0, + (1 << BRCK_POLARITY), (brck_polarity << BRCK_POLARITY)); + return 0; } -static int sunxi_daudio_init(struct sunxi_daudio_info *sunxi_daudio) -{ - struct sunxi_daudio_platform_data *pdat = sunxi_daudio->pdata; +static int sunxi_daudio_init(struct sunxi_daudio_info *sunxi_daudio) { + struct sunxi_daudio_platform_data *pdat = sunxi_daudio->pdata; - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FMT0, - (1<frame_type<regmap, SUNXI_DAUDIO_FMT0, - (SUNXI_DAUDIO_LRCK_PERIOD_MASK)<pcm_lrck_period-1)<regmap, SUNXI_DAUDIO_FMT0, + (1 << LRCK_WIDTH), (pdat->frame_type << LRCK_WIDTH)); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FMT0, + (SUNXI_DAUDIO_LRCK_PERIOD_MASK) << LRCK_PERIOD, + ((pdat->pcm_lrck_period - 1) << LRCK_PERIOD)); - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FMT0, - (SUNXI_DAUDIO_SLOT_WIDTH_MASK<slot_width_select>>2)-1)<regmap, SUNXI_DAUDIO_FMT0, + (SUNXI_DAUDIO_SLOT_WIDTH_MASK << SLOT_WIDTH), + (((pdat->slot_width_select >> 2) - 1) << SLOT_WIDTH)); - /* - * MSB on the transmit format, always be first. - * default using Linear-PCM, without no companding. - * A-law or U-law not working ok. - */ - regmap_write(sunxi_daudio->regmap, - SUNXI_DAUDIO_FMT1, SUNXI_DAUDIO_FMT1_DEF); + /* + * MSB on the transmit format, always be first. + * default using Linear-PCM, without no companding. + * A-law or U-law not working ok. + */ + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_FMT1, + SUNXI_DAUDIO_FMT1_DEF); - sunxi_daudio_init_fmt(sunxi_daudio, (pdat->audio_format - | (pdat->signal_inversion<daudio_master<audio_format | + (pdat->signal_inversion << SND_SOC_DAIFMT_SIG_SHIFT) | + (pdat->daudio_master << SND_SOC_DAIFMT_MASTER_SHIFT))); - return sunxi_daudio_mclk_setting(sunxi_daudio); + return sunxi_daudio_mclk_setting(sunxi_daudio); } static int sunxi_daudio_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) -{ - struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_card *card = rtd->card; - struct sunxi_hdmi_priv *sunxi_hdmi = snd_soc_card_get_drvdata(card); + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) { + struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct sunxi_hdmi_priv *sunxi_hdmi = snd_soc_card_get_drvdata(card); #ifdef SUNXI_HDMI_AUDIO_ENABLE - unsigned int reg_val; + unsigned int reg_val; #endif - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - /* - * Special procesing for hdmi, HDMI card name is - * "sndhdmi" or sndhdmiraw. if card not HDMI, - * strstr func just return NULL, jump to right section. - * Not HDMI card, sunxi_hdmi maybe a NULL pointer. - */ - if (sunxi_daudio->pdata->daudio_type == - SUNXI_DAUDIO_TDMHDMI_TYPE - && (sunxi_hdmi->hdmi_format > 1)) { - regmap_update_bits(sunxi_daudio->regmap, - SUNXI_DAUDIO_FMT0, - (SUNXI_DAUDIO_SR_MASK<regmap, - SUNXI_DAUDIO_FIFOCTL, - (SUNXI_DAUDIO_TXIM_MASK<regmap, - SUNXI_DAUDIO_FMT0, - (SUNXI_DAUDIO_SR_MASK<stream == SNDRV_PCM_STREAM_PLAYBACK) - regmap_update_bits(sunxi_daudio->regmap, - SUNXI_DAUDIO_FIFOCTL, - (SUNXI_DAUDIO_TXIM_MASK<regmap, - SUNXI_DAUDIO_FIFOCTL, - (SUNXI_DAUDIO_RXOM_MASK<regmap, SUNXI_DAUDIO_FMT0, - (SUNXI_DAUDIO_SR_MASK<stream == SNDRV_PCM_STREAM_PLAYBACK) - regmap_update_bits(sunxi_daudio->regmap, - SUNXI_DAUDIO_FIFOCTL, - (SUNXI_DAUDIO_TXIM_MASK<regmap, - SUNXI_DAUDIO_FIFOCTL, - (SUNXI_DAUDIO_RXOM_MASK<regmap, SUNXI_DAUDIO_FMT0, - (SUNXI_DAUDIO_SR_MASK<stream == SNDRV_PCM_STREAM_PLAYBACK) - regmap_update_bits(sunxi_daudio->regmap, - SUNXI_DAUDIO_FIFOCTL, - (SUNXI_DAUDIO_TXIM_MASK<regmap, - SUNXI_DAUDIO_FIFOCTL, - (SUNXI_DAUDIO_RXOM_MASK<dev, "unrecognized format\n"); - return -EINVAL; - } + printk("wzj:set hw params:%d\n", params_format(params)); + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + /* + * Special procesing for hdmi, HDMI card name is + * "sndhdmi" or sndhdmiraw. if card not HDMI, + * strstr func just return NULL, jump to right section. + * Not HDMI card, sunxi_hdmi maybe a NULL pointer. + */ + if (sunxi_daudio->pdata->daudio_type == SUNXI_DAUDIO_TDMHDMI_TYPE && + (sunxi_hdmi->hdmi_format > 1)) { + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FMT0, + (SUNXI_DAUDIO_SR_MASK << SAMPLE_RESOLUTION), + (SUNXI_DAUDIO_SR_24BIT << SAMPLE_RESOLUTION)); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FIFOCTL, + (SUNXI_DAUDIO_TXIM_MASK << TXIM), + (SUNXI_DAUDIO_TXIM_VALID_MSB << TXIM)); + } else { + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FMT0, + (SUNXI_DAUDIO_SR_MASK << SAMPLE_RESOLUTION), + (SUNXI_DAUDIO_SR_16BIT << SAMPLE_RESOLUTION)); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FIFOCTL, + (SUNXI_DAUDIO_TXIM_MASK << TXIM), + (SUNXI_DAUDIO_TXIM_VALID_LSB << TXIM)); + else + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FIFOCTL, + (SUNXI_DAUDIO_RXOM_MASK << RXOM), + (SUNXI_DAUDIO_RXOM_EXPH << RXOM)); + } + break; + case SNDRV_PCM_FORMAT_S20_3LE: + case SNDRV_PCM_FORMAT_S24_LE: + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FMT0, + (SUNXI_DAUDIO_SR_MASK << SAMPLE_RESOLUTION), + (SUNXI_DAUDIO_SR_24BIT << SAMPLE_RESOLUTION)); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FIFOCTL, + (SUNXI_DAUDIO_TXIM_MASK << TXIM), + (SUNXI_DAUDIO_TXIM_VALID_LSB << TXIM)); + else + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FIFOCTL, + (SUNXI_DAUDIO_RXOM_MASK << RXOM), + (SUNXI_DAUDIO_RXOM_EXPH << RXOM)); + break; + case SNDRV_PCM_FORMAT_S32_LE: + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FMT0, + (SUNXI_DAUDIO_SR_MASK << SAMPLE_RESOLUTION), + (SUNXI_DAUDIO_SR_32BIT << SAMPLE_RESOLUTION)); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FIFOCTL, + (SUNXI_DAUDIO_TXIM_MASK << TXIM), + (SUNXI_DAUDIO_TXIM_VALID_LSB << TXIM)); + else + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FIFOCTL, + (SUNXI_DAUDIO_RXOM_MASK << RXOM), + (SUNXI_DAUDIO_RXOM_EXPH << RXOM)); + break; + default: + dev_err(sunxi_daudio->dev, "unrecognized format\n"); + return -EINVAL; + } - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CHCFG, - (SUNXI_DAUDIO_TX_SLOT_MASK<hdmi_en == 0) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CHCFG, + (SUNXI_DAUDIO_TX_SLOT_MASK << TX_SLOT_NUM), + ((params_channels(params) - 1) << TX_SLOT_NUM)); + if (sunxi_daudio->hdmi_en == 0) { #ifdef SUNXI_DAUDIO_MODE_B - regmap_write(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX0CHMAP0, SUNXI_DEFAULT_CHMAP0); - regmap_write(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX0CHMAP1, SUNXI_DEFAULT_CHMAP1); + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_TX0CHMAP0, + SUNXI_DEFAULT_CHMAP0); + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_TX0CHMAP1, + SUNXI_DEFAULT_CHMAP1); #else - regmap_write(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX0CHMAP0, SUNXI_DEFAULT_CHMAP); + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_TX0CHMAP0, + SUNXI_DEFAULT_CHMAP); #endif - regmap_update_bits(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX0CHSEL, - (SUNXI_DAUDIO_TX_CHSEL_MASK<regmap, - SUNXI_DAUDIO_TX0CHSEL, - (SUNXI_DAUDIO_TX_CHEN_MASK<regmap, SUNXI_DAUDIO_TX0CHSEL, + (SUNXI_DAUDIO_TX_CHSEL_MASK << TX_CHSEL), + ((params_channels(params) - 1) << TX_CHSEL)); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_TX0CHSEL, + (SUNXI_DAUDIO_TX_CHEN_MASK << TX_CHEN), + ((1 << params_channels(params)) - 1) << TX_CHEN); + } else { + /* HDMI multi-channel processing */ #ifdef SUNXI_HDMI_AUDIO_ENABLE #ifdef SUNXI_DAUDIO_MODE_B - regmap_write(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX0CHMAP1, 0x10); - if (sunxi_hdmi->hdmi_format > 1) { - regmap_write(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX1CHMAP1, 0x32); - regmap_write(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX2CHMAP1, 0x54); - regmap_write(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX3CHMAP1, 0x76); - } else { - if (params_channels(params) > 2) - regmap_write(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX1CHMAP1, 0x23); - if (params_channels(params) > 4) { - if (params_channels(params) == 6) - regmap_write( - sunxi_daudio->regmap, - SUNXI_DAUDIO_TX2CHMAP1, - 0x54); - else - regmap_write( - sunxi_daudio->regmap, - SUNXI_DAUDIO_TX2CHMAP1, - 0x76); - } - if (params_channels(params) > 6) - regmap_write(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX3CHMAP1, - 0x54); - } + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_TX0CHMAP1, 0x10); + if (sunxi_hdmi->hdmi_format > 1) { + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_TX1CHMAP1, + 0x32); + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_TX2CHMAP1, + 0x54); + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_TX3CHMAP1, + 0x76); + } else { + if (params_channels(params) > 2) + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_TX1CHMAP1, + 0x23); + if (params_channels(params) > 4) { + if (params_channels(params) == 6) + regmap_write(sunxi_daudio->regmap, + SUNXI_DAUDIO_TX2CHMAP1, 0x54); + else + regmap_write(sunxi_daudio->regmap, + SUNXI_DAUDIO_TX2CHMAP1, 0x76); + } + if (params_channels(params) > 6) + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_TX3CHMAP1, + 0x54); + } #else - regmap_write(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX0CHMAP0, 0x10); - if (sunxi_hdmi->hdmi_format > 1) { - /* support for HBR */ - regmap_write(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX1CHMAP0, 0x32); - regmap_write(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX2CHMAP0, 0x54); - regmap_write(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX3CHMAP0, 0x76); - } else { - /* LPCM 5.1 & 7.1 support */ - if (params_channels(params) > 2) - regmap_write(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX1CHMAP0, 0x23); - if (params_channels(params) > 4) { - if (params_channels(params) == 6) - regmap_write( - sunxi_daudio->regmap, - SUNXI_DAUDIO_TX2CHMAP0, - 0x54); - else - regmap_write( - sunxi_daudio->regmap, - SUNXI_DAUDIO_TX2CHMAP0, - 0x76); - } - if (params_channels(params) > 6) - regmap_write(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX3CHMAP0, - 0x54); - } + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_TX0CHMAP0, 0x10); + if (sunxi_hdmi->hdmi_format > 1) { + /* support for HBR */ + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_TX1CHMAP0, + 0x32); + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_TX2CHMAP0, + 0x54); + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_TX3CHMAP0, + 0x76); + } else { + /* LPCM 5.1 & 7.1 support */ + if (params_channels(params) > 2) + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_TX1CHMAP0, + 0x23); + if (params_channels(params) > 4) { + if (params_channels(params) == 6) + regmap_write(sunxi_daudio->regmap, + SUNXI_DAUDIO_TX2CHMAP0, 0x54); + else + regmap_write(sunxi_daudio->regmap, + SUNXI_DAUDIO_TX2CHMAP0, 0x76); + } + if (params_channels(params) > 6) + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_TX3CHMAP0, + 0x54); + } #endif - regmap_update_bits(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX0CHSEL, - 0x01 << TX_CHSEL, 0x01 << TX_CHSEL); - regmap_update_bits(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX0CHSEL, - 0x03 << TX_CHEN, 0x03 << TX_CHEN); - regmap_update_bits(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX1CHSEL, - 0x01 << TX_CHSEL, 0x01 << TX_CHSEL); - regmap_update_bits(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX1CHSEL, - (0x03)<regmap, - SUNXI_DAUDIO_TX2CHSEL, - 0x01 << TX_CHSEL, 0x01 << TX_CHSEL); - regmap_update_bits(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX2CHSEL, - (0x03)<regmap, - SUNXI_DAUDIO_TX3CHSEL, - 0x01 << TX_CHSEL, 0x01 << TX_CHSEL); - regmap_update_bits(sunxi_daudio->regmap, - SUNXI_DAUDIO_TX3CHSEL, - (0x03)<regmap, SUNXI_DAUDIO_TX0CHSEL, + 0x01 << TX_CHSEL, 0x01 << TX_CHSEL); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_TX0CHSEL, + 0x03 << TX_CHEN, 0x03 << TX_CHEN); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_TX1CHSEL, + 0x01 << TX_CHSEL, 0x01 << TX_CHSEL); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_TX1CHSEL, + (0x03) << TX_CHEN, 0x03 << TX_CHEN); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_TX2CHSEL, + 0x01 << TX_CHSEL, 0x01 << TX_CHSEL); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_TX2CHSEL, + (0x03) << TX_CHEN, 0x03 << TX_CHEN); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_TX3CHSEL, + 0x01 << TX_CHSEL, 0x01 << TX_CHSEL); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_TX3CHSEL, + (0x03) << TX_CHEN, 0x03 << TX_CHEN); +#endif /* HDMI */ + } + } else { #ifdef SUNXI_DAUDIO_MODE_B - regmap_write(sunxi_daudio->regmap, - SUNXI_DAUDIO_RXCHMAP0, SUNXI_DEFAULT_CHMAP0); - regmap_write(sunxi_daudio->regmap, - SUNXI_DAUDIO_RXCHMAP1, SUNXI_DEFAULT_CHMAP1); + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_RXCHMAP0, + SUNXI_DEFAULT_CHMAP0); + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_RXCHMAP1, + SUNXI_DEFAULT_CHMAP1); #else - regmap_write(sunxi_daudio->regmap, - SUNXI_DAUDIO_RXCHMAP, SUNXI_DEFAULT_CHMAP); + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_RXCHMAP, + SUNXI_DEFAULT_CHMAP); #endif - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CHCFG, - (SUNXI_DAUDIO_RX_SLOT_MASK<regmap, SUNXI_DAUDIO_RXCHSEL, - (SUNXI_DAUDIO_RX_CHSEL_MASK<regmap, SUNXI_DAUDIO_CHCFG, + (SUNXI_DAUDIO_RX_SLOT_MASK << RX_SLOT_NUM), + ((params_channels(params) - 1) << RX_SLOT_NUM)); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_RXCHSEL, + (SUNXI_DAUDIO_RX_CHSEL_MASK << RX_CHSEL), + ((params_channels(params) - 1) << RX_CHSEL)); + } #ifdef SUNXI_HDMI_AUDIO_ENABLE - /* Special processing for HDMI hub playback to enable hdmi module */ - if (sunxi_daudio->pdata->daudio_type == SUNXI_DAUDIO_TDMHDMI_TYPE) { - mutex_lock(&sunxi_daudio->mutex); - regmap_read(sunxi_daudio->regmap, - SUNXI_DAUDIO_FIFOCTL, ®_val); - sunxi_daudio->hub_mode = (reg_val & (1<hub_mode) { - sunxi_hdmi_codec_hw_params(substream, params, NULL); - sunxi_hdmi_codec_prepare(substream, NULL); - } - mutex_unlock(&sunxi_daudio->mutex); - } + /* Special processing for HDMI hub playback to enable hdmi module */ + if (sunxi_daudio->pdata->daudio_type == SUNXI_DAUDIO_TDMHDMI_TYPE) { + mutex_lock(&sunxi_daudio->mutex); + regmap_read(sunxi_daudio->regmap, SUNXI_DAUDIO_FIFOCTL, ®_val); + sunxi_daudio->hub_mode = (reg_val & (1 << HUB_EN)); + if (sunxi_daudio->hub_mode) { + sunxi_hdmi_codec_hw_params(substream, params, NULL); + sunxi_hdmi_codec_prepare(substream, NULL); + } + mutex_unlock(&sunxi_daudio->mutex); + } #endif #ifdef CONFIG_SND_SUNXI_MAD - /*mad only supported 16k/48KHz samplerate when capturing*/ - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - if (sunxi_daudio->mad_bind == 1) { - if (params_format(params) != SNDRV_PCM_FORMAT_S16_LE) { - dev_err(sunxi_daudio->dev, "unsupported mad sample bits\n"); - return -EINVAL; - } - if ((params_rate(params) == 16000) || (params_rate(params) == 48000)) { - sunxi_mad_hw_params(params_channels(params), params_rate(params)); - sunxi_daudio->audio_src_chan_num = params_channels(params); - } else { - dev_err(sunxi_daudio->dev, "unsupported mad rate\n"); - return -EINVAL; - } - } - } + /*mad only supported 16k/48KHz samplerate when capturing*/ + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + if (sunxi_daudio->mad_bind == 1) { + if (params_format(params) != SNDRV_PCM_FORMAT_S16_LE) { + dev_err(sunxi_daudio->dev, "unsupported mad sample bits\n"); + return -EINVAL; + } + if ((params_rate(params) == 16000) || + (params_rate(params) == 48000)) { + sunxi_mad_hw_params(params_channels(params), + params_rate(params)); + sunxi_daudio->audio_src_chan_num = params_channels(params); + } else { + dev_err(sunxi_daudio->dev, "unsupported mad rate\n"); + return -EINVAL; + } + } + } #endif - return 0; + return 0; } -static int sunxi_daudio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); +static int sunxi_daudio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { + struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); - sunxi_daudio_init_fmt(sunxi_daudio, fmt); - return 0; + sunxi_daudio_init_fmt(sunxi_daudio, fmt); + return 0; } -static int sunxi_daudio_set_sysclk(struct snd_soc_dai *dai, - int clk_id, unsigned int freq, int dir) -{ - struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); +static int sunxi_daudio_set_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) { + struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); - if (clk_set_rate(sunxi_daudio->pllclk, freq)) { - dev_err(sunxi_daudio->dev, "set pllclk rate failed\n"); - pr_err("set sysclk error"); - return -EBUSY; - } - return 0; + printk("wzj:set sysclk:%d, id:%d, name:%s\n", freq, dai->id, dai->name); + if (clk_set_rate(sunxi_daudio->pllclk, freq)) { + dev_err(sunxi_daudio->dev, "set pllclk rate failed\n"); + pr_err("set sysclk error"); + return -EBUSY; + } + return 0; } -static int sunxi_daudio_set_clkdiv(struct snd_soc_dai *dai, - int clk_id, int clk_div) -{ - struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); - unsigned int bclk_div, div_ratio; +static int sunxi_daudio_set_clkdiv(struct snd_soc_dai *dai, int clk_id, + int clk_div) { + struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); + unsigned int bclk_div, div_ratio; - if (sunxi_daudio->pdata->tdm_config) - /* I2S/TDM two channel mode */ - div_ratio = clk_div/(2 * sunxi_daudio->pdata->pcm_lrck_period); - else - /* PCM mode */ - div_ratio = clk_div / sunxi_daudio->pdata->pcm_lrck_period; + if (sunxi_daudio->pdata->tdm_config) + /* I2S/TDM two channel mode */ + div_ratio = clk_div / (2 * sunxi_daudio->pdata->pcm_lrck_period); + else + /* PCM mode */ + div_ratio = clk_div / sunxi_daudio->pdata->pcm_lrck_period; - switch (div_ratio) { - case 1: - bclk_div = SUNXI_DAUDIO_BCLK_DIV_1; - break; - case 2: - bclk_div = SUNXI_DAUDIO_BCLK_DIV_2; - break; - case 4: - bclk_div = SUNXI_DAUDIO_BCLK_DIV_3; - break; - case 6: - bclk_div = SUNXI_DAUDIO_BCLK_DIV_4; - break; - case 8: - bclk_div = SUNXI_DAUDIO_BCLK_DIV_5; - break; - case 12: - bclk_div = SUNXI_DAUDIO_BCLK_DIV_6; - break; - case 16: - bclk_div = SUNXI_DAUDIO_BCLK_DIV_7; - break; - case 24: - bclk_div = SUNXI_DAUDIO_BCLK_DIV_8; - break; - case 32: - bclk_div = SUNXI_DAUDIO_BCLK_DIV_9; - break; - case 48: - bclk_div = SUNXI_DAUDIO_BCLK_DIV_10; - break; - case 64: - bclk_div = SUNXI_DAUDIO_BCLK_DIV_11; - break; - case 96: - bclk_div = SUNXI_DAUDIO_BCLK_DIV_12; - break; - case 128: - bclk_div = SUNXI_DAUDIO_BCLK_DIV_13; - break; - case 176: - bclk_div = SUNXI_DAUDIO_BCLK_DIV_14; - break; - case 192: - bclk_div = SUNXI_DAUDIO_BCLK_DIV_15; - break; - default: - dev_err(sunxi_daudio->dev, "unsupport clk_div\n"); - return -EINVAL; - } + switch (div_ratio) { + case 1: + bclk_div = SUNXI_DAUDIO_BCLK_DIV_1; + break; + case 2: + bclk_div = SUNXI_DAUDIO_BCLK_DIV_2; + break; + case 4: + bclk_div = SUNXI_DAUDIO_BCLK_DIV_3; + break; + case 6: + bclk_div = SUNXI_DAUDIO_BCLK_DIV_4; + break; + case 8: + bclk_div = SUNXI_DAUDIO_BCLK_DIV_5; + break; + case 12: + bclk_div = SUNXI_DAUDIO_BCLK_DIV_6; + break; + case 16: + bclk_div = SUNXI_DAUDIO_BCLK_DIV_7; + break; + case 24: + bclk_div = SUNXI_DAUDIO_BCLK_DIV_8; + break; + case 32: + bclk_div = SUNXI_DAUDIO_BCLK_DIV_9; + break; + case 48: + bclk_div = SUNXI_DAUDIO_BCLK_DIV_10; + break; + case 64: + bclk_div = SUNXI_DAUDIO_BCLK_DIV_11; + break; + case 96: + bclk_div = SUNXI_DAUDIO_BCLK_DIV_12; + break; + case 128: + bclk_div = SUNXI_DAUDIO_BCLK_DIV_13; + break; + case 176: + bclk_div = SUNXI_DAUDIO_BCLK_DIV_14; + break; + case 192: + bclk_div = SUNXI_DAUDIO_BCLK_DIV_15; + break; + default: + dev_err(sunxi_daudio->dev, "unsupport clk_div\n"); + return -EINVAL; + } - /* setting bclk to driver external codec bit clk */ - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CLKDIV, - (SUNXI_DAUDIO_BCLK_DIV_MASK<regmap, SUNXI_DAUDIO_CLKDIV, + (SUNXI_DAUDIO_BCLK_DIV_MASK << BCLK_DIV), + (bclk_div << BCLK_DIV)); + printk("wzj:set bclk:%d, inputdiv:%d, period:%d, clkid:%d\n", bclk_div, clk_div, sunxi_daudio->pdata->pcm_lrck_period, clk_id); + return 0; } static int sunxi_daudio_dai_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); + struct snd_soc_dai *dai) { + struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); + printk("Wzj:sunxi_daudio_dai_startup\n"); #ifdef CONFIG_SND_SUNXI_MAD - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_card *card = rtd->card; - struct sunxi_mad_priv *sunxi_daudio_priv = snd_soc_card_get_drvdata(card); - unsigned int path_sel; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct sunxi_mad_priv *sunxi_daudio_priv = snd_soc_card_get_drvdata(card); + unsigned int path_sel; #endif - /* FIXME: As HDMI module to play audio, it need at least 1100ms to sync. - * if we not wait we lost audio data to playback, or we wait for 1100ms - * to playback, user experience worst than you can imagine. So we need - * to cutdown that sync time by keeping clock signal on. we just enable - * it at startup and resume, cutdown it at remove and suspend time. - */ - if (sunxi_daudio->pdata->daudio_type == SUNXI_DAUDIO_TDMHDMI_TYPE) - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, - (1<pdata->daudio_type == SUNXI_DAUDIO_TDMHDMI_TYPE) + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << CTL_TXEN), (1 << CTL_TXEN)); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - snd_soc_dai_set_dma_data(dai, substream, - &sunxi_daudio->playback_dma_param); - } else { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + snd_soc_dai_set_dma_data(dai, substream, + &sunxi_daudio->playback_dma_param); + } else { #ifdef CONFIG_SND_SUNXI_MAD - sunxi_daudio->mad_bind = sunxi_daudio_priv->mad_bind; - sunxi_daudio->capture_en = 1; + sunxi_daudio->mad_bind = sunxi_daudio_priv->mad_bind; + sunxi_daudio->capture_en = 1; - if (sunxi_daudio->mad_bind == 1) { - sunxi_mad_init(); - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, - (1<capture_dma_param); + if (sunxi_daudio->mad_bind == 1) { + sunxi_mad_init(); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << MAD_DATA_EN), (1 << MAD_DATA_EN)); + sunxi_sram_dma_config(&sunxi_daudio->capture_dma_param); - switch (sunxi_daudio->pdata->tdm_num) { - case 0: - path_sel = 1; /*I2S0*/ - break; - case 1: - path_sel = 4; /*i2s1*/ - break; - case 2: - path_sel = 5; /*I2S2*/ - break; - default: - dev_err(sunxi_daudio->dev, "unsupported I2S number!\n"); - return -EINVAL; - } - /*open daudio src*/ - sunxi_mad_audio_source_sel(path_sel, 1); - } + switch (sunxi_daudio->pdata->tdm_num) { + case 0: + path_sel = 1; /*I2S0*/ + break; + case 1: + path_sel = 4; /*i2s1*/ + break; + case 2: + path_sel = 5; /*I2S2*/ + break; + default: + dev_err(sunxi_daudio->dev, "unsupported I2S number!\n"); + return -EINVAL; + } + /*open daudio src*/ + sunxi_mad_audio_source_sel(path_sel, 1); + } #endif - snd_soc_dai_set_dma_data(dai, substream, - &sunxi_daudio->capture_dma_param); - } + snd_soc_dai_set_dma_data(dai, substream, + &sunxi_daudio->capture_dma_param); + } - return 0; + return 0; } -static int sunxi_daudio_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - sunxi_daudio_txctrl_enable(sunxi_daudio, 1); - } else { - #if 0 +static int sunxi_daudio_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) { + struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); + printk("wzj:sunxi_daudio_trigger,cmd:%d\n", cmd); + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + sunxi_daudio_txctrl_enable(sunxi_daudio, 1); + } else { +#if 0 if (daudio_loop_en) regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, @@ -1033,109 +974,128 @@ static int sunxi_daudio_trigger(struct snd_pcm_substream *substream, regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, (1<stream == SNDRV_PCM_STREAM_PLAYBACK) - sunxi_daudio_txctrl_enable(sunxi_daudio, 0); - else - sunxi_daudio_rxctrl_enable(sunxi_daudio, 0); - break; - default: - return -EINVAL; - } - return 0; +#endif + sunxi_daudio_rxctrl_enable(sunxi_daudio, 1); + } + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + sunxi_daudio_txctrl_enable(sunxi_daudio, 0); + else + sunxi_daudio_rxctrl_enable(sunxi_daudio, 0); + break; + default: + return -EINVAL; + } + return 0; } static int sunxi_daudio_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - unsigned int i; - struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - for (i = 0 ; i < SUNXI_DAUDIO_FTX_TIMES ; i++) { - regmap_update_bits(sunxi_daudio->regmap, - SUNXI_DAUDIO_FIFOCTL, - (1<regmap, SUNXI_DAUDIO_TXCNT, 0); - } else { - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FIFOCTL, - (1<regmap, SUNXI_DAUDIO_RXCNT, 0); - } - return 0; + struct snd_soc_dai *dai) { + unsigned int i; + struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); + printk("wzj:sunxi_daudio_prepare\n"); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + for (i = 0; i < SUNXI_DAUDIO_FTX_TIMES; i++) { + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FIFOCTL, + (1 << FIFO_CTL_FTX), (1 << FIFO_CTL_FTX)); + mdelay(1); + } + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_TXCNT, 0); + } else { + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_FIFOCTL, + (1 << FIFO_CTL_FRX), (1 << FIFO_CTL_FRX)); + regmap_write(sunxi_daudio->regmap, SUNXI_DAUDIO_RXCNT, 0); + } + return 0; } -static int sunxi_daudio_probe(struct snd_soc_dai *dai) -{ - struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); +static struct snd_soc_dai *mic_i2s_dai = NULL; - mutex_init(&sunxi_daudio->mutex); +void netease_enable_clk(void) { + struct snd_soc_dai *dai = mic_i2s_dai; + if (dai != NULL && dai->id == 0) { + printk("Wzj:Begin to init i2s0 clk! dainame:%s\n", dai->name); + sunxi_daudio_set_sysclk(dai, 0, 24576000, 0); + sunxi_daudio_set_clkdiv(dai, 0, 256); + //sunxi_daudio_rxctrl_enable(sunxi_daudio, 1); + printk("end!\n"); + } +} +EXPORT_SYMBOL(netease_enable_clk); - sunxi_daudio_init(sunxi_daudio); - return 0; +static int sunxi_daudio_probe(struct snd_soc_dai *dai) { + printk("wzj:sunxi_daudio_probe\n"); + struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); + + mutex_init(&sunxi_daudio->mutex); + + sunxi_daudio_init(sunxi_daudio); + + if (dai != NULL && dai->id == 0) { + mic_i2s_dai = dai; + } + return 0; } static void sunxi_daudio_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); + struct snd_soc_dai *dai) { + printk("wzj:sunxi_daudio_shutdown\n"); + struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); #ifdef CONFIG_SND_SUNXI_MAD - unsigned int path_sel; + unsigned int path_sel; #endif - /* Special processing for HDMI hub playback to shutdown hdmi module */ - if (sunxi_daudio->pdata->daudio_type == SUNXI_DAUDIO_TDMHDMI_TYPE) { - mutex_lock(&sunxi_daudio->mutex); - if (sunxi_daudio->hub_mode) - sunxi_hdmi_codec_shutdown(substream, NULL); - mutex_unlock(&sunxi_daudio->mutex); - } + /* Special processing for HDMI hub playback to shutdown hdmi module */ + if (sunxi_daudio->pdata->daudio_type == SUNXI_DAUDIO_TDMHDMI_TYPE) { + mutex_lock(&sunxi_daudio->mutex); + if (sunxi_daudio->hub_mode) + sunxi_hdmi_codec_shutdown(substream, NULL); + mutex_unlock(&sunxi_daudio->mutex); + } #ifdef CONFIG_SND_SUNXI_MAD - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - if (sunxi_daudio->mad_bind == 1) { - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, - (1<pdata->tdm_num) { - case 0: - SUNXI_DAUDIO_DRQSRC(sunxi_daudio, 0); - path_sel = 1; /*I2S0*/ - break; - case 1: - SUNXI_DAUDIO_DRQSRC(sunxi_daudio, 1); - path_sel = 4; /*i2s1*/ - break; - case 2: - SUNXI_DAUDIO_DRQSRC(sunxi_daudio, 2); - path_sel = 5; /*I2S2*/ - break; - } - sunxi_mad_audio_source_sel(path_sel, 0); /*diable daudio src*/ - /*if not use mad again*/ - sunxi_daudio->capture_dma_param.dma_addr = - sunxi_daudio->res.start + SUNXI_DAUDIO_RXFIFO; - sunxi_daudio->capture_en = 0; - } - } + printk("wzj:sunxi_daudio_shutdown0\n"); + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + printk("wzj:sunxi_daudio_shutdown1\n"); + if (sunxi_daudio->mad_bind == 1) { + printk("wzj:sunxi_daudio_shutdown2\n"); + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << MAD_DATA_EN), (0 << MAD_DATA_EN)); + printk("wzj:sunxi_daudio_shutdown3, tdm:%d\n", + sunxi_daudio->pdata->tdm_num); + switch (sunxi_daudio->pdata->tdm_num) { + case 0: + SUNXI_DAUDIO_DRQSRC(sunxi_daudio, 0); + path_sel = 1; /*I2S0*/ + break; + case 1: + SUNXI_DAUDIO_DRQSRC(sunxi_daudio, 1); + path_sel = 4; /*i2s1*/ + break; + case 2: + SUNXI_DAUDIO_DRQSRC(sunxi_daudio, 2); + path_sel = 5; /*I2S2*/ + break; + } + sunxi_mad_audio_source_sel(path_sel, 0); /*diable daudio src*/ + /*if not use mad again*/ + sunxi_daudio->capture_dma_param.dma_addr = + sunxi_daudio->res.start + SUNXI_DAUDIO_RXFIFO; + sunxi_daudio->capture_en = 0; + } + } #endif } -static int sunxi_daudio_remove(struct snd_soc_dai *dai) -{ - struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); +static int sunxi_daudio_remove(struct snd_soc_dai *dai) { + struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); - if (sunxi_daudio->pdata->daudio_type == SUNXI_DAUDIO_TDMHDMI_TYPE) - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, - (1<pdata->daudio_type == SUNXI_DAUDIO_TDMHDMI_TYPE) + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << CTL_TXEN), (0 << CTL_TXEN)); + return 0; } #define DAUDIO_STANDBY_DEBUG 0 @@ -1143,270 +1103,257 @@ static int sunxi_daudio_remove(struct snd_soc_dai *dai) #if DAUDIO_STANDBY_DEBUG static int daudio_standby_debug; -static int sunxi_daudio_debug_suspend(struct sunxi_daudio_info *sunxi_daudio) -{ - int ret = 0; +static int sunxi_daudio_debug_suspend(struct sunxi_daudio_info *sunxi_daudio) { + int ret = 0; - pr_debug("[daudio] suspend .%s start\n", dev_name(sunxi_daudio->dev)); - /* Global disable I2S/TDM module */ - sunxi_daudio_global_enable(sunxi_daudio, 0); + pr_debug("[daudio] suspend .%s start\n", dev_name(sunxi_daudio->dev)); + /* Global disable I2S/TDM module */ + sunxi_daudio_global_enable(sunxi_daudio, 0); - if (sunxi_daudio->pdata->daudio_type == SUNXI_DAUDIO_TDMHDMI_TYPE) - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, - (1<pdata->daudio_type == SUNXI_DAUDIO_TDMHDMI_TYPE) + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << CTL_TXEN), (0 << CTL_TXEN)); - clk_disable_unprepare(sunxi_daudio->moduleclk); - clk_disable_unprepare(sunxi_daudio->pllclk); + clk_disable_unprepare(sunxi_daudio->moduleclk); + clk_disable_unprepare(sunxi_daudio->pllclk); - if (sunxi_daudio->pdata->external_type) { - ret = pinctrl_select_state(sunxi_daudio->pinctrl, - sunxi_daudio->pinstate_sleep); - if (ret) { - pr_warn("[daudio]select pin sleep state failed\n"); - return ret; - } - devm_pinctrl_put(sunxi_daudio->pinctrl); - } + if (sunxi_daudio->pdata->external_type) { + ret = pinctrl_select_state(sunxi_daudio->pinctrl, + sunxi_daudio->pinstate_sleep); + if (ret) { + pr_warn("[daudio]select pin sleep state failed\n"); + return ret; + } + devm_pinctrl_put(sunxi_daudio->pinctrl); + } - pr_debug("[daudio] suspend-->line%d\n", __LINE__); - if (sunxi_daudio->vol_supply.daudio_regulator) { - pr_debug("[daudio] suspend-->line%d\n", __LINE__); - regulator_disable(sunxi_daudio->vol_supply.daudio_regulator); - pr_debug("[daudio] suspend-->line%d\n", __LINE__); - } + pr_debug("[daudio] suspend-->line%d\n", __LINE__); + if (sunxi_daudio->vol_supply.daudio_regulator) { + pr_debug("[daudio] suspend-->line%d\n", __LINE__); + regulator_disable(sunxi_daudio->vol_supply.daudio_regulator); + pr_debug("[daudio] suspend-->line%d\n", __LINE__); + } - pr_debug("[daudio] suspend .%s end\n", dev_name(sunxi_daudio->dev)); + pr_debug("[daudio] suspend .%s end\n", dev_name(sunxi_daudio->dev)); - return 0; + return 0; } -static int sunxi_daudio_debug_resume(struct sunxi_daudio_info *sunxi_daudio) -{ - int ret = 0; +static int sunxi_daudio_debug_resume(struct sunxi_daudio_info *sunxi_daudio) { + int ret = 0; - pr_debug("[%s] resume .%s start\n", __func__, - dev_name(sunxi_daudio->dev)); + pr_debug("[%s] resume .%s start\n", __func__, dev_name(sunxi_daudio->dev)); - if (sunxi_daudio->vol_supply.daudio_regulator) { - ret = regulator_enable(sunxi_daudio->vol_supply.daudio_regulator); - if (ret) { - dev_err(sunxi_daudio->dev, - "resume enable duaido[%d] vcc-pin failed\n", - sunxi_daudio->pdata->tdm_num); - goto err_resume_out; - } - } + if (sunxi_daudio->vol_supply.daudio_regulator) { + ret = regulator_enable(sunxi_daudio->vol_supply.daudio_regulator); + if (ret) { + dev_err(sunxi_daudio->dev, + "resume enable duaido[%d] vcc-pin failed\n", + sunxi_daudio->pdata->tdm_num); + goto err_resume_out; + } + } - if (clk_prepare_enable(sunxi_daudio->pllclk)) { - dev_err(sunxi_daudio->dev, "pllclk resume failed\n"); - ret = -EBUSY; - goto err_resume_out; - } + if (clk_prepare_enable(sunxi_daudio->pllclk)) { + dev_err(sunxi_daudio->dev, "pllclk resume failed\n"); + ret = -EBUSY; + goto err_resume_out; + } - if (clk_prepare_enable(sunxi_daudio->moduleclk)) { - dev_err(sunxi_daudio->dev, "moduleclk resume failed\n"); - ret = -EBUSY; - goto err_pllclk_disable; - } + if (clk_prepare_enable(sunxi_daudio->moduleclk)) { + dev_err(sunxi_daudio->dev, "moduleclk resume failed\n"); + ret = -EBUSY; + goto err_pllclk_disable; + } - if (sunxi_daudio->pdata->external_type) { - sunxi_daudio->pinctrl = devm_pinctrl_get(sunxi_daudio->dev); - if (IS_ERR_OR_NULL(sunxi_daudio)) { - dev_err(sunxi_daudio->dev, "pinctrl resume get fail\n"); - ret = -ENOMEM; - goto err_moduleclk_disable; - } + if (sunxi_daudio->pdata->external_type) { + sunxi_daudio->pinctrl = devm_pinctrl_get(sunxi_daudio->dev); + if (IS_ERR_OR_NULL(sunxi_daudio)) { + dev_err(sunxi_daudio->dev, "pinctrl resume get fail\n"); + ret = -ENOMEM; + goto err_moduleclk_disable; + } - sunxi_daudio->pinstate = pinctrl_lookup_state( - sunxi_daudio->pinctrl, PINCTRL_STATE_DEFAULT); - if (IS_ERR_OR_NULL(sunxi_daudio->pinstate)) { - dev_err(sunxi_daudio->dev, - "pinctrl default state get failed\n"); - ret = -EINVAL; - goto err_pinctrl_put; - } + sunxi_daudio->pinstate = + pinctrl_lookup_state(sunxi_daudio->pinctrl, PINCTRL_STATE_DEFAULT); + if (IS_ERR_OR_NULL(sunxi_daudio->pinstate)) { + dev_err(sunxi_daudio->dev, "pinctrl default state get failed\n"); + ret = -EINVAL; + goto err_pinctrl_put; + } - sunxi_daudio->pinstate_sleep = pinctrl_lookup_state( - sunxi_daudio->pinctrl, PINCTRL_STATE_SLEEP); - if (IS_ERR_OR_NULL(sunxi_daudio->pinstate_sleep)) { - dev_err(sunxi_daudio->dev, - "pinctrl sleep state get failed\n"); - ret = -EINVAL; - goto err_pinctrl_put; - } + sunxi_daudio->pinstate_sleep = + pinctrl_lookup_state(sunxi_daudio->pinctrl, PINCTRL_STATE_SLEEP); + if (IS_ERR_OR_NULL(sunxi_daudio->pinstate_sleep)) { + dev_err(sunxi_daudio->dev, "pinctrl sleep state get failed\n"); + ret = -EINVAL; + goto err_pinctrl_put; + } - ret = pinctrl_select_state(sunxi_daudio->pinctrl, - sunxi_daudio->pinstate); - if (ret) - dev_warn(sunxi_daudio->dev, - "daudio set pinctrl default state fail\n"); - } + ret = + pinctrl_select_state(sunxi_daudio->pinctrl, sunxi_daudio->pinstate); + if (ret) + dev_warn(sunxi_daudio->dev, + "daudio set pinctrl default state fail\n"); + } - sunxi_daudio_init(sunxi_daudio); + sunxi_daudio_init(sunxi_daudio); - /* Global enable I2S/TDM module */ - sunxi_daudio_global_enable(sunxi_daudio, 1); + /* Global enable I2S/TDM module */ + sunxi_daudio_global_enable(sunxi_daudio, 1); - if (sunxi_daudio->pdata->daudio_type == SUNXI_DAUDIO_TDMHDMI_TYPE) - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, - (1<pdata->daudio_type == SUNXI_DAUDIO_TDMHDMI_TYPE) + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << CTL_TXEN), (1 << CTL_TXEN)); - pr_debug("[%s] resume .%s end\n", __func__, - dev_name(sunxi_daudio->dev)); + pr_debug("[%s] resume .%s end\n", __func__, dev_name(sunxi_daudio->dev)); - return 0; + return 0; err_pinctrl_put: - devm_pinctrl_put(sunxi_daudio->pinctrl); + devm_pinctrl_put(sunxi_daudio->pinctrl); err_moduleclk_disable: - clk_disable_unprepare(sunxi_daudio->moduleclk); + clk_disable_unprepare(sunxi_daudio->moduleclk); err_pllclk_disable: - clk_disable_unprepare(sunxi_daudio->pllclk); + clk_disable_unprepare(sunxi_daudio->pllclk); err_resume_out: - return ret; + return ret; } #endif -static int sunxi_daudio_suspend(struct snd_soc_dai *dai) -{ - struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); - int ret = 0; +static int sunxi_daudio_suspend(struct snd_soc_dai *dai) { + struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); + int ret = 0; - pr_debug("[daudio] suspend .%s start\n", dev_name(sunxi_daudio->dev)); + printk("[daudio] suspend .%s start\n", dev_name(sunxi_daudio->dev)); #ifdef CONFIG_SND_SUNXI_MAD - if ((sunxi_daudio->mad_bind == 1) && (sunxi_daudio->capture_en == 1)) { - sunxi_mad_suspend_external(sunxi_daudio->lpsd_chan_sel, - sunxi_daudio->mad_standby_chan_sel); - pr_debug("mad suspend succeed %s\n", __func__); - return 0; - } + if ((sunxi_daudio->mad_bind == 1) && (sunxi_daudio->capture_en == 1)) { + sunxi_mad_suspend_external(sunxi_daudio->lpsd_chan_sel, + sunxi_daudio->mad_standby_chan_sel); + pr_debug("mad suspend succeed %s\n", __func__); + return 0; + } #endif - /* Global disable I2S/TDM module */ - sunxi_daudio_global_enable(sunxi_daudio, 0); + /* Global disable I2S/TDM module */ + sunxi_daudio_global_enable(sunxi_daudio, 0); - if (sunxi_daudio->pdata->daudio_type == SUNXI_DAUDIO_TDMHDMI_TYPE) - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, - (1<pdata->daudio_type == SUNXI_DAUDIO_TDMHDMI_TYPE) + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << CTL_TXEN), (0 << CTL_TXEN)); - clk_disable_unprepare(sunxi_daudio->moduleclk); - clk_disable_unprepare(sunxi_daudio->pllclk); + clk_disable_unprepare(sunxi_daudio->moduleclk); + clk_disable_unprepare(sunxi_daudio->pllclk); - if (sunxi_daudio->pdata->external_type) { - ret = pinctrl_select_state(sunxi_daudio->pinctrl, - sunxi_daudio->pinstate_sleep); - if (ret) { - pr_warn("[daudio]select pin sleep state failed\n"); - return ret; - } - devm_pinctrl_put(sunxi_daudio->pinctrl); - } + if (sunxi_daudio->pdata->external_type) { + ret = pinctrl_select_state(sunxi_daudio->pinctrl, + sunxi_daudio->pinstate_sleep); + if (ret) { + pr_warn("[daudio]select pin sleep state failed\n"); + return ret; + } + devm_pinctrl_put(sunxi_daudio->pinctrl); + } - if (sunxi_daudio->vol_supply.daudio_regulator) - regulator_disable(sunxi_daudio->vol_supply.daudio_regulator); + if (sunxi_daudio->vol_supply.daudio_regulator) + regulator_disable(sunxi_daudio->vol_supply.daudio_regulator); - pr_debug("[daudio] suspend .%s end \n", dev_name(sunxi_daudio->dev)); + pr_debug("[daudio] suspend .%s end \n", dev_name(sunxi_daudio->dev)); - return 0; + return 0; } -static int sunxi_daudio_resume(struct snd_soc_dai *dai) -{ - struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); - int ret; +static int sunxi_daudio_resume(struct snd_soc_dai *dai) { + struct sunxi_daudio_info *sunxi_daudio = snd_soc_dai_get_drvdata(dai); + int ret; - pr_debug("[%s] resume .%s start\n", __func__, - dev_name(sunxi_daudio->dev)); + printk("[%s] resume .%s start\n", __func__, dev_name(sunxi_daudio->dev)); - if (sunxi_daudio->vol_supply.daudio_regulator) { - ret = regulator_enable(sunxi_daudio->vol_supply.daudio_regulator); - if (ret) { - dev_err(sunxi_daudio->dev, - "resume enable duaido vcc-pin failed\n"); - goto err_resume_out; - } - } + if (sunxi_daudio->vol_supply.daudio_regulator) { + ret = regulator_enable(sunxi_daudio->vol_supply.daudio_regulator); + if (ret) { + dev_err(sunxi_daudio->dev, "resume enable duaido vcc-pin failed\n"); + goto err_resume_out; + } + } #ifdef CONFIG_SND_SUNXI_MAD - if ((sunxi_daudio->mad_bind == 1) && (sunxi_daudio->capture_en == 1)) { - sunxi_mad_resume_external(sunxi_daudio->mad_standby_chan_sel, - sunxi_daudio->audio_src_chan_num); - pr_debug("mad resume succeed %s\n", __func__); - return 0; - } + if ((sunxi_daudio->mad_bind == 1) && (sunxi_daudio->capture_en == 1)) { + sunxi_mad_resume_external(sunxi_daudio->mad_standby_chan_sel, + sunxi_daudio->audio_src_chan_num); + pr_debug("mad resume succeed %s\n", __func__); + return 0; + } #endif - if (clk_prepare_enable(sunxi_daudio->pllclk)) { - dev_err(sunxi_daudio->dev, "pllclk resume failed\n"); - ret = -EBUSY; - goto err_resume_out; - } + if (clk_prepare_enable(sunxi_daudio->pllclk)) { + dev_err(sunxi_daudio->dev, "pllclk resume failed\n"); + ret = -EBUSY; + goto err_resume_out; + } - if (clk_prepare_enable(sunxi_daudio->moduleclk)) { - dev_err(sunxi_daudio->dev, "moduleclk resume failed\n"); - ret = -EBUSY; - goto err_pllclk_disable; - } + if (clk_prepare_enable(sunxi_daudio->moduleclk)) { + dev_err(sunxi_daudio->dev, "moduleclk resume failed\n"); + ret = -EBUSY; + goto err_pllclk_disable; + } - if (sunxi_daudio->pdata->external_type) { - sunxi_daudio->pinctrl = devm_pinctrl_get(sunxi_daudio->dev); - if (IS_ERR_OR_NULL(sunxi_daudio)) { - dev_err(sunxi_daudio->dev, "pinctrl resume get fail\n"); - ret = -ENOMEM; - goto err_moduleclk_disable; - } + if (sunxi_daudio->pdata->external_type) { + sunxi_daudio->pinctrl = devm_pinctrl_get(sunxi_daudio->dev); + if (IS_ERR_OR_NULL(sunxi_daudio)) { + dev_err(sunxi_daudio->dev, "pinctrl resume get fail\n"); + ret = -ENOMEM; + goto err_moduleclk_disable; + } - sunxi_daudio->pinstate = pinctrl_lookup_state( - sunxi_daudio->pinctrl, PINCTRL_STATE_DEFAULT); - if (IS_ERR_OR_NULL(sunxi_daudio->pinstate)) { - dev_err(sunxi_daudio->dev, - "pinctrl default state get failed\n"); - ret = -EINVAL; - goto err_pinctrl_put; - } + sunxi_daudio->pinstate = + pinctrl_lookup_state(sunxi_daudio->pinctrl, PINCTRL_STATE_DEFAULT); + if (IS_ERR_OR_NULL(sunxi_daudio->pinstate)) { + dev_err(sunxi_daudio->dev, "pinctrl default state get failed\n"); + ret = -EINVAL; + goto err_pinctrl_put; + } - sunxi_daudio->pinstate_sleep = pinctrl_lookup_state( - sunxi_daudio->pinctrl, PINCTRL_STATE_SLEEP); - if (IS_ERR_OR_NULL(sunxi_daudio->pinstate_sleep)) { - dev_err(sunxi_daudio->dev, - "pinctrl sleep state get failed\n"); - ret = -EINVAL; - goto err_pinctrl_put; - } + sunxi_daudio->pinstate_sleep = + pinctrl_lookup_state(sunxi_daudio->pinctrl, PINCTRL_STATE_SLEEP); + if (IS_ERR_OR_NULL(sunxi_daudio->pinstate_sleep)) { + dev_err(sunxi_daudio->dev, "pinctrl sleep state get failed\n"); + ret = -EINVAL; + goto err_pinctrl_put; + } - ret = pinctrl_select_state(sunxi_daudio->pinctrl, - sunxi_daudio->pinstate); - if (ret) - dev_warn(sunxi_daudio->dev, - "daudio set pinctrl default state fail\n"); - } + ret = + pinctrl_select_state(sunxi_daudio->pinctrl, sunxi_daudio->pinstate); + if (ret) + dev_warn(sunxi_daudio->dev, + "daudio set pinctrl default state fail\n"); + } - sunxi_daudio_init(sunxi_daudio); + sunxi_daudio_init(sunxi_daudio); - /* Global enable I2S/TDM module */ - sunxi_daudio_global_enable(sunxi_daudio, 1); + /* Global enable I2S/TDM module */ + sunxi_daudio_global_enable(sunxi_daudio, 1); - if (sunxi_daudio->pdata->daudio_type == SUNXI_DAUDIO_TDMHDMI_TYPE) - regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, - (1<pdata->daudio_type == SUNXI_DAUDIO_TDMHDMI_TYPE) + regmap_update_bits(sunxi_daudio->regmap, SUNXI_DAUDIO_CTL, + (1 << CTL_TXEN), (1 << CTL_TXEN)); - pr_debug("[%s] resume .%s end\n", __func__, - dev_name(sunxi_daudio->dev)); - return 0; + pr_debug("[%s] resume .%s end\n", __func__, dev_name(sunxi_daudio->dev)); + return 0; err_pinctrl_put: - devm_pinctrl_put(sunxi_daudio->pinctrl); + devm_pinctrl_put(sunxi_daudio->pinctrl); err_moduleclk_disable: - clk_disable_unprepare(sunxi_daudio->moduleclk); + clk_disable_unprepare(sunxi_daudio->moduleclk); err_pllclk_disable: - clk_disable_unprepare(sunxi_daudio->pllclk); + clk_disable_unprepare(sunxi_daudio->pllclk); err_resume_out: - if (sunxi_daudio->vol_supply.daudio_regulator) - regulator_disable(sunxi_daudio->vol_supply.daudio_regulator); - return ret; + if (sunxi_daudio->vol_supply.daudio_regulator) + regulator_disable(sunxi_daudio->vol_supply.daudio_regulator); + return ret; } #if DAUDIO_STANDBY_DEBUG @@ -1421,77 +1368,74 @@ err_resume_out: * echo 1,0x1,0x1 > daudio_standby */ static ssize_t daudio_class_standby_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int i; - ssize_t count = 0; - int daudio_num = daudio_standby_debug >> 4; - int standby_mode = (daudio_standby_debug >> 1) & 0x1; - int enable = daudio_standby_debug & 0x1; + struct class_attribute *attr, + char *buf) { + int i; + ssize_t count = 0; + int daudio_num = daudio_standby_debug >> 4; + int standby_mode = (daudio_standby_debug >> 1) & 0x1; + int enable = daudio_standby_debug & 0x1; - if (daudio_standby_debug == 0) { - count += sprintf(buf, "Example(:daudio_num->%d):\n", DAUDIO_NUM_MAX); - count += sprintf(buf + count, "echo 0,0x1,0x1 > daudio_standby\n\n"); - count += sprintf(buf + count, "param 1: 0 Daudio0; 1 Daudio1;...\n"); - count += sprintf(buf + count, "param 2: 0 Suspend; 1 Resume;\n"); - count += sprintf(buf + count, "param 3: 0 disabled; 1 enabled;\n"); - count += sprintf(buf + count, "Daudio[1], Standby->[resume], Enable\n\n"); - return count; - } + if (daudio_standby_debug == 0) { + count += sprintf(buf, "Example(:daudio_num->%d):\n", DAUDIO_NUM_MAX); + count += sprintf(buf + count, "echo 0,0x1,0x1 > daudio_standby\n\n"); + count += sprintf(buf + count, "param 1: 0 Daudio0; 1 Daudio1;...\n"); + count += sprintf(buf + count, "param 2: 0 Suspend; 1 Resume;\n"); + count += sprintf(buf + count, "param 3: 0 disabled; 1 enabled;\n"); + count += + sprintf(buf + count, "Daudio[1], Standby->[resume], Enable\n\n"); + return count; + } - pr_err("[%s], Daudio[%d], Standby->[%s], %s\n", __func__, - daudio_num, - standby_mode ? "resume":"suspend", - enable ? "Enable":"Disable"); - for (i = 0; i < DAUDIO_NUM_MAX; i++) { - if (sunxi_daudio_global[i] && sunxi_daudio_global[i]->pdata) { - if ((sunxi_daudio_global[i]->pdata->tdm_num == - (daudio_standby_debug >> 4)) && - (daudio_standby_debug & 0x1)) { - if ((daudio_standby_debug >> 1) & 0x1) { - sunxi_daudio_debug_resume( - sunxi_daudio_global[i]); - } else { - sunxi_daudio_debug_suspend( - sunxi_daudio_global[i]); - } - } - } - } + pr_err("[%s], Daudio[%d], Standby->[%s], %s\n", __func__, daudio_num, + standby_mode ? "resume" : "suspend", enable ? "Enable" : "Disable"); + for (i = 0; i < DAUDIO_NUM_MAX; i++) { + if (sunxi_daudio_global[i] && sunxi_daudio_global[i]->pdata) { + if ((sunxi_daudio_global[i]->pdata->tdm_num == + (daudio_standby_debug >> 4)) && + (daudio_standby_debug & 0x1)) { + if ((daudio_standby_debug >> 1) & 0x1) { + sunxi_daudio_debug_resume(sunxi_daudio_global[i]); + } else { + sunxi_daudio_debug_suspend(sunxi_daudio_global[i]); + } + } + } + } - daudio_standby_debug = 0; - return 0; + daudio_standby_debug = 0; + return 0; } static ssize_t daudio_class_standby_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t count) -{ - int ret; - int input_reg_group = 0; - int standby_mode = 0; - int input_bool_val = 0; + struct class_attribute *attr, + const char *buf, size_t count) { + int ret; + int input_reg_group = 0; + int standby_mode = 0; + int input_bool_val = 0; - ret = sscanf(buf, "%d,0x%x,0x%x", &input_reg_group, - &standby_mode, &input_bool_val); - if ((input_reg_group >= DAUDIO_NUM_MAX) || (input_reg_group < 0)) { - pr_err("not exist daudio%d\n", input_reg_group); - return count; - } - if ((standby_mode > 1) || (standby_mode < 0) || - (input_bool_val > 1) || (input_bool_val < 0)) { - pr_err("is bool vaule!!\n"); - return count; - } + ret = sscanf(buf, "%d,0x%x,0x%x", &input_reg_group, &standby_mode, + &input_bool_val); + if ((input_reg_group >= DAUDIO_NUM_MAX) || (input_reg_group < 0)) { + pr_err("not exist daudio%d\n", input_reg_group); + return count; + } + if ((standby_mode > 1) || (standby_mode < 0) || (input_bool_val > 1) || + (input_bool_val < 0)) { + pr_err("is bool vaule!!\n"); + return count; + } - daudio_standby_debug = (input_reg_group << 4) & 0xf0; - daudio_standby_debug |= (standby_mode << 1) & 0x2; - daudio_standby_debug |= input_bool_val & 0x1; + daudio_standby_debug = (input_reg_group << 4) & 0xf0; + daudio_standby_debug |= (standby_mode << 1) & 0x2; + daudio_standby_debug |= input_bool_val & 0x1; - pr_err("ret:%d, Daudio[%d], Standby->[%s], %s\n", - ret, input_reg_group, standby_mode ? "resume":"suspend", - input_bool_val ? "Enable":"Disable"); + pr_err("ret:%d, Daudio[%d], Standby->[%s], %s\n", ret, input_reg_group, + standby_mode ? "resume" : "suspend", + input_bool_val ? "Enable" : "Disable"); - return count; + return count; } #endif @@ -1511,609 +1455,602 @@ static ssize_t daudio_class_standby_store(struct class *class, * echo 1,0,0x00,0xff > daudio_reg_debug */ static ssize_t daudio_class_debug_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t count) -{ - int ret; - int rw_flag; - int reg_val_read; - int input_reg_val = 0; - int input_reg_group = 0; - int input_reg_offset = 0; - int i = 0; + struct class_attribute *attr, + const char *buf, size_t count) { + int ret; + int rw_flag; + int reg_val_read; + int input_reg_val = 0; + int input_reg_group = 0; + int input_reg_offset = 0; + int i = 0; - ret = sscanf(buf, "%d,%d,0x%x,0x%x", &rw_flag, &input_reg_group, - &input_reg_offset, &input_reg_val); + ret = sscanf(buf, "%d,%d,0x%x,0x%x", &rw_flag, &input_reg_group, + &input_reg_offset, &input_reg_val); - if (!(rw_flag == 1 || rw_flag == 0)) { - pr_err("not rw_flag\n"); - return count; - } + if (!(rw_flag == 1 || rw_flag == 0)) { + pr_err("not rw_flag\n"); + return count; + } - if ((input_reg_group >= DAUDIO_NUM_MAX) || - !sunxi_daudio_global[input_reg_group]) { - pr_err("not exist daudio[%d] driver or device\n", - input_reg_group); - pr_err("Daudio device list:\n\n"); - for (i = 0; i < DAUDIO_NUM_MAX; i++) { - if (sunxi_daudio_global[i] != NULL) - pr_err(" Daudio[%d]\n", i); - } - return count; - } + if ((input_reg_group >= DAUDIO_NUM_MAX) || + !sunxi_daudio_global[input_reg_group]) { + pr_err("not exist daudio[%d] driver or device\n", input_reg_group); + pr_err("Daudio device list:\n\n"); + for (i = 0; i < DAUDIO_NUM_MAX; i++) { + if (sunxi_daudio_global[i] != NULL) + pr_err(" Daudio[%d]\n", i); + } + return count; + } - pr_err("Dump daudio reg:\n"); + pr_err("Dump daudio reg:\n"); - if (rw_flag) { - if (ret == 4) { - writel(input_reg_val, - sunxi_daudio_global[input_reg_group]->membase + - input_reg_offset); - reg_val_read = readl( - sunxi_daudio_global[input_reg_group]->membase + - input_reg_offset); - pr_err("\n\n Daudio[%d] Reg[0x%x] : 0x%x\n\n", - input_reg_group, input_reg_offset, - reg_val_read); - } else { - pr_err("\nnum of params invalid\n"); - } - } else { - switch (ret) { - case 2: - while (reg_labels[i].name != NULL) { - pr_err("%s 0x%p: 0x%x\n", reg_labels[i].name, - (sunxi_daudio_global[input_reg_group]->membase + - reg_labels[i].address), - readl(sunxi_daudio_global[input_reg_group]->membase + - reg_labels[i].address)); - i++; - } - break; - case 3: - reg_val_read = readl( - sunxi_daudio_global[input_reg_group]->membase + - input_reg_offset); - pr_err("\n\n Daudio[%d] Reg[0x%x] : 0x%x\n\n", - input_reg_group, input_reg_offset, - reg_val_read); - break; - default: - pr_err("\nnum of params invalid\n"); - break; - } - } + if (rw_flag) { + if (ret == 4) { + writel(input_reg_val, + sunxi_daudio_global[input_reg_group]->membase + + input_reg_offset); + reg_val_read = readl(sunxi_daudio_global[input_reg_group]->membase + + input_reg_offset); + pr_err("\n\n Daudio[%d] Reg[0x%x] : 0x%x\n\n", input_reg_group, + input_reg_offset, reg_val_read); + } else { + pr_err("\nnum of params invalid\n"); + } + } else { + switch (ret) { + case 2: + while (reg_labels[i].name != NULL) { + pr_err("%s 0x%p: 0x%x\n", reg_labels[i].name, + (sunxi_daudio_global[input_reg_group]->membase + + reg_labels[i].address), + readl(sunxi_daudio_global[input_reg_group]->membase + + reg_labels[i].address)); + i++; + } + break; + case 3: + reg_val_read = readl(sunxi_daudio_global[input_reg_group]->membase + + input_reg_offset); + pr_err("\n\n Daudio[%d] Reg[0x%x] : 0x%x\n\n", input_reg_group, + input_reg_offset, reg_val_read); + break; + default: + pr_err("\nnum of params invalid\n"); + break; + } + } - return count; + return count; } static ssize_t daudio_class_debug_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int count = 0; - int i = 0; + struct class_attribute *attr, + char *buf) { + int count = 0; + int i = 0; - count += sprintf(buf, "Example(:daudio_num->%d):\n", DAUDIO_NUM_MAX); - count += sprintf(buf + count, "param 1: 0 read; 1 write;\n"); - count += sprintf(buf + count, "param 2: 0 daudio0; 1 dauido1...;\n"); - count += sprintf(buf + count, "param 3: address\n"); - count += sprintf(buf + count, "param 4: reg value\n\n"); - count += sprintf(buf + count, "echo 0,0 > daudio_reg_debug\n"); - count += sprintf(buf + count, "echo 0,1,0x4 > daudio_reg_debug\n"); - count += sprintf(buf + count, "echo 1,0,0x4,0x1 > daudio_reg_debug\n"); - count += sprintf(buf + count, "echo 1,1,0x14,0xa > daudio_reg_debug\n\n"); + count += sprintf(buf, "Example(:daudio_num->%d):\n", DAUDIO_NUM_MAX); + count += sprintf(buf + count, "param 1: 0 read; 1 write;\n"); + count += sprintf(buf + count, "param 2: 0 daudio0; 1 dauido1...;\n"); + count += sprintf(buf + count, "param 3: address\n"); + count += sprintf(buf + count, "param 4: reg value\n\n"); + count += sprintf(buf + count, "echo 0,0 > daudio_reg_debug\n"); + count += sprintf(buf + count, "echo 0,1,0x4 > daudio_reg_debug\n"); + count += sprintf(buf + count, "echo 1,0,0x4,0x1 > daudio_reg_debug\n"); + count += sprintf(buf + count, "echo 1,1,0x14,0xa > daudio_reg_debug\n\n"); - count += sprintf(buf + count, "daudio device list:\n\n"); - for (i = 0; i < DAUDIO_NUM_MAX; i++) { - if (sunxi_daudio_global[i] != NULL) - count += sprintf(buf + count, " Daudio[%d]\n", i); - } + count += sprintf(buf + count, "daudio device list:\n\n"); + for (i = 0; i < DAUDIO_NUM_MAX; i++) { + if (sunxi_daudio_global[i] != NULL) + count += sprintf(buf + count, " Daudio[%d]\n", i); + } - return count; + return count; } static struct class_attribute daudio_class_attrs[] = { #if DAUDIO_STANDBY_DEBUG - __ATTR(daudio_standby, S_IRUGO|S_IWUSR, daudio_class_standby_show, daudio_class_standby_store), + __ATTR(daudio_standby, S_IRUGO | S_IWUSR, daudio_class_standby_show, + daudio_class_standby_store), #endif - __ATTR(daudio_reg_debug, S_IRUGO|S_IWUSR, daudio_class_debug_show, daudio_class_debug_store), - __ATTR_NULL -}; + __ATTR(daudio_reg_debug, S_IRUGO | S_IWUSR, daudio_class_debug_show, + daudio_class_debug_store), + __ATTR_NULL}; static struct class daudio_class = { - .name = "daudio", - .class_attrs = daudio_class_attrs, + .name = "daudio", + .class_attrs = daudio_class_attrs, }; - -#define SUNXI_DAUDIO_RATES (SNDRV_PCM_RATE_8000_192000 \ - | SNDRV_PCM_RATE_KNOT) +#define SUNXI_DAUDIO_RATES (SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT) static struct snd_soc_dai_ops sunxi_daudio_dai_ops = { - .hw_params = sunxi_daudio_hw_params, - .set_sysclk = sunxi_daudio_set_sysclk, - .set_clkdiv = sunxi_daudio_set_clkdiv, - .set_fmt = sunxi_daudio_set_fmt, - .startup = sunxi_daudio_dai_startup, - .trigger = sunxi_daudio_trigger, - .prepare = sunxi_daudio_prepare, - .shutdown = sunxi_daudio_shutdown, + .hw_params = sunxi_daudio_hw_params, + .set_sysclk = sunxi_daudio_set_sysclk, + .set_clkdiv = sunxi_daudio_set_clkdiv, + .set_fmt = sunxi_daudio_set_fmt, + .startup = sunxi_daudio_dai_startup, + .trigger = sunxi_daudio_trigger, + .prepare = sunxi_daudio_prepare, + .shutdown = sunxi_daudio_shutdown, }; static struct snd_soc_dai_driver sunxi_daudio_dai = { - .probe = sunxi_daudio_probe, - .suspend = sunxi_daudio_suspend, - .resume = sunxi_daudio_resume, - .remove = sunxi_daudio_remove, - .playback = { - .channels_min = 1, - .channels_max = 8, - .rates = SUNXI_DAUDIO_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE - | SNDRV_PCM_FMTBIT_S20_3LE - | SNDRV_PCM_FMTBIT_S24_LE - | SNDRV_PCM_FMTBIT_S32_LE, - }, - .capture = { - .channels_min = 1, - .channels_max = 8, - .rates = SUNXI_DAUDIO_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE - | SNDRV_PCM_FMTBIT_S20_3LE - | SNDRV_PCM_FMTBIT_S24_LE - | SNDRV_PCM_FMTBIT_S32_LE, - }, - .ops = &sunxi_daudio_dai_ops, + .probe = sunxi_daudio_probe, + .suspend = sunxi_daudio_suspend, + .resume = sunxi_daudio_resume, + .remove = sunxi_daudio_remove, + .playback = + { + .channels_min = 1, + .channels_max = 8, + .rates = SUNXI_DAUDIO_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, + }, + .capture = + { + .channels_min = 1, + .channels_max = 8, + .rates = SUNXI_DAUDIO_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &sunxi_daudio_dai_ops, }; static const struct snd_soc_component_driver sunxi_daudio_component = { - .name = DRV_NAME, - .controls = sunxi_daudio_controls, - .num_controls = ARRAY_SIZE(sunxi_daudio_controls), + .name = DRV_NAME, + .controls = sunxi_daudio_controls, + .num_controls = ARRAY_SIZE(sunxi_daudio_controls), }; static struct sunxi_daudio_platform_data sunxi_daudio = { - .daudio_type = SUNXI_DAUDIO_EXTERNAL_TYPE, - .external_type = 1, + .daudio_type = SUNXI_DAUDIO_EXTERNAL_TYPE, + .external_type = 1, }; static struct sunxi_daudio_platform_data sunxi_tdmhdmi = { - .daudio_type = SUNXI_DAUDIO_TDMHDMI_TYPE, - .external_type = 0, - .audio_format = 1, - .signal_inversion = 1, - .daudio_master = 4, - .pcm_lrck_period = 32, - .slot_width_select = 32, - .tdm_config = 1, - .mclk_div = 0, + .daudio_type = SUNXI_DAUDIO_TDMHDMI_TYPE, + .external_type = 0, + .audio_format = 1, + .signal_inversion = 1, + .daudio_master = 4, + .pcm_lrck_period = 32, + .slot_width_select = 32, + .tdm_config = 1, + .mclk_div = 0, }; static const struct of_device_id sunxi_daudio_of_match[] = { - { - .compatible = "allwinner,sunxi-daudio", - .data = &sunxi_daudio, - }, - { - .compatible = "allwinner,sunxi-tdmhdmi", - .data = &sunxi_tdmhdmi, - }, - {}, + { + .compatible = "allwinner,sunxi-daudio", + .data = &sunxi_daudio, + }, + { + .compatible = "allwinner,sunxi-tdmhdmi", + .data = &sunxi_tdmhdmi, + }, + {}, }; MODULE_DEVICE_TABLE(of, sunxi_daudio_of_match); static const struct regmap_config sunxi_daudio_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = SUNXI_DAUDIO_DEBUG, - .cache_type = REGCACHE_NONE, + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = SUNXI_DAUDIO_DEBUG, + .cache_type = REGCACHE_NONE, }; -static int sunxi_daudio_dev_probe(struct platform_device *pdev) -{ - struct resource res, *memregion; - const struct of_device_id *match; - void __iomem *sunxi_daudio_membase; - struct sunxi_daudio_info *sunxi_daudio; - struct device_node *np = pdev->dev.of_node; - unsigned int temp_val; - int ret; +static int sunxi_daudio_dev_probe(struct platform_device *pdev) { + struct resource res, *memregion; + const struct of_device_id *match; + void __iomem *sunxi_daudio_membase; + struct sunxi_daudio_info *sunxi_daudio; + struct device_node *np = pdev->dev.of_node; + unsigned int temp_val; + int ret; + printk("wzj:sunxi_daudio_dev_probe\n"); + match = of_match_device(sunxi_daudio_of_match, &pdev->dev); + if (match) { + sunxi_daudio = devm_kzalloc( + &pdev->dev, sizeof(struct sunxi_daudio_info), GFP_KERNEL); + if (!sunxi_daudio) { + dev_err(&pdev->dev, "alloc sunxi_daudio failed\n"); + ret = -ENOMEM; + goto err_node_put; + } + dev_set_drvdata(&pdev->dev, sunxi_daudio); + sunxi_daudio->dev = &pdev->dev; - match = of_match_device(sunxi_daudio_of_match, &pdev->dev); - if (match) { - sunxi_daudio = devm_kzalloc(&pdev->dev, - sizeof(struct sunxi_daudio_info), - GFP_KERNEL); - if (!sunxi_daudio) { - dev_err(&pdev->dev, "alloc sunxi_daudio failed\n"); - ret = -ENOMEM; - goto err_node_put; - } - dev_set_drvdata(&pdev->dev, sunxi_daudio); - sunxi_daudio->dev = &pdev->dev; + sunxi_daudio->pdata = devm_kzalloc( + &pdev->dev, sizeof(struct sunxi_daudio_platform_data), GFP_KERNEL); + if (!sunxi_daudio->pdata) { + dev_err(&pdev->dev, "alloc sunxi daudio platform data failed\n"); + ret = -ENOMEM; + goto err_devm_kfree; + } - sunxi_daudio->pdata = devm_kzalloc(&pdev->dev, - sizeof(struct sunxi_daudio_platform_data), - GFP_KERNEL); - if (!sunxi_daudio->pdata) { - dev_err(&pdev->dev, - "alloc sunxi daudio platform data failed\n"); - ret = -ENOMEM; - goto err_devm_kfree; - } + memcpy(sunxi_daudio->pdata, match->data, + sizeof(struct sunxi_daudio_platform_data)); + } else { + dev_err(&pdev->dev, "node match failed\n"); + return -EINVAL; + } - memcpy(sunxi_daudio->pdata, match->data, - sizeof(struct sunxi_daudio_platform_data)); - } else { - dev_err(&pdev->dev, "node match failed\n"); - return -EINVAL; - } - - ret = of_address_to_resource(np, 0, &res); - if (ret) { - dev_err(&pdev->dev, "parse device node resource failed\n"); - ret = -EINVAL; - goto err_devm_kfree; - } + ret = of_address_to_resource(np, 0, &res); + if (ret) { + dev_err(&pdev->dev, "parse device node resource failed\n"); + ret = -EINVAL; + goto err_devm_kfree; + } #ifdef CONFIG_SND_SUNXI_MAD - sunxi_daudio->mad_bind = 0; - sunxi_daudio->lpsd_chan_sel = 0; - sunxi_daudio->mad_standby_chan_sel = 0; - sunxi_daudio->res.start = res.start; - sunxi_daudio->capture_en = 0; + sunxi_daudio->mad_bind = 0; + sunxi_daudio->lpsd_chan_sel = 0; + sunxi_daudio->mad_standby_chan_sel = 0; + sunxi_daudio->res.start = res.start; + sunxi_daudio->capture_en = 0; #endif - memregion = devm_request_mem_region(&pdev->dev, res.start, - resource_size(&res), DRV_NAME); - if (!memregion) { - dev_err(&pdev->dev, "Memory region already claimed\n"); - ret = -EBUSY; - goto err_devm_kfree; - } + memregion = devm_request_mem_region(&pdev->dev, res.start, + resource_size(&res), DRV_NAME); + if (!memregion) { + dev_err(&pdev->dev, "Memory region already claimed\n"); + ret = -EBUSY; + goto err_devm_kfree; + } - sunxi_daudio_membase = ioremap(res.start, resource_size(&res)); - if (!sunxi_daudio_membase) { - dev_err(&pdev->dev, "ioremap failed\n"); - ret = -EBUSY; - goto err_devm_kfree; - } - sunxi_daudio->membase = sunxi_daudio_membase; + sunxi_daudio_membase = ioremap(res.start, resource_size(&res)); + if (!sunxi_daudio_membase) { + dev_err(&pdev->dev, "ioremap failed\n"); + ret = -EBUSY; + goto err_devm_kfree; + } + sunxi_daudio->membase = sunxi_daudio_membase; - sunxi_daudio->regmap = devm_regmap_init_mmio(&pdev->dev, - sunxi_daudio_membase, - &sunxi_daudio_regmap_config); - if (IS_ERR(sunxi_daudio->regmap)) { - dev_err(&pdev->dev, "regmap init failed\n"); - ret = PTR_ERR(sunxi_daudio->regmap); - goto err_iounmap; - } + sunxi_daudio->regmap = devm_regmap_init_mmio( + &pdev->dev, sunxi_daudio_membase, &sunxi_daudio_regmap_config); + if (IS_ERR(sunxi_daudio->regmap)) { + dev_err(&pdev->dev, "regmap init failed\n"); + ret = PTR_ERR(sunxi_daudio->regmap); + goto err_iounmap; + } - sunxi_daudio->pllclk = of_clk_get(np, 0); - if (IS_ERR_OR_NULL(sunxi_daudio->pllclk)) { - dev_err(&pdev->dev, "pllclk get failed\n"); - ret = PTR_ERR(sunxi_daudio->pllclk); - goto err_iounmap; - } + sunxi_daudio->pllclk = of_clk_get(np, 0); + if (IS_ERR_OR_NULL(sunxi_daudio->pllclk)) { + dev_err(&pdev->dev, "pllclk get failed\n"); + ret = PTR_ERR(sunxi_daudio->pllclk); + goto err_iounmap; + } - sunxi_daudio->moduleclk = of_clk_get(np, 1); - if (IS_ERR_OR_NULL(sunxi_daudio->moduleclk)) { - dev_err(&pdev->dev, "moduleclk get failed\n"); - ret = PTR_ERR(sunxi_daudio->moduleclk); - goto err_pllclk_put; - } + sunxi_daudio->moduleclk = of_clk_get(np, 1); + if (IS_ERR_OR_NULL(sunxi_daudio->moduleclk)) { + dev_err(&pdev->dev, "moduleclk get failed\n"); + ret = PTR_ERR(sunxi_daudio->moduleclk); + goto err_pllclk_put; + } - if (clk_set_parent(sunxi_daudio->moduleclk, sunxi_daudio->pllclk)) { - dev_err(&pdev->dev, "set parent of moduleclk to pllclk fail\n"); - ret = -EBUSY; - goto err_moduleclk_put; - } - clk_prepare_enable(sunxi_daudio->pllclk); - clk_prepare_enable(sunxi_daudio->moduleclk); + if (clk_set_parent(sunxi_daudio->moduleclk, sunxi_daudio->pllclk)) { + dev_err(&pdev->dev, "set parent of moduleclk to pllclk fail\n"); + ret = -EBUSY; + goto err_moduleclk_put; + } + clk_prepare_enable(sunxi_daudio->pllclk); + clk_prepare_enable(sunxi_daudio->moduleclk); - if (sunxi_daudio->pdata->external_type) { - sunxi_daudio->pinctrl = devm_pinctrl_get(&pdev->dev); - if (IS_ERR_OR_NULL(sunxi_daudio->pinctrl)) { - dev_err(&pdev->dev, "pinctrl get failed\n"); - ret = -EINVAL; - goto err_moduleclk_put; - } + if (sunxi_daudio->pdata->external_type) { + sunxi_daudio->pinctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR_OR_NULL(sunxi_daudio->pinctrl)) { + dev_err(&pdev->dev, "pinctrl get failed\n"); + ret = -EINVAL; + goto err_moduleclk_put; + } - sunxi_daudio->pinstate = pinctrl_lookup_state( - sunxi_daudio->pinctrl, PINCTRL_STATE_DEFAULT); - if (IS_ERR_OR_NULL(sunxi_daudio->pinstate)) { - dev_err(&pdev->dev, "pinctrl default state get fail\n"); - ret = -EINVAL; - goto err_pinctrl_put; - } + sunxi_daudio->pinstate = + pinctrl_lookup_state(sunxi_daudio->pinctrl, PINCTRL_STATE_DEFAULT); + if (IS_ERR_OR_NULL(sunxi_daudio->pinstate)) { + dev_err(&pdev->dev, "pinctrl default state get fail\n"); + ret = -EINVAL; + goto err_pinctrl_put; + } - sunxi_daudio->pinstate_sleep = pinctrl_lookup_state( - sunxi_daudio->pinctrl, PINCTRL_STATE_SLEEP); - if (IS_ERR_OR_NULL(sunxi_daudio->pinstate_sleep)) { - dev_err(&pdev->dev, "pinctrl sleep state get failed\n"); - ret = -EINVAL; - goto err_pinctrl_put; - } + sunxi_daudio->pinstate_sleep = + pinctrl_lookup_state(sunxi_daudio->pinctrl, PINCTRL_STATE_SLEEP); + if (IS_ERR_OR_NULL(sunxi_daudio->pinstate_sleep)) { + dev_err(&pdev->dev, "pinctrl sleep state get failed\n"); + ret = -EINVAL; + goto err_pinctrl_put; + } - ret = pinctrl_select_state(sunxi_daudio->pinctrl, - sunxi_daudio->pinstate); - if (ret) - dev_warn(sunxi_daudio->dev, - "daudio set pinctrl default state fail\n"); - } + ret = + pinctrl_select_state(sunxi_daudio->pinctrl, sunxi_daudio->pinstate); + if (ret) + dev_warn(sunxi_daudio->dev, + "daudio set pinctrl default state fail\n"); + } - switch (sunxi_daudio->pdata->daudio_type) { - case SUNXI_DAUDIO_EXTERNAL_TYPE: - ret = of_property_read_u32(np, "tdm_num", &temp_val); - if (ret < 0) { - dev_warn(&pdev->dev, "tdm configuration missing\n"); - /* - * warnning just continue, - * making tdm_num as default setting - */ - sunxi_daudio->pdata->tdm_num = 0; - } else { - /* - * FIXME, for channel number mess, - * so just not check channel overflow - */ - sunxi_daudio->pdata->tdm_num = temp_val; - } + switch (sunxi_daudio->pdata->daudio_type) { + case SUNXI_DAUDIO_EXTERNAL_TYPE: + ret = of_property_read_u32(np, "tdm_num", &temp_val); + if (ret < 0) { + dev_warn(&pdev->dev, "tdm configuration missing\n"); + /* + * warnning just continue, + * making tdm_num as default setting + */ + sunxi_daudio->pdata->tdm_num = 0; + } else { + /* + * FIXME, for channel number mess, + * so just not check channel overflow + */ + sunxi_daudio->pdata->tdm_num = temp_val; + } - sunxi_daudio->playback_dma_param.src_maxburst = 4; - sunxi_daudio->playback_dma_param.dst_maxburst = 4; + sunxi_daudio->playback_dma_param.src_maxburst = 4; + sunxi_daudio->playback_dma_param.dst_maxburst = 4; - sunxi_daudio->capture_dma_param.dma_addr = - res.start + SUNXI_DAUDIO_RXFIFO; - sunxi_daudio->capture_dma_param.src_maxburst = 4; - sunxi_daudio->capture_dma_param.dst_maxburst = 4; + sunxi_daudio->capture_dma_param.dma_addr = + res.start + SUNXI_DAUDIO_RXFIFO; + sunxi_daudio->capture_dma_param.src_maxburst = 4; + sunxi_daudio->capture_dma_param.dst_maxburst = 4; - sunxi_daudio->playback_dma_param.dma_addr = - res.start + SUNXI_DAUDIO_TXFIFO; - switch (sunxi_daudio->pdata->tdm_num) { - case 0: - SUNXI_DAUDIO_DRQDST(sunxi_daudio, 0); - SUNXI_DAUDIO_DRQSRC(sunxi_daudio, 0); - break; - case 1: - SUNXI_DAUDIO_DRQDST(sunxi_daudio, 1); - SUNXI_DAUDIO_DRQSRC(sunxi_daudio, 1); - break; - case 2: - SUNXI_DAUDIO_DRQDST(sunxi_daudio, 2); - SUNXI_DAUDIO_DRQSRC(sunxi_daudio, 2); - break; - case 3: - SUNXI_DAUDIO_DRQDST(sunxi_daudio, 3); - SUNXI_DAUDIO_DRQSRC(sunxi_daudio, 3); - break; - default: - dev_warn(&pdev->dev, "tdm_num setting overflow\n"); - ret = -EFAULT; - goto err_pinctrl_put; - break; - } + sunxi_daudio->playback_dma_param.dma_addr = + res.start + SUNXI_DAUDIO_TXFIFO; + switch (sunxi_daudio->pdata->tdm_num) { + case 0: + SUNXI_DAUDIO_DRQDST(sunxi_daudio, 0); + SUNXI_DAUDIO_DRQSRC(sunxi_daudio, 0); + break; + case 1: + SUNXI_DAUDIO_DRQDST(sunxi_daudio, 1); + SUNXI_DAUDIO_DRQSRC(sunxi_daudio, 1); + break; + case 2: + SUNXI_DAUDIO_DRQDST(sunxi_daudio, 2); + SUNXI_DAUDIO_DRQSRC(sunxi_daudio, 2); + break; + case 3: + SUNXI_DAUDIO_DRQDST(sunxi_daudio, 3); + SUNXI_DAUDIO_DRQSRC(sunxi_daudio, 3); + break; + default: + dev_warn(&pdev->dev, "tdm_num setting overflow\n"); + ret = -EFAULT; + goto err_pinctrl_put; + break; + } - sunxi_daudio->vol_supply.regulator_name = NULL; - ret = of_property_read_string(np, "daudio_regulator", - &sunxi_daudio->vol_supply.regulator_name); - if (ret < 0) { - dev_warn(&pdev->dev, "regulator missing or invalid\n"); - sunxi_daudio->vol_supply.daudio_regulator = NULL; - } else { - sunxi_daudio->vol_supply.daudio_regulator = - regulator_get(NULL, sunxi_daudio->vol_supply.regulator_name); - if (IS_ERR(sunxi_daudio->vol_supply.daudio_regulator)) { - pr_err("get duaido[%d] vcc-pin failed\n", - sunxi_daudio->pdata->tdm_num); - ret = -EFAULT; - goto err_pinctrl_put; - } else { - ret = regulator_set_voltage( - sunxi_daudio->vol_supply.daudio_regulator, - 3300000, 3300000); - if (ret) { - pr_err("set duaido[%d] voltage failed\n", - sunxi_daudio->pdata->tdm_num); - ret = -EFAULT; - goto err_regulator_get; - } - ret = regulator_enable( - sunxi_daudio->vol_supply.daudio_regulator); - if (ret) { - pr_err("enable duaido[%d] vcc-pin failed\n", - sunxi_daudio->pdata->tdm_num); - ret = -EFAULT; - goto err_regulator_get; - } - } - } + sunxi_daudio->vol_supply.regulator_name = NULL; + ret = of_property_read_string(np, "daudio_regulator", + &sunxi_daudio->vol_supply.regulator_name); + if (ret < 0) { + dev_warn(&pdev->dev, "regulator missing or invalid\n"); + sunxi_daudio->vol_supply.daudio_regulator = NULL; + } else { + sunxi_daudio->vol_supply.daudio_regulator = + regulator_get(NULL, sunxi_daudio->vol_supply.regulator_name); + if (IS_ERR(sunxi_daudio->vol_supply.daudio_regulator)) { + pr_err("get duaido[%d] vcc-pin failed\n", + sunxi_daudio->pdata->tdm_num); + ret = -EFAULT; + goto err_pinctrl_put; + } else { + ret = regulator_set_voltage( + sunxi_daudio->vol_supply.daudio_regulator, 3300000, + 3300000); + if (ret) { + pr_err("set duaido[%d] voltage failed\n", + sunxi_daudio->pdata->tdm_num); + ret = -EFAULT; + goto err_regulator_get; + } + ret = + regulator_enable(sunxi_daudio->vol_supply.daudio_regulator); + if (ret) { + pr_err("enable duaido[%d] vcc-pin failed\n", + sunxi_daudio->pdata->tdm_num); + ret = -EFAULT; + goto err_regulator_get; + } + } + } - ret = of_property_read_u32(np, "daudio_master", &temp_val); - if (ret < 0) { - dev_warn(&pdev->dev, "daudio_master configuration missing or invalid\n"); - /* - * default setting SND_SOC_DAIFMT_CBS_CFS mode - * codec clk & FRM slave - */ - sunxi_daudio->pdata->daudio_master = 4; - } else { - sunxi_daudio->pdata->daudio_master = temp_val; - } + ret = of_property_read_u32(np, "daudio_master", &temp_val); + if (ret < 0) { + dev_warn(&pdev->dev, + "daudio_master configuration missing or invalid\n"); + /* + * default setting SND_SOC_DAIFMT_CBS_CFS mode + * codec clk & FRM slave + */ + sunxi_daudio->pdata->daudio_master = 4; + } else { + sunxi_daudio->pdata->daudio_master = temp_val; + } - ret = of_property_read_u32(np, "pcm_lrck_period", &temp_val); - if (ret < 0) { - dev_warn(&pdev->dev, "pcm_lrck_period configuration missing or invalid\n"); - sunxi_daudio->pdata->pcm_lrck_period = 0; - } else { - sunxi_daudio->pdata->pcm_lrck_period = temp_val; - } + ret = of_property_read_u32(np, "pcm_lrck_period", &temp_val); + if (ret < 0) { + dev_warn(&pdev->dev, + "pcm_lrck_period configuration missing or invalid\n"); + sunxi_daudio->pdata->pcm_lrck_period = 0; + } else { + sunxi_daudio->pdata->pcm_lrck_period = temp_val; + } - ret = of_property_read_u32(np, "slot_width_select", &temp_val); - if (ret < 0) { - dev_warn(&pdev->dev, "slot_width_select configuration missing or invalid\n"); - sunxi_daudio->pdata->slot_width_select = 0; - } else { - sunxi_daudio->pdata->slot_width_select = temp_val; - } + ret = of_property_read_u32(np, "slot_width_select", &temp_val); + if (ret < 0) { + dev_warn(&pdev->dev, + "slot_width_select configuration missing or invalid\n"); + sunxi_daudio->pdata->slot_width_select = 0; + } else { + sunxi_daudio->pdata->slot_width_select = temp_val; + } - ret = of_property_read_u32(np, "audio_format", &temp_val); - if (ret < 0) { - dev_warn(&pdev->dev, "audio_format configuration missing or invalid\n"); - sunxi_daudio->pdata->audio_format = 1; - } else { - sunxi_daudio->pdata->audio_format = temp_val; - } + ret = of_property_read_u32(np, "audio_format", &temp_val); + if (ret < 0) { + dev_warn(&pdev->dev, + "audio_format configuration missing or invalid\n"); + sunxi_daudio->pdata->audio_format = 1; + } else { + sunxi_daudio->pdata->audio_format = temp_val; + } - ret = of_property_read_u32(np, "signal_inversion", &temp_val); - if (ret < 0) { - dev_warn(&pdev->dev, "signal_inversion configuration missing or invalid\n"); - sunxi_daudio->pdata->signal_inversion = 1; - } else { - sunxi_daudio->pdata->signal_inversion = temp_val; - } + ret = of_property_read_u32(np, "signal_inversion", &temp_val); + if (ret < 0) { + dev_warn(&pdev->dev, + "signal_inversion configuration missing or invalid\n"); + sunxi_daudio->pdata->signal_inversion = 1; + } else { + sunxi_daudio->pdata->signal_inversion = temp_val; + } - ret = of_property_read_u32(np, "frametype", &temp_val); - if (ret < 0) { - dev_warn(&pdev->dev, "frametype configuration missing or invalid\n"); - sunxi_daudio->pdata->frame_type = 0; - } else { - sunxi_daudio->pdata->frame_type = temp_val; - } + ret = of_property_read_u32(np, "frametype", &temp_val); + if (ret < 0) { + dev_warn(&pdev->dev, + "frametype configuration missing or invalid\n"); + sunxi_daudio->pdata->frame_type = 0; + } else { + sunxi_daudio->pdata->frame_type = temp_val; + } - ret = of_property_read_u32(np, "tdm_config", &temp_val); - if (ret < 0) { - dev_warn(&pdev->dev, "tdm_config configuration missing or invalid\n"); - sunxi_daudio->pdata->tdm_config = 1; - } else { - sunxi_daudio->pdata->tdm_config = temp_val; - } + ret = of_property_read_u32(np, "tdm_config", &temp_val); + if (ret < 0) { + dev_warn(&pdev->dev, + "tdm_config configuration missing or invalid\n"); + sunxi_daudio->pdata->tdm_config = 1; + } else { + sunxi_daudio->pdata->tdm_config = temp_val; + } - ret = of_property_read_u32(np, "mclk_div", &temp_val); - if (ret < 0) - sunxi_daudio->pdata->mclk_div = 0; - else - sunxi_daudio->pdata->mclk_div = temp_val; + ret = of_property_read_u32(np, "mclk_div", &temp_val); + if (ret < 0) + sunxi_daudio->pdata->mclk_div = 0; + else + sunxi_daudio->pdata->mclk_div = temp_val; - of_node_put(np); - break; - case SUNXI_DAUDIO_TDMHDMI_TYPE: + of_node_put(np); + break; + case SUNXI_DAUDIO_TDMHDMI_TYPE: #ifdef SUNXI_HDMI_AUDIO_ENABLE - sunxi_daudio->playback_dma_param.dma_addr = - res.start + SUNXI_DAUDIO_TXFIFO; - sunxi_daudio->playback_dma_param.dma_drq_type_num = - DRQDST_HDMI_TX; - sunxi_daudio->playback_dma_param.src_maxburst = 8; - sunxi_daudio->playback_dma_param.dst_maxburst = 8; - sunxi_daudio->hdmi_en = 1; + sunxi_daudio->playback_dma_param.dma_addr = + res.start + SUNXI_DAUDIO_TXFIFO; + sunxi_daudio->playback_dma_param.dma_drq_type_num = DRQDST_HDMI_TX; + sunxi_daudio->playback_dma_param.src_maxburst = 8; + sunxi_daudio->playback_dma_param.dst_maxburst = 8; + sunxi_daudio->hdmi_en = 1; #endif - break; - default: - dev_err(&pdev->dev, "missing digital audio type\n"); - ret = -EINVAL; - goto err_moduleclk_put; - } + break; + default: + dev_err(&pdev->dev, "missing digital audio type\n"); + ret = -EINVAL; + goto err_moduleclk_put; + } - ret = snd_soc_register_component(&pdev->dev, &sunxi_daudio_component, - &sunxi_daudio_dai, 1); - if (ret) { - dev_err(&pdev->dev, "component register failed\n"); - ret = -ENOMEM; - goto err_regulator_disable; - } + ret = snd_soc_register_component(&pdev->dev, &sunxi_daudio_component, + &sunxi_daudio_dai, 1); + if (ret) { + dev_err(&pdev->dev, "component register failed\n"); + ret = -ENOMEM; + goto err_regulator_disable; + } - switch (sunxi_daudio->pdata->daudio_type) { - case SUNXI_DAUDIO_EXTERNAL_TYPE: - ret = asoc_dma_platform_register(&pdev->dev, 0); - if (ret) { - dev_err(&pdev->dev, "register ASoC platform failed\n"); - ret = -ENOMEM; - goto err_unregister_component; - } - break; - case SUNXI_DAUDIO_TDMHDMI_TYPE: - ret = asoc_dma_platform_register(&pdev->dev, - SND_DMAENGINE_PCM_FLAG_NO_DT); - if (ret) { - dev_err(&pdev->dev, "register ASoC platform failed\n"); - ret = -ENOMEM; - goto err_unregister_component; - } - break; - default: - dev_err(&pdev->dev, "missing digital audio type\n"); - ret = -EINVAL; - goto err_unregister_component; - } + switch (sunxi_daudio->pdata->daudio_type) { + case SUNXI_DAUDIO_EXTERNAL_TYPE: + ret = asoc_dma_platform_register(&pdev->dev, 0); + if (ret) { + dev_err(&pdev->dev, "register ASoC platform failed\n"); + ret = -ENOMEM; + goto err_unregister_component; + } + break; + case SUNXI_DAUDIO_TDMHDMI_TYPE: + ret = asoc_dma_platform_register(&pdev->dev, + SND_DMAENGINE_PCM_FLAG_NO_DT); + if (ret) { + dev_err(&pdev->dev, "register ASoC platform failed\n"); + ret = -ENOMEM; + goto err_unregister_component; + } + break; + default: + dev_err(&pdev->dev, "missing digital audio type\n"); + ret = -EINVAL; + goto err_unregister_component; + } - if (device_count++ == 0) { - ret = class_register(&daudio_class); - if (ret) - pr_warn("daudio: Failed to create debugfs directory\n"); - } - sunxi_daudio_global[sunxi_daudio->pdata->tdm_num] = sunxi_daudio; + if (device_count++ == 0) { + ret = class_register(&daudio_class); + if (ret) + pr_warn("daudio: Failed to create debugfs directory\n"); + } + sunxi_daudio_global[sunxi_daudio->pdata->tdm_num] = sunxi_daudio; - sunxi_daudio_global_enable(sunxi_daudio, 1); - - return 0; + sunxi_daudio_global_enable(sunxi_daudio, 1); + printk("wzj: prbe end!\n"); + return 0; err_unregister_component: - snd_soc_unregister_component(&pdev->dev); + snd_soc_unregister_component(&pdev->dev); err_regulator_disable: - if (sunxi_daudio->pdata->external_type && - sunxi_daudio->vol_supply.daudio_regulator) - regulator_disable(sunxi_daudio->vol_supply.daudio_regulator); + if (sunxi_daudio->pdata->external_type && + sunxi_daudio->vol_supply.daudio_regulator) + regulator_disable(sunxi_daudio->vol_supply.daudio_regulator); err_regulator_get: - if (sunxi_daudio->pdata->external_type && - sunxi_daudio->vol_supply.daudio_regulator) - regulator_put(sunxi_daudio->vol_supply.daudio_regulator); + if (sunxi_daudio->pdata->external_type && + sunxi_daudio->vol_supply.daudio_regulator) + regulator_put(sunxi_daudio->vol_supply.daudio_regulator); err_pinctrl_put: - if (sunxi_daudio->pdata->external_type) - devm_pinctrl_put(sunxi_daudio->pinctrl); + if (sunxi_daudio->pdata->external_type) + devm_pinctrl_put(sunxi_daudio->pinctrl); err_moduleclk_put: - clk_put(sunxi_daudio->moduleclk); + clk_put(sunxi_daudio->moduleclk); err_pllclk_put: - clk_put(sunxi_daudio->pllclk); + clk_put(sunxi_daudio->pllclk); err_iounmap: - iounmap(sunxi_daudio_membase); + iounmap(sunxi_daudio_membase); err_devm_kfree: - devm_kfree(&pdev->dev, sunxi_daudio); + devm_kfree(&pdev->dev, sunxi_daudio); err_node_put: - of_node_put(np); - return ret; + of_node_put(np); + return ret; } -static int __exit sunxi_daudio_dev_remove(struct platform_device *pdev) -{ - struct sunxi_daudio_info *sunxi_daudio = dev_get_drvdata(&pdev->dev); +static int __exit sunxi_daudio_dev_remove(struct platform_device *pdev) { + struct sunxi_daudio_info *sunxi_daudio = dev_get_drvdata(&pdev->dev); - if (--device_count == 0) - class_unregister(&daudio_class); + if (--device_count == 0) + class_unregister(&daudio_class); - cancel_delayed_work_sync(&sunxi_daudio->resume_work); + cancel_delayed_work_sync(&sunxi_daudio->resume_work); - if (sunxi_daudio->pdata->external_type) - devm_pinctrl_put(sunxi_daudio->pinctrl); + if (sunxi_daudio->pdata->external_type) + devm_pinctrl_put(sunxi_daudio->pinctrl); - if (sunxi_daudio->vol_supply.daudio_regulator) { - regulator_disable(sunxi_daudio->vol_supply.daudio_regulator); - regulator_put(sunxi_daudio->vol_supply.daudio_regulator); - } + if (sunxi_daudio->vol_supply.daudio_regulator) { + regulator_disable(sunxi_daudio->vol_supply.daudio_regulator); + regulator_put(sunxi_daudio->vol_supply.daudio_regulator); + } - snd_soc_unregister_component(&pdev->dev); - clk_put(sunxi_daudio->moduleclk); - clk_put(sunxi_daudio->pllclk); - devm_kfree(&pdev->dev, sunxi_daudio); - return 0; + snd_soc_unregister_component(&pdev->dev); + clk_put(sunxi_daudio->moduleclk); + clk_put(sunxi_daudio->pllclk); + devm_kfree(&pdev->dev, sunxi_daudio); + return 0; } static struct platform_driver sunxi_daudio_driver = { - .probe = sunxi_daudio_dev_probe, - .remove = __exit_p(sunxi_daudio_dev_remove), - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, - .of_match_table = sunxi_daudio_of_match, - }, + .probe = sunxi_daudio_dev_probe, + .remove = __exit_p(sunxi_daudio_dev_remove), + .driver = + { + .name = DRV_NAME, + .owner = THIS_MODULE, + .of_match_table = sunxi_daudio_of_match, + }, }; module_platform_driver(sunxi_daudio_driver); diff --git a/lichee/linux-4.9/sound/soc/sunxi/sunxi-snddaudio.c b/lichee/linux-4.9/sound/soc/sunxi/sunxi-snddaudio.c index 7c0f29a87..673913438 100644 --- a/lichee/linux-4.9/sound/soc/sunxi/sunxi-snddaudio.c +++ b/lichee/linux-4.9/sound/soc/sunxi/sunxi-snddaudio.c @@ -102,6 +102,7 @@ static int sunxi_snddaudio_hw_params(struct snd_pcm_substream *substream, /* sunxi card initialization */ static int sunxi_snddaudio_init(struct snd_soc_pcm_runtime *rtd) { + printk("wzj:sunxi_snddaudio_init!\n"); return 0; } @@ -356,6 +357,9 @@ cpu_node_find: dai_link->codec_name, dai_link->codec_dai_name); + printk("wzj: codec: %s, codec_dai: %s.\n", + dai_link->codec_name, + dai_link->codec_dai_name); #ifdef CONFIG_SND_SUNXI_MAD sunxi_daudio_priv.mad_bind = 0; snd_soc_card_set_drvdata(card, &sunxi_daudio_priv); diff --git a/package/allwinner/adau1761/Makefile b/package/allwinner/adau1761/Makefile new file mode 100644 index 000000000..85dc10604 --- /dev/null +++ b/package/allwinner/adau1761/Makefile @@ -0,0 +1,98 @@ +############################################## +# OpenWrt Makefile for helloworld program +# +# +# Most of the variables used here are defined in +# the include directives below. We just need to +# specify a basic description of the package, +# where to build our program, where to find +# the source files, and where to install the +# compiled program on the router. +# +# Be very careful of spacing in this file. +# Indents should be tabs, not spaces, and +# there should be no trailing whitespace in +# lines that are not commented. +# +############################################## +include $(TOPDIR)/rules.mk + +# Name and release number of this package +PKG_NAME:=adau1761 +PKG_VERSION:=0.0.1 +PKG_RELEASE:=1 + + +# This specifies the directory where we're going to build the program. +# The root build directory, $(BUILD_DIR), is by default the build_mipsel +# directory in your OpenWrt SDK directory +PKG_BUILD_DIR := $(COMPILE_DIR)/$(PKG_NAME) + + +include $(BUILD_DIR)/package.mk + +# Specify package information for this program. +# The variables defined here should be self explanatory. +# If you are running Kamikaze, delete the DESCRIPTION +# variable below and uncomment the Kamikaze define +# directive for the description below +define Package/adau1761 + SECTION:=utils + CATEGORY:=Allwinner + TITLE:=just test adau1761 + DEPENDS:=+libpthread +endef + + +# Uncomment portion below for Kamikaze and delete DESCRIPTION variable above +define Package/adau1761/description + If you can't figure out what this program does, you're probably + brain-dead and need immediate medical attention. +endef + +# Specify what needs to be done to prepare for building the package. +# In our case, we need to copy the source files to the build directory. +# This is NOT the default. The default uses the PKG_SOURCE_URL and the +# PKG_SOURCE which is not defined here to download the source from the web. +# In order to just build a simple program that we have just written, it is +# much easier to do it this way. +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Build/Configure +endef + +define Build/Compile + $(MAKE) -C $(PKG_BUILD_DIR) \ + CC="$(TARGET_CC)" \ + CFLAGS="$(TARGET_CFLAGS)" -Wall \ + LDFLAGS="$(TARGET_LDFLAGS)" \ + LIBS="-lpthread" \ + all +endef + +# We do not need to define Build/Configure or Build/Compile directives +# The defaults are appropriate for compiling a simple program such as this one + + +# Specify where and how to install the program. Since we only have one file, +# the helloworld executable, install it by copying it to the /bin directory on +# the router. The $(1) variable represents the root directory on the router running +# OpenWrt. The $(INSTALL_DIR) variable contains a command to prepare the install +# directory if it does not already exist. Likewise $(INSTALL_BIN) contains the +# command to copy the binary file from its current location (in our case the build +# directory) to the install directory. +define Package/adau1761/install + $(INSTALL_DIR) $(1)/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/adau1761 $(1)/bin/ +endef + + +# This line executes the necessary commands to compile our program. +# The above define directives specify all the information needed, but this +# line calls BuildPackage which in turn actually uses this information to +# build a package. + +$(eval $(call BuildPackage,adau1761)) diff --git a/package/allwinner/adau1761/src/Makefile b/package/allwinner/adau1761/src/Makefile new file mode 100644 index 000000000..38fe68f1b --- /dev/null +++ b/package/allwinner/adau1761/src/Makefile @@ -0,0 +1,16 @@ +TARGET = adau1761 +LIBS += -lpthread -lm -lrt + +SRCS = main.c +OBJS = $(SRCS:.c=.o) + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +$(TARGET): $(OBJS) + $(CC) -o $@ $(OBJS) $(LIBS) $(LDFLAGS) + +all:$(TARGET) + +clean: + rm -rf $(TARGET) *.o *.a *~ diff --git a/package/allwinner/adau1761/src/main.c b/package/allwinner/adau1761/src/main.c new file mode 100755 index 000000000..c10721d23 --- /dev/null +++ b/package/allwinner/adau1761/src/main.c @@ -0,0 +1,148 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +// io commands +#define MAGIC_NUM 'A' +#define ADAU1761_CMD_VOL_SET _IOW(MAGIC_NUM, 0, int) +#define ADAU1761_CMD_VOL_GET _IOR(MAGIC_NUM, 1, int) +#define ADAU1761_CMD_AMP_MUTE_SET _IOW(MAGIC_NUM, 2, int) +#define ADAU1761_CMD_AMP_MUTE_GET _IOR(MAGIC_NUM, 3, int) +#define ADAU1761_CMD_SRC_SET _IOW(MAGIC_NUM, 4, int) +#define ADAU1761_CMD_SRC_GET _IOR(MAGIC_NUM, 5, int) +#define ADAU1761_CMD_FW_LOAD _IOW(MAGIC_NUM, 6, int) +#define ADAU1761_CMD_EQ_SET _IOW(MAGIC_NUM, 7, int) + +#define ADAU1761_CMD_MAX (7) + + +#define MAX_VOL_STEP (20) + +int main(int argc, char *argv[]) +{ + int fd, ret = 0; + unsigned int cmd; + unsigned long para; + char *path = "/dev/adau1761"; + + printf("argv1 is cmd, argv2 is para.\n"); + + if((atoi(argv[1]) < 0) || (atoi(argv[1]) > ADAU1761_CMD_MAX)) { + printf("argv1 is out of scope\n"); + exit(1); + } + + cmd = (unsigned int)atoi(argv[1]); + para = (unsigned long)atoi(argv[2]); + printf("cmd %ud, para %lu.\n", cmd, para); + + fd = open(path, O_RDWR); + + if(fd < 0) { + printf("open %s failed.\n", path); + } else { + printf("fd %d, cmd %ud, para %lu.\n", fd, cmd, para); + + switch(cmd) { + case 0: + if((para < 0) || (para > MAX_VOL_STEP)) { + printf("argv2 is out of scope\n"); + exit(2); + } + + cmd = _IOW(MAGIC_NUM, cmd, int); + + ret = ioctl(fd, cmd, para); + printf("return: %d\n", ret); + break; + + case 1: + cmd = _IOR(MAGIC_NUM, cmd, int); + ret = ioctl(fd, cmd, (unsigned long)¶); + printf("return: %lu\n", para); + + if((para < 0) || (para > MAX_VOL_STEP)) { + printf("vol is out of scope\n"); + exit(3); + } + + break; + + case 2: + if((para < 0) || (para > 1)) { + printf("argv2 is out of scope\n"); + exit(4); + } + + cmd = _IOW(MAGIC_NUM, cmd, int); + + ret = ioctl(fd, cmd, para); + printf("return: %d\n", ret); + break; + + case 3: + cmd = _IOR(MAGIC_NUM, cmd, int); + ret = ioctl(fd, cmd, (unsigned long)¶); + printf("return: %lu\n", para); + + if((para < 0) || (para > 1)) { + printf("mute is out of scope\n"); + exit(5); + } + break; + + case 4: + if((para < 0) || (para > 1)) { + printf("argv2 is out of scope\n"); + exit(6); + } + + cmd = _IOW(MAGIC_NUM, cmd, int); + + ret = ioctl(fd, cmd, para); + printf("return: %d\n", ret); + break; + + case 5: + cmd = _IOR(MAGIC_NUM, cmd, int); + ret = ioctl(fd, cmd, (unsigned long)¶); + printf("return: %lu\n", para); + + if((para < 0) || (para > 1)) { + printf("src is out of scope\n"); + exit(7); + } + break; + + case 6: + cmd = _IOW(MAGIC_NUM, cmd, int); + + ret = ioctl(fd, cmd, para); + printf("return: %d\n", ret); + break; + + case 7: + if((para < 0) || (para > 2)) { + printf("argv2 is out of scope\n"); + } + + cmd = _IOW(MAGIC_NUM, cmd, int); + + ret = ioctl(fd, cmd, para); + printf("return: %d\n", ret); + break; + + default: + break; + } + } + + close(fd); + + return ret; +} diff --git a/package/base-files/files/etc/config/system b/package/base-files/files/etc/config/system index 021169978..3c6cfdeba 100644 --- a/package/base-files/files/etc/config/system +++ b/package/base-files/files/etc/config/system @@ -1,6 +1,6 @@ config system option hostname TinaLinux - option timezone Asia/Shanghai + option zonename Asia/Shanghai option timezone CST-8 option log_file /root/.lastlog option log_size 512 diff --git a/package/base-files/files/usr/share/golang/lib/time/zoneinfo.zip b/package/base-files/files/usr/share/golang/lib/time/zoneinfo.zip new file mode 100644 index 0000000000000000000000000000000000000000..d33dc1d2732850506f8927aae9d0ba8e487dd783 GIT binary patch literal 366113 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