diff --git a/asoc/codecs/csra66x0/Kbuild b/asoc/codecs/csra66x0/Kbuild new file mode 100644 index 0000000000..c23811c23a --- /dev/null +++ b/asoc/codecs/csra66x0/Kbuild @@ -0,0 +1,105 @@ +# We can build either as part of a standalone Kernel build or as +# an external module. Determine which mechanism is being used +ifeq ($(MODNAME),) + KERNEL_BUILD := 1 +else + KERNEL_BUILD := 0 +endif + + +ifeq ($(KERNEL_BUILD), 1) + # These are configurable via Kconfig for kernel-based builds + # Need to explicitly configure for Android-based builds + AUDIO_BLD_DIR := $(ANDROID_BUILD_TOP)/kernel/msm-4.14 + AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio +endif + +ifeq ($(KERNEL_BUILD), 0) + ifeq ($(CONFIG_ARCH_QCS405), y) + include $(AUDIO_ROOT)/config/qcs405auto.conf + export + INCS += -include $(AUDIO_ROOT)/config/qcs405autoconf.h + endif +endif + +# As per target team, build is done as follows: +# Defconfig : build with default flags +# Slub : defconfig + CONFIG_SLUB_DEBUG := y + +# CONFIG_SLUB_DEBUG_ON := y + CONFIG_PAGE_POISONING := y +# Perf : Using appropriate msmXXXX-perf_defconfig +# +# Shipment builds (user variants) should not have any debug feature +# enabled. This is identified using 'TARGET_BUILD_VARIANT'. Slub builds +# are identified using the CONFIG_SLUB_DEBUG_ON configuration. Since +# there is no other way to identify defconfig builds, QTI internal +# representation of perf builds (identified using the string 'perf'), +# is used to identify if the build is a slub or defconfig one. This +# way no critical debug feature will be enabled for perf and shipment +# builds. Other OEMs are also protected using the TARGET_BUILD_VARIANT +# config. + +############ UAPI ############ +UAPI_DIR := uapi +UAPI_INC := -I$(AUDIO_ROOT)/include/$(UAPI_DIR) + +############ COMMON ############ +COMMON_DIR := include +COMMON_INC := -I$(AUDIO_ROOT)/$(COMMON_DIR) + +############ CSRA66X0 ############ + +# for CSRA66X0 Codec +ifdef CONFIG_SND_SOC_CSRA66X0 + CSRA66X0_OBJS += csra66x0.o +endif + +LINUX_INC += -Iinclude/linux + +INCS += $(COMMON_INC) \ + $(UAPI_INC) + +#EXTRA_CFLAGS += $(INCS) +ccflags-y += $(INCS) + + +CDEFINES += -DANI_LITTLE_BYTE_ENDIAN \ + -DANI_LITTLE_BIT_ENDIAN \ + -DDOT11F_LITTLE_ENDIAN_HOST \ + -DANI_COMPILER_TYPE_GCC \ + -DANI_OS_TYPE_ANDROID=6 \ + -DPTT_SOCK_SVC_ENABLE \ + -Wall\ + -Werror\ + -D__linux__ + +KBUILD_CPPFLAGS += $(CDEFINES) + +# Currently, for versions of gcc which support it, the kernel Makefile +# is disabling the maybe-uninitialized warning. Re-enable it for the +# AUDIO driver. Note that we must use EXTRA_CFLAGS here so that it +# will override the kernel settings. +ifeq ($(call cc-option-yn, -Wmaybe-uninitialized),y) +#EXTRA_CFLAGS += -Wmaybe-uninitialized +ccflags-y += -Wmaybe-uninitialized +endif +#EXTRA_CFLAGS += -Wmissing-prototypes + +ifeq ($(call cc-option-yn, -Wheader-guard),y) +#EXTRA_CFLAGS += -Wheader-guard +ccflags-y += -Wheader-guard +endif + +ifeq ($(KERNEL_BUILD), 0) +KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/ipc/Module.symvers +KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/dsp/Module.symvers +KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/Module.symvers +KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/Module.symvers +KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/soc/Module.symvers +endif + +# Module information used by KBuild framework +obj-$(CONFIG_SND_SOC_CSRA66X0) += csra66x0_dlkm.o +csra66x0_dlkm-y := $(CSRA66X0_OBJS) + +# inject some build related information +DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/asoc/codecs/csra66x0/csra66x0.c b/asoc/codecs/csra66x0/csra66x0.c new file mode 100644 index 0000000000..e9e11cb387 --- /dev/null +++ b/asoc/codecs/csra66x0/csra66x0.c @@ -0,0 +1,767 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "csra66x0.h" + +/* CSRA66X0 register default values */ +static struct reg_default csra66x0_reg_defaults[] = { + {CSRA66X0_AUDIO_IF_RX_CONFIG1, 0x00}, + {CSRA66X0_AUDIO_IF_RX_CONFIG2, 0x0B}, + {CSRA66X0_AUDIO_IF_RX_CONFIG3, 0x0F}, + {CSRA66X0_AUDIO_IF_TX_EN, 0x00}, + {CSRA66X0_AUDIO_IF_TX_CONFIG1, 0x6B}, + {CSRA66X0_AUDIO_IF_TX_CONFIG2, 0x02}, + {CSRA66X0_I2C_DEVICE_ADDRESS, 0x0D}, + {CSRA66X0_CHIP_ID_FA, 0x39}, + {CSRA66X0_ROM_VER_FA, 0x08}, + {CSRA66X0_CHIP_REV_0_FA, 0x05}, + {CSRA66X0_CHIP_REV_1_FA, 0x03}, + {CSRA66X0_CH1_MIX_SEL, 0x01}, + {CSRA66X0_CH2_MIX_SEL, 0x10}, + {CSRA66X0_CH1_SAMPLE1_SCALE_0, 0x00}, + {CSRA66X0_CH1_SAMPLE1_SCALE_1, 0x20}, + {CSRA66X0_CH1_SAMPLE3_SCALE_0, 0x00}, + {CSRA66X0_CH1_SAMPLE3_SCALE_1, 0x20}, + {CSRA66X0_CH1_SAMPLE5_SCALE_0, 0x00}, + {CSRA66X0_CH1_SAMPLE5_SCALE_1, 0x20}, + {CSRA66X0_CH1_SAMPLE7_SCALE_0, 0x00}, + {CSRA66X0_CH1_SAMPLE7_SCALE_1, 0x20}, + {CSRA66X0_CH1_SAMPLE2_SCALE_0, 0x00}, + {CSRA66X0_CH1_SAMPLE2_SCALE_1, 0x20}, + {CSRA66X0_CH1_SAMPLE4_SCALE_0, 0x00}, + {CSRA66X0_CH1_SAMPLE4_SCALE_1, 0x20}, + {CSRA66X0_CH1_SAMPLE6_SCALE_0, 0x00}, + {CSRA66X0_CH1_SAMPLE6_SCALE_1, 0x20}, + {CSRA66X0_CH1_SAMPLE8_SCALE_0, 0x00}, + {CSRA66X0_CH1_SAMPLE8_SCALE_1, 0x20}, + {CSRA66X0_CH2_SAMPLE1_SCALE_0, 0x00}, + {CSRA66X0_CH2_SAMPLE1_SCALE_1, 0x20}, + {CSRA66X0_CH2_SAMPLE3_SCALE_0, 0x00}, + {CSRA66X0_CH2_SAMPLE3_SCALE_1, 0x20}, + {CSRA66X0_CH2_SAMPLE5_SCALE_0, 0x00}, + {CSRA66X0_CH2_SAMPLE5_SCALE_1, 0x20}, + {CSRA66X0_CH2_SAMPLE7_SCALE_0, 0x00}, + {CSRA66X0_CH2_SAMPLE7_SCALE_1, 0x20}, + {CSRA66X0_CH2_SAMPLE2_SCALE_0, 0x00}, + {CSRA66X0_CH2_SAMPLE2_SCALE_1, 0x20}, + {CSRA66X0_CH2_SAMPLE4_SCALE_0, 0x00}, + {CSRA66X0_CH2_SAMPLE4_SCALE_1, 0x20}, + {CSRA66X0_CH2_SAMPLE6_SCALE_0, 0x00}, + {CSRA66X0_CH2_SAMPLE6_SCALE_1, 0x20}, + {CSRA66X0_CH2_SAMPLE8_SCALE_0, 0x00}, + {CSRA66X0_CH2_SAMPLE8_SCALE_1, 0x20}, + {CSRA66X0_VOLUME_CONFIG_FA, 0x26}, + {CSRA66X0_STARTUP_DELAY_FA, 0x00}, + {CSRA66X0_CH1_VOLUME_0_FA, 0x19}, + {CSRA66X0_CH1_VOLUME_1_FA, 0x01}, + {CSRA66X0_CH2_VOLUME_0_FA, 0x19}, + {CSRA66X0_CH2_VOLUME_1_FA, 0x01}, + {CSRA66X0_QUAD_ENC_COUNT_0_FA, 0x00}, + {CSRA66X0_QUAD_ENC_COUNT_1_FA, 0x00}, + {CSRA66X0_SOFT_CLIP_CONFIG, 0x00}, + {CSRA66X0_CH1_HARD_CLIP_THRESH, 0x00}, + {CSRA66X0_CH2_HARD_CLIP_THRESH, 0x00}, + {CSRA66X0_SOFT_CLIP_THRESH, 0x00}, + {CSRA66X0_DS_ENABLE_THRESH_0, 0x05}, + {CSRA66X0_DS_ENABLE_THRESH_1, 0x00}, + {CSRA66X0_DS_TARGET_COUNT_0, 0x00}, + {CSRA66X0_DS_TARGET_COUNT_1, 0xFF}, + {CSRA66X0_DS_TARGET_COUNT_2, 0xFF}, + {CSRA66X0_DS_DISABLE_THRESH_0, 0x0F}, + {CSRA66X0_DS_DISABLE_THRESH_1, 0x00}, + {CSRA66X0_DCA_CTRL, 0x07}, + {CSRA66X0_CH1_DCA_THRESH, 0x40}, + {CSRA66X0_CH2_DCA_THRESH, 0x40}, + {CSRA66X0_DCA_ATTACK_RATE, 0x00}, + {CSRA66X0_DCA_RELEASE_RATE, 0x00}, + {CSRA66X0_CH1_OUTPUT_INVERT_EN, 0x00}, + {CSRA66X0_CH2_OUTPUT_INVERT_EN, 0x00}, + {CSRA66X0_CH1_176P4K_DELAY, 0x00}, + {CSRA66X0_CH2_176P4K_DELAY, 0x00}, + {CSRA66X0_CH1_192K_DELAY, 0x00}, + {CSRA66X0_CH2_192K_DELAY, 0x00}, + {CSRA66X0_DEEMP_CONFIG_FA, 0x00}, + {CSRA66X0_CH1_TREBLE_GAIN_CTRL_FA, 0x00}, + {CSRA66X0_CH2_TREBLE_GAIN_CTRL_FA, 0x00}, + {CSRA66X0_CH1_TREBLE_FC_CTRL_FA, 0x00}, + {CSRA66X0_CH2_TREBLE_FC_CTRL_FA, 0x00}, + {CSRA66X0_CH1_BASS_GAIN_CTRL_FA, 0x00}, + {CSRA66X0_CH2_BASS_GAIN_CTRL_FA, 0x00}, + {CSRA66X0_CH1_BASS_FC_CTRL_FA, 0x00}, + {CSRA66X0_CH2_BASS_FC_CTRL_FA, 0x00}, + {CSRA66X0_FILTER_SEL_8K, 0x00}, + {CSRA66X0_FILTER_SEL_11P025K, 0x00}, + {CSRA66X0_FILTER_SEL_16K, 0x00}, + {CSRA66X0_FILTER_SEL_22P05K, 0x00}, + {CSRA66X0_FILTER_SEL_32K, 0x00}, + {CSRA66X0_FILTER_SEL_44P1K_48K, 0x00}, + {CSRA66X0_FILTER_SEL_88P2K_96K, 0x00}, + {CSRA66X0_FILTER_SEL_176P4K_192K, 0x00}, + /* RESERVED */ + {CSRA66X0_USER_DSP_CTRL, 0x00}, + {CSRA66X0_TEST_TONE_CTRL, 0x00}, + {CSRA66X0_TEST_TONE_FREQ_0, 0x00}, + {CSRA66X0_TEST_TONE_FREQ_1, 0x00}, + {CSRA66X0_TEST_TONE_FREQ_2, 0x00}, + {CSRA66X0_AUDIO_RATE_CTRL_FA, 0x08}, + {CSRA66X0_MODULATION_INDEX_CTRL, 0x3F}, + {CSRA66X0_MODULATION_INDEX_COUNT, 0x10}, + {CSRA66X0_MIN_MODULATION_PULSE_WIDTH, 0x7A}, + {CSRA66X0_DEAD_TIME_CTRL, 0x00}, + {CSRA66X0_DEAD_TIME_THRESHOLD_0, 0xE7}, + {CSRA66X0_DEAD_TIME_THRESHOLD_1, 0x26}, + {CSRA66X0_DEAD_TIME_THRESHOLD_2, 0x40}, + {CSRA66X0_CH1_LOW_SIDE_DLY, 0x00}, + {CSRA66X0_CH2_LOW_SIDE_DLY, 0x00}, + {CSRA66X0_SPECTRUM_CTRL, 0x00}, + /* RESERVED */ + {CSRA66X0_SPECTRUM_SPREAD_CTRL, 0x0C}, + /* RESERVED */ + {CSRA66X0_EXT_PA_PROTECT_POLARITY, 0x03}, + {CSRA66X0_TEMP0_BACKOFF_COMP_VALUE, 0x98}, + {CSRA66X0_TEMP0_SHUTDOWN_COMP_VALUE, 0xA3}, + {CSRA66X0_TEMP1_BACKOFF_COMP_VALUE, 0x98}, + {CSRA66X0_TEMP1_SHUTDOWN_COMP_VALUE, 0xA3}, + {CSRA66X0_TEMP_PROT_BACKOFF, 0x00}, + {CSRA66X0_TEMP_READ0_FA, 0x00}, + {CSRA66X0_TEMP_READ1_FA, 0x00}, + {CSRA66X0_CHIP_STATE_CTRL_FA, 0x02}, + /* RESERVED */ + {CSRA66X0_PWM_OUTPUT_CONFIG, 0x00}, + {CSRA66X0_MISC_CONTROL_STATUS_0, 0x08}, + {CSRA66X0_MISC_CONTROL_STATUS_1_FA, 0x40}, + {CSRA66X0_PIO0_SELECT, 0x00}, + {CSRA66X0_PIO1_SELECT, 0x00}, + {CSRA66X0_PIO2_SELECT, 0x00}, + {CSRA66X0_PIO3_SELECT, 0x00}, + {CSRA66X0_PIO4_SELECT, 0x00}, + {CSRA66X0_PIO5_SELECT, 0x00}, + {CSRA66X0_PIO6_SELECT, 0x00}, + {CSRA66X0_PIO7_SELECT, 0x00}, + {CSRA66X0_PIO8_SELECT, 0x00}, + {CSRA66X0_PIO_DIRN0, 0xFF}, + {CSRA66X0_PIO_DIRN1, 0x01}, + {CSRA66X0_PIO_PULL_EN0, 0xFF}, + {CSRA66X0_PIO_PULL_EN1, 0x01}, + {CSRA66X0_PIO_PULL_DIR0, 0x00}, + {CSRA66X0_PIO_PULL_DIR1, 0x00}, + {CSRA66X0_PIO_DRIVE_OUT0_FA, 0x00}, + {CSRA66X0_PIO_DRIVE_OUT1_FA, 0x00}, + {CSRA66X0_PIO_STATUS_IN0_FA, 0x00}, + {CSRA66X0_PIO_STATUS_IN1_FA, 0x00}, + /* RESERVED */ + {CSRA66X0_IRQ_OUTPUT_ENABLE, 0x00}, + {CSRA66X0_IRQ_OUTPUT_POLARITY, 0x01}, + {CSRA66X0_IRQ_OUTPUT_STATUS_FA, 0x00}, + {CSRA66X0_CLIP_DCA_STATUS_FA, 0x00}, + {CSRA66X0_CHIP_STATE_STATUS_FA, 0x02}, + {CSRA66X0_FAULT_STATUS_FA, 0x00}, + {CSRA66X0_OTP_STATUS_FA, 0x00}, + {CSRA66X0_AUDIO_IF_STATUS_FA, 0x00}, + /* RESERVED */ + {CSRA66X0_DSP_SATURATION_STATUS_FA, 0x00}, + {CSRA66X0_AUDIO_RATE_STATUS_FA, 0x00}, + /* RESERVED */ + {CSRA66X0_DISABLE_PWM_OUTPUT, 0x00}, + /* RESERVED */ + {CSRA66X0_OTP_VER_FA, 0x03}, + {CSRA66X0_RAM_VER_FA, 0x02}, + /* RESERVED */ + {CSRA66X0_AUDIO_SATURATION_FLAGS_FA, 0x00}, + {CSRA66X0_DCOFFSET_CHAN_1_01_FA, 0x00}, + {CSRA66X0_DCOFFSET_CHAN_1_02_FA, 0x00}, + {CSRA66X0_DCOFFSET_CHAN_1_03_FA, 0x00}, + {CSRA66X0_DCOFFSET_CHAN_2_01_FA, 0x00}, + {CSRA66X0_DCOFFSET_CHAN_2_02_FA, 0x00}, + {CSRA66X0_DCOFFSET_CHAN_2_03_FA, 0x00}, + {CSRA66X0_FORCED_PA_SWITCHING_CTRL, 0x90}, + {CSRA66X0_PA_FORCE_PULSE_WIDTH, 0x07}, + {CSRA66X0_PA_HIGH_MODULATION_CTRL_CH1, 0x00}, + /* RESERVED */ + {CSRA66X0_HIGH_MODULATION_THRESHOLD_LOW, 0xD4}, + {CSRA66X0_HIGH_MODULATION_THRESHOLD_HIGH, 0x78}, + /* RESERVED */ + {CSRA66X0_PA_FREEZE_CTRL, 0x00}, + {CSRA66X0_DCA_FREEZE_CTRL, 0x3C}, + /* RESERVED */ +}; + +static bool csra66x0_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CSRA66X0_CHIP_ID_FA: + case CSRA66X0_TEMP_READ0_FA: + case CSRA66X0_TEMP_READ1_FA: + case CSRA66X0_MISC_CONTROL_STATUS_1_FA: + case CSRA66X0_IRQ_OUTPUT_STATUS_FA: + case CSRA66X0_CLIP_DCA_STATUS_FA: + case CSRA66X0_CHIP_STATE_STATUS_FA: + case CSRA66X0_FAULT_STATUS_FA: + case CSRA66X0_OTP_STATUS_FA: + case CSRA66X0_AUDIO_IF_STATUS_FA: + case CSRA66X0_DSP_SATURATION_STATUS_FA: + case CSRA66X0_AUDIO_RATE_STATUS_FA: + return true; + default: + return false; + } +} + +static bool csra66x0_writeable_registers(struct device *dev, unsigned int reg) +{ + if ((reg >= CSRA66X0_AUDIO_IF_RX_CONFIG1) + && (reg <= CSRA66X0_MAX_REGISTER_ADDR)) + return true; + + return false; +} + +static bool csra66x0_readable_registers(struct device *dev, unsigned int reg) +{ + if ((reg >= CSRA66X0_AUDIO_IF_RX_CONFIG1) + && (reg <= CSRA66X0_MAX_REGISTER_ADDR)) + return true; + + return false; +} + +/* codec private data */ +struct csra66x0_priv { + struct regmap *regmap; + struct snd_soc_codec *codec; + int spk_volume_ch1; + int spk_volume_ch2; + int irq; + int vreg_gpio; + u32 irq_active_low; + u32 in_cluster; + u32 is_master; +}; + +/* + * CSRA66X0 Controls + */ +static const DECLARE_TLV_DB_SCALE(csra66x0_volume_tlv, -9000, 25, 0); +static const DECLARE_TLV_DB_RANGE(csra66x0_bass_treble_tlv, + 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), + 1, 15, TLV_DB_SCALE_ITEM(-1500, 100, 0), + 16, 30, TLV_DB_SCALE_ITEM(100, 100, 0) +); + +static int csra66x0_get_volume(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + unsigned int reg_l = mc->reg; + unsigned int reg_r = mc->rreg; + unsigned int val_l, val_r; + + val_l = (snd_soc_read(codec, reg_l) & 0xff) | + ((snd_soc_read(codec, + CSRA66X0_CH1_VOLUME_1_FA) & (0x01)) << 8); + val_r = (snd_soc_read(codec, reg_r) & 0xff) | + ((snd_soc_read(codec, + CSRA66X0_CH2_VOLUME_1_FA) & (0x01)) << 8); + ucontrol->value.integer.value[0] = val_l; + ucontrol->value.integer.value[1] = val_r; + return 0; +} + +static int csra66x0_set_volume(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct csra66x0_priv *csra66x0 = snd_soc_codec_get_drvdata(codec); + unsigned int reg_l = mc->reg; + unsigned int reg_r = mc->rreg; + unsigned int val_l[2]; + unsigned int val_r[2]; + + csra66x0->spk_volume_ch1 = (ucontrol->value.integer.value[0]); + csra66x0->spk_volume_ch2 = (ucontrol->value.integer.value[1]); + val_l[0] = csra66x0->spk_volume_ch1 & SPK_VOLUME_LSB_MSK; + val_l[1] = (csra66x0->spk_volume_ch1 & SPK_VOLUME_MSB_MSK) ? 1 : 0; + val_r[0] = csra66x0->spk_volume_ch2 & SPK_VOLUME_LSB_MSK; + val_r[1] = (csra66x0->spk_volume_ch2 & SPK_VOLUME_MSB_MSK) ? 1 : 0; + snd_soc_write(codec, reg_l, val_l[0]); + snd_soc_write(codec, reg_r, val_r[0]); + snd_soc_write(codec, CSRA66X0_CH1_VOLUME_1_FA, val_l[1]); + snd_soc_write(codec, CSRA66X0_CH2_VOLUME_1_FA, val_r[1]); + return 0; +} + +/* enumerated controls */ +static const char * const csra66x0_mute_output_text[] = {"PLAY", "MUTE"}; +static const char * const csra66x0_output_invert_text[] = { + "UNCHANGED", "INVERTED"}; +static const char * const csra66x0_deemp_config_text[] = { + "DISABLED", "ENABLED"}; + +SOC_ENUM_SINGLE_DECL(csra66x0_mute_output_enum, + CSRA66X0_MISC_CONTROL_STATUS_1_FA, 2, + csra66x0_mute_output_text); +SOC_ENUM_SINGLE_DECL(csra66x0_ch1_output_invert_enum, + CSRA66X0_CH1_OUTPUT_INVERT_EN, 0, + csra66x0_output_invert_text); +SOC_ENUM_SINGLE_DECL(csra66x0_ch2_output_invert_enum, + CSRA66X0_CH2_OUTPUT_INVERT_EN, 0, + csra66x0_output_invert_text); +SOC_ENUM_DOUBLE_DECL(csra66x0_deemp_config_enum, + CSRA66X0_DEEMP_CONFIG_FA, 0, 1, + csra66x0_deemp_config_text); + +static const struct snd_kcontrol_new csra66x0_snd_controls[] = { + /* volume */ + SOC_DOUBLE_R_EXT_TLV("PA VOLUME", CSRA66X0_CH1_VOLUME_0_FA, + CSRA66X0_CH2_VOLUME_0_FA, 0, 0x1C9, 0, + csra66x0_get_volume, csra66x0_set_volume, + csra66x0_volume_tlv), + + /* bass treble */ + SOC_DOUBLE_R_TLV("PA BASS GAIN", CSRA66X0_CH1_BASS_GAIN_CTRL_FA, + CSRA66X0_CH2_BASS_GAIN_CTRL_FA, 0, 0x1E, 0, + csra66x0_bass_treble_tlv), + SOC_DOUBLE_R_TLV("PA TREBLE GAIN", CSRA66X0_CH1_TREBLE_GAIN_CTRL_FA, + CSRA66X0_CH2_TREBLE_GAIN_CTRL_FA, 0, 0x1E, 0, + csra66x0_bass_treble_tlv), + SOC_DOUBLE_R("PA BASS_XOVER FREQ", CSRA66X0_CH1_BASS_FC_CTRL_FA, + CSRA66X0_CH2_BASS_FC_CTRL_FA, 0, 2, 0), + SOC_DOUBLE_R("PA TREBLE_XOVER FREQ", CSRA66X0_CH1_TREBLE_FC_CTRL_FA, + CSRA66X0_CH2_TREBLE_FC_CTRL_FA, 0, 2, 0), + + /* switch */ + SOC_ENUM("PA MUTE_OUTPUT SWITCH", csra66x0_mute_output_enum), + SOC_ENUM("PA DE-EMPHASIS SWITCH", csra66x0_deemp_config_enum), +}; + +static const struct snd_kcontrol_new csra_mix_switch[] = { + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) +}; + +static const struct snd_soc_dapm_widget csra66x0_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("IN"), + SND_SOC_DAPM_MIXER("MIXER", SND_SOC_NOPM, 0, 0, + csra_mix_switch, ARRAY_SIZE(csra_mix_switch)), + SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_PGA("PGA", CSRA66X0_CHIP_STATE_CTRL_FA, 0, 0, NULL, 0), + SND_SOC_DAPM_OUTPUT("SPKR"), + + SND_SOC_DAPM_SUPPLY("POWER", CSRA66X0_CHIP_STATE_CTRL_FA, + 1, 1, NULL, 0), +}; + +static const struct snd_soc_dapm_route csra66x0_dapm_routes[] = { + {"MIXER", "Switch", "IN"}, + {"DAC", NULL, "MIXER"}, + {"PGA", NULL, "DAC"}, + {"SPKR", NULL, "PGA"}, + {"SPKR", NULL, "POWER"}, +}; + +static int csra66x0_init(struct snd_soc_codec *codec, + struct csra66x0_priv *csra66x0) +{ + /* config */ + snd_soc_write(codec, CSRA66X0_CHIP_STATE_CTRL_FA, CONFIG_STATE); + /* settle time in HW is min. 500ms before proceeding */ + msleep(500); + + /* setup */ + snd_soc_write(codec, CSRA66X0_MISC_CONTROL_STATUS_0, 0x09); + snd_soc_write(codec, CSRA66X0_TEMP_PROT_BACKOFF, 0x0C); + snd_soc_write(codec, CSRA66X0_EXT_PA_PROTECT_POLARITY, 0x03); + snd_soc_write(codec, CSRA66X0_PWM_OUTPUT_CONFIG, 0xC8); + csra66x0->spk_volume_ch1 = SPK_VOLUME_M20DB; + csra66x0->spk_volume_ch2 = SPK_VOLUME_M20DB; + snd_soc_write(codec, CSRA66X0_CH1_VOLUME_0_FA, SPK_VOLUME_M20DB_LSB); + snd_soc_write(codec, CSRA66X0_CH2_VOLUME_0_FA, SPK_VOLUME_M20DB_LSB); + snd_soc_write(codec, CSRA66X0_CH1_VOLUME_1_FA, SPK_VOLUME_M20DB_MSB); + snd_soc_write(codec, CSRA66X0_CH2_VOLUME_1_FA, SPK_VOLUME_M20DB_MSB); + + snd_soc_write(codec, CSRA66X0_DEAD_TIME_CTRL, 0x0); + snd_soc_write(codec, CSRA66X0_DEAD_TIME_THRESHOLD_0, 0xE7); + snd_soc_write(codec, CSRA66X0_DEAD_TIME_THRESHOLD_1, 0x26); + snd_soc_write(codec, CSRA66X0_DEAD_TIME_THRESHOLD_2, 0x40); + + snd_soc_write(codec, CSRA66X0_MIN_MODULATION_PULSE_WIDTH, 0x7A); + snd_soc_write(codec, CSRA66X0_CH1_HARD_CLIP_THRESH, 0x00); + snd_soc_write(codec, CSRA66X0_CH2_HARD_CLIP_THRESH, 0x00); + + snd_soc_write(codec, CSRA66X0_CH1_DCA_THRESH, 0x40); + snd_soc_write(codec, CSRA66X0_CH2_DCA_THRESH, 0x40); + snd_soc_write(codec, CSRA66X0_DCA_ATTACK_RATE, 0x00); + snd_soc_write(codec, CSRA66X0_DCA_RELEASE_RATE, 0x00); + + if (csra66x0->irq) { + snd_soc_write(codec, CSRA66X0_PIO0_SELECT, 0x1); + if (csra66x0->irq_active_low) + snd_soc_write(codec, CSRA66X0_IRQ_OUTPUT_POLARITY, 0x0); + else + snd_soc_write(codec, CSRA66X0_IRQ_OUTPUT_POLARITY, 0x1); + + snd_soc_write(codec, CSRA66X0_IRQ_OUTPUT_ENABLE, 0x01); + } else { + snd_soc_write(codec, CSRA66X0_IRQ_OUTPUT_ENABLE, 0x00); + } + /* settle time in HW is min. 500ms before slave initializing */ + msleep(500); + return 0; +} + +static int csra66x0_soc_probe(struct snd_soc_codec *codec) +{ + struct csra66x0_priv *csra66x0 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm; + char name[50]; + + if (csra66x0->in_cluster) { + dapm = snd_soc_codec_get_dapm(codec); + dev_dbg(codec->dev, "%s: setting %s to codec %s\n", + __func__, codec->component.name_prefix, + codec->component.name); + snd_soc_write(codec, CSRA66X0_CHIP_STATE_CTRL_FA, + CONFIG_STATE); + /* settle time in HW is min. 500ms before proceeding */ + msleep(500); + snd_soc_write(codec, CSRA66X0_PIO7_SELECT, 0x04); + snd_soc_write(codec, CSRA66X0_PIO8_SELECT, 0x04); + if (csra66x0->is_master) { + /* Master specific config */ + snd_soc_write(codec, CSRA66X0_PIO_PULL_EN0, 0xFF); + snd_soc_write(codec, CSRA66X0_PIO_PULL_DIR0, 0x80); + snd_soc_write(codec, CSRA66X0_PIO_PULL_EN1, 0x01); + snd_soc_write(codec, CSRA66X0_PIO_PULL_DIR1, 0x01); + } else { + /* Slave specific config */ + snd_soc_write(codec, CSRA66X0_PIO_PULL_EN0, 0x7F); + snd_soc_write(codec, CSRA66X0_PIO_PULL_EN1, 0x00); + } + snd_soc_write(codec, CSRA66X0_DCA_CTRL, 0x05); + if (dapm->component) { + strlcpy(name, dapm->component->name_prefix, + sizeof(name)); + strlcat(name, " IN", sizeof(name)); + snd_soc_dapm_ignore_suspend(dapm, name); + strlcpy(name, dapm->component->name_prefix, + sizeof(name)); + strlcat(name, " SPKR", sizeof(name)); + snd_soc_dapm_ignore_suspend(dapm, name); + } + } + + csra66x0->codec = codec; + + /* common configuration */ + csra66x0_init(codec, csra66x0); + return 0; +} + +static int csra66x0_soc_remove(struct snd_soc_codec *codec) +{ + snd_soc_write(codec, CSRA66X0_CHIP_STATE_CTRL_FA, STDBY_STATE); + return 0; +} + +static int csra66x0_soc_suspend(struct snd_soc_codec *codec) +{ + u16 state_reg = snd_soc_read(codec, CSRA66X0_CHIP_STATE_CTRL_FA) & 0xFC; + + snd_soc_write(codec, CSRA66X0_CHIP_STATE_CTRL_FA, state_reg | + STDBY_STATE); + return 0; +} + +static int csra66x0_soc_resume(struct snd_soc_codec *codec) +{ + u16 state_reg = snd_soc_read(codec, CSRA66X0_CHIP_STATE_CTRL_FA) & 0xFC; + + snd_soc_write(codec, CSRA66X0_CHIP_STATE_CTRL_FA, state_reg | + RUN_STATE); + return 0; +} + +static struct regmap *csra66x0_get_regmap(struct device *dev) +{ + struct csra66x0_priv *csra66x0_ctrl = dev_get_drvdata(dev); + + if (!csra66x0_ctrl) + return NULL; + return csra66x0_ctrl->regmap; +} + +static struct snd_soc_codec_driver soc_codec_drv_csra66x0 = { + .probe = csra66x0_soc_probe, + .remove = csra66x0_soc_remove, + .suspend = csra66x0_soc_suspend, + .resume = csra66x0_soc_resume, + .get_regmap = csra66x0_get_regmap, + .component_driver = { + .controls = csra66x0_snd_controls, + .num_controls = ARRAY_SIZE(csra66x0_snd_controls), + .dapm_widgets = csra66x0_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(csra66x0_dapm_widgets), + .dapm_routes = csra66x0_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(csra66x0_dapm_routes), + }, +}; + +static struct regmap_config csra66x0_regmap_config = { + .reg_bits = 16, + .val_bits = 8, + .cache_type = REGCACHE_RBTREE, + .reg_defaults = csra66x0_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(csra66x0_reg_defaults), + .max_register = CSRA66X0_MAX_REGISTER_ADDR, + .volatile_reg = csra66x0_volatile_register, + .writeable_reg = csra66x0_writeable_registers, + .readable_reg = csra66x0_readable_registers, +}; + +static irqreturn_t csra66x0_irq(int irq, void *data) +{ + struct csra66x0_priv *csra66x0 = (struct csra66x0_priv *) data; + struct snd_soc_codec *codec = csra66x0->codec; + u16 val; + + /* Treat interrupt before codec is initialized as spurious */ + if (codec == NULL) + return IRQ_NONE; + + dev_dbg(codec->dev, "%s: csra66x0_interrupt\n", __func__); + + /* fault indication */ + val = snd_soc_read(codec, CSRA66X0_IRQ_OUTPUT_STATUS_FA) & 0x1; + if (val) { + val = snd_soc_read(codec, CSRA66X0_FAULT_STATUS_FA); + if (val & FAULT_STATUS_INTERNAL) + dev_dbg(codec->dev, "%s: FAULT_STATUS_INTERNAL 0x%X\n", + __func__, val); + if (val & FAULT_STATUS_OTP_INTEGRITY) + dev_dbg(codec->dev, "%s: FAULT_STATUS_OTP_INTEGRITY 0x%X\n", + __func__, val); + if (val & FAULT_STATUS_PADS2) + dev_dbg(codec->dev, "%s: FAULT_STATUS_PADS2 0x%X\n", + __func__, val); + if (val & FAULT_STATUS_SMPS) + dev_dbg(codec->dev, "%s: FAULT_STATUS_SMPS 0x%X\n", + __func__, val); + if (val & FAULT_STATUS_TEMP) + dev_dbg(codec->dev, "%s: FAULT_STATUS_TEMP 0x%X\n", + __func__, val); + if (val & FAULT_STATUS_PROTECT) + dev_dbg(codec->dev, "%s: FAULT_STATUS_PROTECT 0x%X\n", + __func__, val); + + /* clear fault state and re-init */ + snd_soc_write(codec, CSRA66X0_FAULT_STATUS_FA, 0x00); + csra66x0_init(codec, csra66x0); + } else { + return IRQ_NONE; + } + return IRQ_HANDLED; +}; + +static const struct of_device_id csra66x0_of_match[] = { + { .compatible = "qcom,csra66x0", }, + { } +}; +MODULE_DEVICE_TABLE(of, csra66x0_of_match); + +#if IS_ENABLED(CONFIG_I2C) +static int csra66x0_i2c_probe(struct i2c_client *client_i2c, + const struct i2c_device_id *id) +{ + struct csra66x0_priv *csra66x0; + int ret, irq_trigger; + + csra66x0 = devm_kzalloc(&client_i2c->dev, sizeof(struct csra66x0_priv), + GFP_KERNEL); + if (csra66x0 == NULL) + return -ENOMEM; + + csra66x0->regmap = devm_regmap_init_i2c(client_i2c, + &csra66x0_regmap_config); + if (IS_ERR(csra66x0->regmap)) { + ret = PTR_ERR(csra66x0->regmap); + dev_err(&client_i2c->dev, + "%s %d: Failed to allocate register map for I2C device: %d\n", + __func__, __LINE__, ret); + return ret; + } + + i2c_set_clientdata(client_i2c, csra66x0); + + /* get data from device tree */ + if (client_i2c->dev.of_node) { + /* cluster of multiple devices */ + ret = of_property_read_u32( + client_i2c->dev.of_node, "qcom,csra-cluster", + &csra66x0->in_cluster); + if (ret) { + dev_info(&client_i2c->dev, + "%s: qcom,csra-cluster property not defined in DT\n", __func__); + csra66x0->in_cluster = 0; + } + /* master or slave device */ + ret = of_property_read_u32( + client_i2c->dev.of_node, "qcom,csra-cluster-master", + &csra66x0->is_master); + if (ret) { + dev_info(&client_i2c->dev, + "%s: qcom,csra-cluster-master property not defined in DT\n", __func__); + csra66x0->is_master = 0; + } + + /* gpio setup for vreg */ + csra66x0->vreg_gpio = of_get_named_gpio(client_i2c->dev.of_node, + "qcom,csra-vreg-en-gpio", 0); + if (!gpio_is_valid(csra66x0->vreg_gpio)) { + dev_err(&client_i2c->dev, "%s: %s property is not found %d\n", + __func__, "qcom,csra-vreg-en-gpio", + csra66x0->vreg_gpio); + return -ENODEV; + } + dev_dbg(&client_i2c->dev, "%s: vreg_en gpio %d\n", __func__, + csra66x0->vreg_gpio); + ret = gpio_request(csra66x0->vreg_gpio, dev_name(&client_i2c->dev)); + if (ret) { + if (ret == -EBUSY) { + /* GPIO was already requested */ + dev_dbg(&client_i2c->dev, + "%s: gpio %d is already set\n", + __func__, csra66x0->vreg_gpio); + } else { + dev_err(&client_i2c->dev, "%s: Failed to request gpio %d, err: %d\n", + __func__, csra66x0->vreg_gpio, ret); + } + } else { + gpio_direction_output(csra66x0->vreg_gpio, 1); + gpio_set_value(csra66x0->vreg_gpio, 1); + } + + /* register interrupt handle */ + if (client_i2c->irq) { + csra66x0->irq = client_i2c->irq; + /* interrupt polarity */ + ret = of_property_read_u32( + client_i2c->dev.of_node, "irq-active-low", + &csra66x0->irq_active_low); + if (ret) { + dev_info(&client_i2c->dev, + "%s: irq-active-low property not defined in DT\n", __func__); + csra66x0->irq_active_low = 0; + } + if (csra66x0->irq_active_low) + irq_trigger = IRQF_TRIGGER_LOW; + else + irq_trigger = IRQF_TRIGGER_HIGH; + + ret = devm_request_threaded_irq(&client_i2c->dev, + csra66x0->irq, NULL, csra66x0_irq, + irq_trigger | IRQF_ONESHOT, + "csra66x0_irq", csra66x0); + if (ret) { + dev_err(&client_i2c->dev, + "%s: Failed to request IRQ %d: %d\n", + __func__, csra66x0->irq, ret); + csra66x0->irq = 0; + } + } + } + + /* register codec */ + ret = snd_soc_register_codec(&client_i2c->dev, + &soc_codec_drv_csra66x0, NULL, 0); + if (ret != 0) { + dev_err(&client_i2c->dev, "%s %d: Failed to register CODEC: %d\n", + __func__, __LINE__, ret); + if (gpio_is_valid(csra66x0->vreg_gpio)) { + gpio_set_value(csra66x0->vreg_gpio, 0); + gpio_free(csra66x0->vreg_gpio); + } + return ret; + } + return 0; +} + +static int csra66x0_i2c_remove(struct i2c_client *i2c_client) +{ + struct csra66x0_priv *csra66x0 = i2c_get_clientdata(i2c_client); + + if (csra66x0) { + if (gpio_is_valid(csra66x0->vreg_gpio)) { + gpio_set_value(csra66x0->vreg_gpio, 0); + gpio_free(csra66x0->vreg_gpio); + } + } + snd_soc_unregister_codec(&i2c_client->dev); + return 0; +} + +static const struct i2c_device_id csra66x0_i2c_id[] = { + { "csra66x0", 0}, + { } +}; +MODULE_DEVICE_TABLE(i2c, csra66x0_i2c_id); + +static struct i2c_driver csra66x0_i2c_driver = { + .probe = csra66x0_i2c_probe, + .remove = csra66x0_i2c_remove, + .id_table = csra66x0_i2c_id, + .driver = { + .name = "csra66x0", + .owner = THIS_MODULE, + .of_match_table = csra66x0_of_match + }, +}; +#endif + +static int __init csra66x0_codec_init(void) +{ + int ret = 0; +#if IS_ENABLED(CONFIG_I2C) + ret = i2c_add_driver(&csra66x0_i2c_driver); + if (ret != 0) + pr_err("%s: Failed to register CSRA66X0 I2C driver, ret = %d\n", + __func__, ret); +#endif + return ret; +} +module_init(csra66x0_codec_init); + +static void __exit csra66x0_codec_exit(void) +{ +#if IS_ENABLED(CONFIG_I2C) + i2c_del_driver(&csra66x0_i2c_driver); +#endif +} +module_exit(csra66x0_codec_exit); + +MODULE_DESCRIPTION("CSRA66X0 Codec driver"); +MODULE_LICENSE("GPL v2"); diff --git a/asoc/codecs/csra66x0/csra66x0.h b/asoc/codecs/csra66x0/csra66x0.h new file mode 100644 index 0000000000..43d83d847a --- /dev/null +++ b/asoc/codecs/csra66x0/csra66x0.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _CSRA66X0_H +#define _CSRA66X0_H + +/* CSRA66X0 register addresses */ +#define CSRA66X0_BASE 0x7000 + +#define CSRA66X0_AUDIO_IF_RX_CONFIG1 (CSRA66X0_BASE+0x0000) +#define CSRA66X0_AUDIO_IF_RX_CONFIG2 (CSRA66X0_BASE+0x0001) +#define CSRA66X0_AUDIO_IF_RX_CONFIG3 (CSRA66X0_BASE+0x0002) +#define CSRA66X0_AUDIO_IF_TX_EN (CSRA66X0_BASE+0x0003) +#define CSRA66X0_AUDIO_IF_TX_CONFIG1 (CSRA66X0_BASE+0x0004) +#define CSRA66X0_AUDIO_IF_TX_CONFIG2 (CSRA66X0_BASE+0x0005) +#define CSRA66X0_I2C_DEVICE_ADDRESS (CSRA66X0_BASE+0x0006) +#define CSRA66X0_CHIP_ID_FA (CSRA66X0_BASE+0x0007) +#define CSRA66X0_ROM_VER_FA (CSRA66X0_BASE+0x0008) +#define CSRA66X0_CHIP_REV_0_FA (CSRA66X0_BASE+0x0009) +#define CSRA66X0_CHIP_REV_1_FA (CSRA66X0_BASE+0x000A) +#define CSRA66X0_CH1_MIX_SEL (CSRA66X0_BASE+0x000B) +#define CSRA66X0_CH2_MIX_SEL (CSRA66X0_BASE+0x000C) +#define CSRA66X0_CH1_SAMPLE1_SCALE_0 (CSRA66X0_BASE+0x000D) +#define CSRA66X0_CH1_SAMPLE1_SCALE_1 (CSRA66X0_BASE+0x000E) +#define CSRA66X0_CH1_SAMPLE3_SCALE_0 (CSRA66X0_BASE+0x000F) +#define CSRA66X0_CH1_SAMPLE3_SCALE_1 (CSRA66X0_BASE+0x0010) +#define CSRA66X0_CH1_SAMPLE5_SCALE_0 (CSRA66X0_BASE+0x0011) +#define CSRA66X0_CH1_SAMPLE5_SCALE_1 (CSRA66X0_BASE+0x0012) +#define CSRA66X0_CH1_SAMPLE7_SCALE_0 (CSRA66X0_BASE+0x0013) +#define CSRA66X0_CH1_SAMPLE7_SCALE_1 (CSRA66X0_BASE+0x0014) +#define CSRA66X0_CH1_SAMPLE2_SCALE_0 (CSRA66X0_BASE+0x0015) +#define CSRA66X0_CH1_SAMPLE2_SCALE_1 (CSRA66X0_BASE+0x0016) +#define CSRA66X0_CH1_SAMPLE4_SCALE_0 (CSRA66X0_BASE+0x0017) +#define CSRA66X0_CH1_SAMPLE4_SCALE_1 (CSRA66X0_BASE+0x0018) +#define CSRA66X0_CH1_SAMPLE6_SCALE_0 (CSRA66X0_BASE+0x0019) +#define CSRA66X0_CH1_SAMPLE6_SCALE_1 (CSRA66X0_BASE+0x001A) +#define CSRA66X0_CH1_SAMPLE8_SCALE_0 (CSRA66X0_BASE+0x001B) +#define CSRA66X0_CH1_SAMPLE8_SCALE_1 (CSRA66X0_BASE+0x001C) +#define CSRA66X0_CH2_SAMPLE1_SCALE_0 (CSRA66X0_BASE+0x001D) +#define CSRA66X0_CH2_SAMPLE1_SCALE_1 (CSRA66X0_BASE+0x001E) +#define CSRA66X0_CH2_SAMPLE3_SCALE_0 (CSRA66X0_BASE+0x001F) +#define CSRA66X0_CH2_SAMPLE3_SCALE_1 (CSRA66X0_BASE+0x0020) +#define CSRA66X0_CH2_SAMPLE5_SCALE_0 (CSRA66X0_BASE+0x0021) +#define CSRA66X0_CH2_SAMPLE5_SCALE_1 (CSRA66X0_BASE+0x0022) +#define CSRA66X0_CH2_SAMPLE7_SCALE_0 (CSRA66X0_BASE+0x0023) +#define CSRA66X0_CH2_SAMPLE7_SCALE_1 (CSRA66X0_BASE+0x0024) +#define CSRA66X0_CH2_SAMPLE2_SCALE_0 (CSRA66X0_BASE+0x0025) +#define CSRA66X0_CH2_SAMPLE2_SCALE_1 (CSRA66X0_BASE+0x0026) +#define CSRA66X0_CH2_SAMPLE4_SCALE_0 (CSRA66X0_BASE+0x0027) +#define CSRA66X0_CH2_SAMPLE4_SCALE_1 (CSRA66X0_BASE+0x0028) +#define CSRA66X0_CH2_SAMPLE6_SCALE_0 (CSRA66X0_BASE+0x0029) +#define CSRA66X0_CH2_SAMPLE6_SCALE_1 (CSRA66X0_BASE+0x002A) +#define CSRA66X0_CH2_SAMPLE8_SCALE_0 (CSRA66X0_BASE+0x002B) +#define CSRA66X0_CH2_SAMPLE8_SCALE_1 (CSRA66X0_BASE+0x002C) +#define CSRA66X0_VOLUME_CONFIG_FA (CSRA66X0_BASE+0x002D) +#define CSRA66X0_STARTUP_DELAY_FA (CSRA66X0_BASE+0x002E) +#define CSRA66X0_CH1_VOLUME_0_FA (CSRA66X0_BASE+0x002F) +#define CSRA66X0_CH1_VOLUME_1_FA (CSRA66X0_BASE+0x0030) +#define CSRA66X0_CH2_VOLUME_0_FA (CSRA66X0_BASE+0x0031) +#define CSRA66X0_CH2_VOLUME_1_FA (CSRA66X0_BASE+0x0032) +#define CSRA66X0_QUAD_ENC_COUNT_0_FA (CSRA66X0_BASE+0x0033) +#define CSRA66X0_QUAD_ENC_COUNT_1_FA (CSRA66X0_BASE+0x0034) +#define CSRA66X0_SOFT_CLIP_CONFIG (CSRA66X0_BASE+0x0035) +#define CSRA66X0_CH1_HARD_CLIP_THRESH (CSRA66X0_BASE+0x0036) +#define CSRA66X0_CH2_HARD_CLIP_THRESH (CSRA66X0_BASE+0x0037) +#define CSRA66X0_SOFT_CLIP_THRESH (CSRA66X0_BASE+0x0038) +#define CSRA66X0_DS_ENABLE_THRESH_0 (CSRA66X0_BASE+0x0039) +#define CSRA66X0_DS_ENABLE_THRESH_1 (CSRA66X0_BASE+0x003A) +#define CSRA66X0_DS_TARGET_COUNT_0 (CSRA66X0_BASE+0x003B) +#define CSRA66X0_DS_TARGET_COUNT_1 (CSRA66X0_BASE+0x003C) +#define CSRA66X0_DS_TARGET_COUNT_2 (CSRA66X0_BASE+0x003D) +#define CSRA66X0_DS_DISABLE_THRESH_0 (CSRA66X0_BASE+0x003E) +#define CSRA66X0_DS_DISABLE_THRESH_1 (CSRA66X0_BASE+0x003F) +#define CSRA66X0_DCA_CTRL (CSRA66X0_BASE+0x0040) +#define CSRA66X0_CH1_DCA_THRESH (CSRA66X0_BASE+0x0041) +#define CSRA66X0_CH2_DCA_THRESH (CSRA66X0_BASE+0x0042) +#define CSRA66X0_DCA_ATTACK_RATE (CSRA66X0_BASE+0x0043) +#define CSRA66X0_DCA_RELEASE_RATE (CSRA66X0_BASE+0x0044) +#define CSRA66X0_CH1_OUTPUT_INVERT_EN (CSRA66X0_BASE+0x0045) +#define CSRA66X0_CH2_OUTPUT_INVERT_EN (CSRA66X0_BASE+0x0046) +#define CSRA66X0_CH1_176P4K_DELAY (CSRA66X0_BASE+0x0047) +#define CSRA66X0_CH2_176P4K_DELAY (CSRA66X0_BASE+0x0048) +#define CSRA66X0_CH1_192K_DELAY (CSRA66X0_BASE+0x0049) +#define CSRA66X0_CH2_192K_DELAY (CSRA66X0_BASE+0x004A) +#define CSRA66X0_DEEMP_CONFIG_FA (CSRA66X0_BASE+0x004B) +#define CSRA66X0_CH1_TREBLE_GAIN_CTRL_FA (CSRA66X0_BASE+0x004C) +#define CSRA66X0_CH2_TREBLE_GAIN_CTRL_FA (CSRA66X0_BASE+0x004D) +#define CSRA66X0_CH1_TREBLE_FC_CTRL_FA (CSRA66X0_BASE+0x004E) +#define CSRA66X0_CH2_TREBLE_FC_CTRL_FA (CSRA66X0_BASE+0x004F) +#define CSRA66X0_CH1_BASS_GAIN_CTRL_FA (CSRA66X0_BASE+0x0050) +#define CSRA66X0_CH2_BASS_GAIN_CTRL_FA (CSRA66X0_BASE+0x0051) +#define CSRA66X0_CH1_BASS_FC_CTRL_FA (CSRA66X0_BASE+0x0052) +#define CSRA66X0_CH2_BASS_FC_CTRL_FA (CSRA66X0_BASE+0x0053) +#define CSRA66X0_FILTER_SEL_8K (CSRA66X0_BASE+0x0054) +#define CSRA66X0_FILTER_SEL_11P025K (CSRA66X0_BASE+0x0055) +#define CSRA66X0_FILTER_SEL_16K (CSRA66X0_BASE+0x0056) +#define CSRA66X0_FILTER_SEL_22P05K (CSRA66X0_BASE+0x0057) +#define CSRA66X0_FILTER_SEL_32K (CSRA66X0_BASE+0x0058) +#define CSRA66X0_FILTER_SEL_44P1K_48K (CSRA66X0_BASE+0x0059) +#define CSRA66X0_FILTER_SEL_88P2K_96K (CSRA66X0_BASE+0x005A) +#define CSRA66X0_FILTER_SEL_176P4K_192K (CSRA66X0_BASE+0x005B) +/* RESERVED (CSRA66X0_BASE+0x005C) */ +#define CSRA66X0_USER_DSP_CTRL (CSRA66X0_BASE+0x005D) +#define CSRA66X0_TEST_TONE_CTRL (CSRA66X0_BASE+0x005E) +#define CSRA66X0_TEST_TONE_FREQ_0 (CSRA66X0_BASE+0x005F) +#define CSRA66X0_TEST_TONE_FREQ_1 (CSRA66X0_BASE+0x0060) +#define CSRA66X0_TEST_TONE_FREQ_2 (CSRA66X0_BASE+0x0061) +#define CSRA66X0_AUDIO_RATE_CTRL_FA (CSRA66X0_BASE+0x0062) +#define CSRA66X0_MODULATION_INDEX_CTRL (CSRA66X0_BASE+0x0063) +#define CSRA66X0_MODULATION_INDEX_COUNT (CSRA66X0_BASE+0x0064) +#define CSRA66X0_MIN_MODULATION_PULSE_WIDTH (CSRA66X0_BASE+0x0065) +#define CSRA66X0_DEAD_TIME_CTRL (CSRA66X0_BASE+0x0066) +#define CSRA66X0_DEAD_TIME_THRESHOLD_0 (CSRA66X0_BASE+0x0067) +#define CSRA66X0_DEAD_TIME_THRESHOLD_1 (CSRA66X0_BASE+0x0068) +#define CSRA66X0_DEAD_TIME_THRESHOLD_2 (CSRA66X0_BASE+0x0069) +#define CSRA66X0_CH1_LOW_SIDE_DLY (CSRA66X0_BASE+0x006A) +#define CSRA66X0_CH2_LOW_SIDE_DLY (CSRA66X0_BASE+0x006B) +#define CSRA66X0_SPECTRUM_CTRL (CSRA66X0_BASE+0x006C) +/* RESERVED (CSRA66X0_BASE+0x006D) */ +#define CSRA66X0_SPECTRUM_SPREAD_CTRL (CSRA66X0_BASE+0x006E) +/* RESERVED (CSRA66X0_BASE+0x006F) */ +/* ... */ +/* RESERVED (CSRA66X0_BASE+0x007C) */ +#define CSRA66X0_EXT_PA_PROTECT_POLARITY (CSRA66X0_BASE+0x007D) +#define CSRA66X0_TEMP0_BACKOFF_COMP_VALUE (CSRA66X0_BASE+0x007E) +#define CSRA66X0_TEMP0_SHUTDOWN_COMP_VALUE (CSRA66X0_BASE+0x007F) +#define CSRA66X0_TEMP1_BACKOFF_COMP_VALUE (CSRA66X0_BASE+0x0080) +#define CSRA66X0_TEMP1_SHUTDOWN_COMP_VALUE (CSRA66X0_BASE+0x0081) +#define CSRA66X0_TEMP_PROT_BACKOFF (CSRA66X0_BASE+0x0082) +#define CSRA66X0_TEMP_READ0_FA (CSRA66X0_BASE+0x0083) +#define CSRA66X0_TEMP_READ1_FA (CSRA66X0_BASE+0x0084) +#define CSRA66X0_CHIP_STATE_CTRL_FA (CSRA66X0_BASE+0x0085) +/* RESERVED (CSRA66X0_BASE+0x0086) */ +#define CSRA66X0_PWM_OUTPUT_CONFIG (CSRA66X0_BASE+0x0087) +#define CSRA66X0_MISC_CONTROL_STATUS_0 (CSRA66X0_BASE+0x0088) +#define CSRA66X0_MISC_CONTROL_STATUS_1_FA (CSRA66X0_BASE+0x0089) +#define CSRA66X0_PIO0_SELECT (CSRA66X0_BASE+0x008A) +#define CSRA66X0_PIO1_SELECT (CSRA66X0_BASE+0x008B) +#define CSRA66X0_PIO2_SELECT (CSRA66X0_BASE+0x008C) +#define CSRA66X0_PIO3_SELECT (CSRA66X0_BASE+0x008D) +#define CSRA66X0_PIO4_SELECT (CSRA66X0_BASE+0x008E) +#define CSRA66X0_PIO5_SELECT (CSRA66X0_BASE+0x008F) +#define CSRA66X0_PIO6_SELECT (CSRA66X0_BASE+0x0090) +#define CSRA66X0_PIO7_SELECT (CSRA66X0_BASE+0x0091) +#define CSRA66X0_PIO8_SELECT (CSRA66X0_BASE+0x0092) +#define CSRA66X0_PIO_DIRN0 (CSRA66X0_BASE+0x0093) +#define CSRA66X0_PIO_DIRN1 (CSRA66X0_BASE+0x0094) +#define CSRA66X0_PIO_PULL_EN0 (CSRA66X0_BASE+0x0095) +#define CSRA66X0_PIO_PULL_EN1 (CSRA66X0_BASE+0x0096) +#define CSRA66X0_PIO_PULL_DIR0 (CSRA66X0_BASE+0x0097) +#define CSRA66X0_PIO_PULL_DIR1 (CSRA66X0_BASE+0x0098) +#define CSRA66X0_PIO_DRIVE_OUT0_FA (CSRA66X0_BASE+0x0099) +#define CSRA66X0_PIO_DRIVE_OUT1_FA (CSRA66X0_BASE+0x009A) +#define CSRA66X0_PIO_STATUS_IN0_FA (CSRA66X0_BASE+0x009B) +#define CSRA66X0_PIO_STATUS_IN1_FA (CSRA66X0_BASE+0x009C) +/* RESERVED (CSRA66X0_BASE+0x009D) */ +#define CSRA66X0_IRQ_OUTPUT_ENABLE (CSRA66X0_BASE+0x009E) +#define CSRA66X0_IRQ_OUTPUT_POLARITY (CSRA66X0_BASE+0x009F) +#define CSRA66X0_IRQ_OUTPUT_STATUS_FA (CSRA66X0_BASE+0x00A0) +#define CSRA66X0_CLIP_DCA_STATUS_FA (CSRA66X0_BASE+0x00A1) +#define CSRA66X0_CHIP_STATE_STATUS_FA (CSRA66X0_BASE+0x00A2) +#define CSRA66X0_FAULT_STATUS_FA (CSRA66X0_BASE+0x00A3) +#define CSRA66X0_OTP_STATUS_FA (CSRA66X0_BASE+0x00A4) +#define CSRA66X0_AUDIO_IF_STATUS_FA (CSRA66X0_BASE+0x00A5) +/* RESERVED (CSRA66X0_BASE+0x00A6) */ +#define CSRA66X0_DSP_SATURATION_STATUS_FA (CSRA66X0_BASE+0x00A7) +#define CSRA66X0_AUDIO_RATE_STATUS_FA (CSRA66X0_BASE+0x00A8) +/* RESERVED (CSRA66X0_BASE+0x00A9) */ +/* ... */ +/* RESERVED (CSRA66X0_BASE+0x00AB) */ +#define CSRA66X0_DISABLE_PWM_OUTPUT (CSRA66X0_BASE+0x00AC) +/* RESERVED (CSRA66X0_BASE+0x00AD) */ +/* ... */ +/* RESERVED (CSRA66X0_BASE+0x00B0) */ +#define CSRA66X0_OTP_VER_FA (CSRA66X0_BASE+0x00B1) +#define CSRA66X0_RAM_VER_FA (CSRA66X0_BASE+0x00B2) +/* RESERVED (CSRA66X0_BASE+0x00B3) */ +#define CSRA66X0_AUDIO_SATURATION_FLAGS_FA (CSRA66X0_BASE+0x00B4) +#define CSRA66X0_DCOFFSET_CHAN_1_01_FA (CSRA66X0_BASE+0x00B5) +#define CSRA66X0_DCOFFSET_CHAN_1_02_FA (CSRA66X0_BASE+0x00B6) +#define CSRA66X0_DCOFFSET_CHAN_1_03_FA (CSRA66X0_BASE+0x00B7) +#define CSRA66X0_DCOFFSET_CHAN_2_01_FA (CSRA66X0_BASE+0x00B8) +#define CSRA66X0_DCOFFSET_CHAN_2_02_FA (CSRA66X0_BASE+0x00B9) +#define CSRA66X0_DCOFFSET_CHAN_2_03_FA (CSRA66X0_BASE+0x00BA) +#define CSRA66X0_FORCED_PA_SWITCHING_CTRL (CSRA66X0_BASE+0x00BB) +#define CSRA66X0_PA_FORCE_PULSE_WIDTH (CSRA66X0_BASE+0x00BC) +#define CSRA66X0_PA_HIGH_MODULATION_CTRL_CH1 (CSRA66X0_BASE+0x00BD) +/* RESERVED (CSRA66X0_BASE+0x00BE) */ +/* RESERVED (CSRA66X0_BASE+0x00BF) */ +#define CSRA66X0_HIGH_MODULATION_THRESHOLD_LOW (CSRA66X0_BASE+0x00C0) +#define CSRA66X0_HIGH_MODULATION_THRESHOLD_HIGH (CSRA66X0_BASE+0x00C1) +/* RESERVED (CSRA66X0_BASE+0x00C2) */ +/* RESERVED (CSRA66X0_BASE+0x00C3) */ +#define CSRA66X0_PA_FREEZE_CTRL (CSRA66X0_BASE+0x00C4) +#define CSRA66X0_DCA_FREEZE_CTRL (CSRA66X0_BASE+0x00C5) +/* RESERVED (CSRA66X0_BASE+0x00C6) */ +/* ... */ +/* RESERVED (CSRA66X0_BASE+0x00FF) */ +#define CSRA66X0_MAX_REGISTER_ADDR CSRA66X0_DCA_FREEZE_CTRL + +#define EXPECTED_CSRA66X0_CHIP_ID 0x39 + +#define SPK_VOLUME_M20DB 0x119 +#define SPK_VOLUME_M20DB_LSB (SPK_VOLUME_M20DB & 0x0FF) +#define SPK_VOLUME_M20DB_MSB ((SPK_VOLUME_M20DB & 0x100)>>8) +#define SPK_VOLUME_LSB_MSK 0x00FF +#define SPK_VOLUME_MSB_MSK 0x0100 + +#define CONFIG_STATE 0x0 +#define RUN_STATE 0x1 +#define STDBY_STATE 0x2 + +#define FAULT_STATUS_INTERNAL 0x01 +#define FAULT_STATUS_OTP_INTEGRITY 0x02 +#define FAULT_STATUS_PADS2 0x04 +#define FAULT_STATUS_SMPS 0x08 +#define FAULT_STATUS_TEMP 0x10 +#define FAULT_STATUS_PROTECT 0x20 + +#endif /* _CSRA66X0_H */